From 49c44fe87c00ff0d32e35a449c62db6fca00f36a Mon Sep 17 00:00:00 2001 From: mid <> Date: Sun, 19 Jan 2025 17:29:52 +0200 Subject: [PATCH] Initial commit --- .gitea/workflows/k4.yaml | 27 + .gitmodules | 3 + Makefile | 36 + k3ex.py | 247 + physex.py | 77 + src/cwalk.c | 1479 +++++ src/cwalk.h | 498 ++ src/enet.h | 6069 ++++++++++++++++++++ src/game.c | 898 +++ src/game.h | 254 + src/gl.h | 10961 +++++++++++++++++++++++++++++++++++++ src/k3mix.c | 395 ++ src/k3mix.h | 50 + src/k4.h | 41 + src/komihash.h | 973 ++++ src/loaders.inc | 347 ++ src/luaapi.c | 3422 ++++++++++++ src/luaapi.h | 51 + src/main.c | 962 ++++ src/net.h | 206 + src/net_client.c | 287 + src/net_client.h | 8 + src/net_server.c | 344 ++ src/net_server.h | 16 + src/resman.c | 160 + src/resman.h | 46 + src/ssort.h | 25 + src/stb_image.h | 7987 +++++++++++++++++++++++++++ src/stb_image_resize.h | 2634 +++++++++ src/stoon.c | 395 ++ src/stoon.h | 64 + 31 files changed, 38962 insertions(+) create mode 100644 .gitea/workflows/k4.yaml create mode 100644 .gitmodules create mode 100644 Makefile create mode 100644 k3ex.py create mode 100644 physex.py create mode 100644 src/cwalk.c create mode 100644 src/cwalk.h create mode 100644 src/enet.h create mode 100644 src/game.c create mode 100644 src/game.h create mode 100644 src/gl.h create mode 100644 src/k3mix.c create mode 100644 src/k3mix.h create mode 100644 src/k4.h create mode 100644 src/komihash.h create mode 100644 src/loaders.inc create mode 100644 src/luaapi.c create mode 100644 src/luaapi.h create mode 100644 src/main.c create mode 100644 src/net.h create mode 100644 src/net_client.c create mode 100644 src/net_client.h create mode 100644 src/net_server.c create mode 100644 src/net_server.h create mode 100644 src/resman.c create mode 100644 src/resman.h create mode 100644 src/ssort.h create mode 100644 src/stb_image.h create mode 100644 src/stb_image_resize.h create mode 100644 src/stoon.c create mode 100644 src/stoon.h diff --git a/.gitea/workflows/k4.yaml b/.gitea/workflows/k4.yaml new file mode 100644 index 0000000..0c83597 --- /dev/null +++ b/.gitea/workflows/k4.yaml @@ -0,0 +1,27 @@ +name: k4 Build Test +run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀 +on: + push: + tags: + - 'v*' + +jobs: + do_the_build: + runs-on: debian_amd64 + steps: + - name: Check out repository code + uses: actions/checkout@v3 + with: + submodules: 'true' + - run: mkdir build build/k3 bin bin/assets + - run: CC="i686-w64-mingw32-gcc" CFLAGS="-I/usr/i686-w64-mingw32/include -I/usr/i686-w64-mingw32/include/lua5.3 -L/usr/i686-w64-mingw32/lib -Wno-error" make -B + - run: CC="i686-linux-gnu-gcc" CFLAGS="-I/usr/i686-linux-gnu/include -I/usr/i686-linux-gnu/include/lua5.3 -L/usr/i686-linux-gnu/lib -Wno-error" make -B + - run: cp /usr/lib/gcc/i686-w64-mingw32/10-win32/libgcc_s_dw2-1.dll /usr/lib/gcc/i686-w64-mingw32/10-win32/libstdc++-6.dll /usr/i686-w64-mingw32/lib/libportaudio-2.dll /usr/i686-w64-mingw32/lib/libwinpthread-1.dll bin/ + - run: cp -r /home/git/k4templateassets/* bin/assets/ + - run: zip -9r "k4${{ github.ref_name }}.zip" bin/ + - name: Create package + uses: akkuman/gitea-release-action@v1 + with: + files: |- + k4${{ github.ref_name }}.zip + - run: echo "🍏 This job's status is ${{ job.status }}." diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..20f2e39 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "k3"] + path = k3 + url = https://mid.net.ua/git/mid/k3 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..28b56ce --- /dev/null +++ b/Makefile @@ -0,0 +1,36 @@ +k4_SRCS := $(wildcard src/*.c) +k4_HDRS := $(wildcard src/*.h) +k4_OBJS := $(patsubst src/%.c, build/%.o, $(k4_SRCS)) +k4_DEPS := $(patsubst src/%.c, build/%.d, $(k4_SRCS)) + +k3_SRCS = $(wildcard k3/src/*.c) +k3_HDRS = $(wildcard k3/src/*.h) +k3_OBJS := $(patsubst k3/src/%.c, build/k3/%.o, $(k3_SRCS)) +k3_DEPS := $(patsubst k3/src/%.c, build/k3/%.d, $(k3_SRCS)) + +CFLAGS := $(CFLAGS) -Ik3/src + +ifneq (,$(findstring mingw,$(CC))) + CFLAGS := -static-libgcc -static-libstdc++ -std=gnu99 -march=pentium4 -D_WIN32_WINNT=0x600 -DENET_FEATURE_ADDRESS_MAPPING -fno-pic -no-pie -fms-extensions -fno-pie -O0 -g -gdwarf-2 -Isrc $(CFLAGS) + LIBS := -l:libglfw3.a -lopengl32 -pthread -lm -l:libode.a -l:libvorbisfile.a -l:libvorbis.a -l:libogg.a -lportaudio -lgdi32 -lws2_32 -lwinmm -lstdc++ -lole32 -lsetupapi -lhid -l:liblua5.3.a $(LIBS) +else + CFLAGS := -march=opteron $(SAN) -std=gnu99 -DENET_FEATURE_ADDRESS_MAPPING -fms-extensions -fno-pic -no-pie -fno-pie -O0 -g -Isrc $(CFLAGS) + LIBS := -lglfw3 -pthread -ldl -lm -lode -lstdc++ -llua5.3 -lvorbis -lvorbisfile -lportaudio $(LIBS) +endif + +CFLAGS := $(CFLAGS) -DLOCALHOST_ONLY -Dk3_IRREGULAR_SHADOWS + +build/k3/%.o: k3/src/%.c + $(CC) $(CFLAGS) -MMD -o $@ -c $< + +build/%.o: src/%.c + $(CC) $(CFLAGS) -MMD -o $@ -c $< + +k4: $(k4_OBJS) $(k3_OBJS) + $(CC) $(CFLAGS) -o bin/k4 $(k4_OBJS) $(k3_OBJS) $(LIBS) + +include $(k4_DEPS) +include $(k3_DEPS) + +$(k4_DEPS): ; +$(k3_DEPS): ; diff --git a/k3ex.py b/k3ex.py new file mode 100644 index 0000000..34b62e7 --- /dev/null +++ b/k3ex.py @@ -0,0 +1,247 @@ +import bpy, bmesh, struct, collections, bpy_extras, re +from collections import namedtuple + +AxisChange = bpy_extras.io_utils.axis_conversion(to_forward = "-Z", to_up = "Y").to_4x4() + +def ShowMessageBox(message = "", title = "Message Box", icon = 'INFO'): + def draw(self, context): + self.layout.label(text=message) + bpy.context.window_manager.popup_menu(draw, title = title, icon = icon) + +def normalize_weights(items): + items = list(items) + items.sort(key = lambda x: x[1], reverse = True) + items = items[:4] + while len(items) < 4: items.append((0, 0)) + normFac = sum([w[1] for w in items]) + return tuple([(w[0], w[1] / normFac) for w in items]) + +V = namedtuple("V", ["pos", "nrm", "uv", "weights", "col"]) + +def vert2tup(bm, loop): + return V( + pos = (loop.vert.co.x, loop.vert.co.y, loop.vert.co.z), + nrm = (loop.vert.normal.x, loop.vert.normal.y, loop.vert.normal.z), + uv = (loop[bm.loops.layers.uv.active].uv[0], 1 - loop[bm.loops.layers.uv.active].uv[1]) if bm.loops.layers.uv.active is not None else (0, 0), + weights = normalize_weights(loop.vert[bm.verts.layers.deform.active].items()) if bm.verts.layers.deform.active is not None else ((0, 0), (0, 0), (0, 0), (0, 0)), + col = tuple(list(loop[bm.loops.layers.color.active]) + [1.0]) if bm.loops.layers.color.active is not None else None + ) + +patrn = re.compile(r"^\s*(\d+)\s*\(\s*(\d+)\s*\@\s*(\d+)\s*\)\s*$") + +def write_some_data(context, filepath, doExportEverything): + if doExportEverything: + bpy.ops.object.select_all(action = "DESELECT") + objs = [o for o in context.scene.objects if o.layers[0] and o.type == "MESH"] + for o in objs: + o.select = True + bpy.ops.object.duplicate() + objs = [o for o in context.scene.objects if o.select] + bpy.ops.object.select_all(action = "DESELECT") + for o in objs: + o.select = True + context.scene.objects.active = o + for m in o.modifiers: + bpy.ops.object.modifier_apply(modifier=m.name) + o.select = False + for o in objs: + o.select = True + bpy.ops.object.join() + context.scene.objects.active = [o for o in context.scene.objects if o.select][0] + bpy.ops.object.transform_apply(location = True, scale = True, rotation = True) + + arm = None + obj = None + if context.active_object.type == "ARMATURE": + arm = context.active_object + obj = arm.children[0] + elif context.active_object.type == "MESH": + obj = context.active_object + arm = obj.parent + + if not doExportEverything: + bpy.ops.object.select_all(action = "DESELECT") + obj.select = True + bpy.ops.object.duplicate() + obj = context.scene.objects.active = [o for o in context.scene.objects if o.select][0] + for m in obj.modifiers: + if m.type != "ARMATURE": + bpy.ops.object.modifier_apply(modifier=m.name) + + bm = bmesh.new() + bm.from_mesh(obj.data) + bmesh.ops.triangulate(bm, faces = bm.faces) + + vertdict = collections.OrderedDict() + for face in bm.faces: + for loop in face.loops: + vertdict.setdefault(vert2tup(bm, loop), None) + + vertkeys = list(vertdict.keys()) + + tris = [[] for i in range(len(obj.data.materials))] + for face in bm.faces: + for loop in face.loops: + tris[face.material_index].append(vertkeys.index(vert2tup(bm, loop))) + + bm.verts.ensure_lookup_table() + bm.faces.ensure_lookup_table() + + print("Beginning to write..") + + with open(filepath, "wb") as out: + out.write(b"K3M ") + + out.write(struct.pack("I", len(vertdict))) + out.write(struct.pack("I", 3 * len(bm.faces))) + + out.write(struct.pack("B", len(arm.data.bones) if arm else 0)) + + print("A") + colorsEnabled = any([v.col is not None for v in vertdict.keys()]) + print("B", colorsEnabled) + + out.write(struct.pack("B", 1 if colorsEnabled else 0)) + + out.write(struct.pack("H", len([a for a in bpy.data.actions if patrn.match(a.name)]) if arm else 0)) + + print("Wrote header.") + + if arm: + dabones = list(arm.data.bones) + for b in dabones: + m = (AxisChange * b.matrix_local).inverted() + for c in range(4): + out.write(struct.pack("4f", m.col[c][0], m.col[c][1], m.col[c][2], m.col[c][3])) + for b in dabones: + out.write(struct.pack("B", dabones.index(b.parent) if b.parent else 255)) + + for v in vertdict.keys(): + out.write(struct.pack("3f", v[0][0], v[0][2], -v[0][1])) + + for v in vertdict.keys(): + invFactor = max(abs(v[1][0]), max(abs(v[1][1]), abs(v[1][2]))) + out.write(struct.pack("3b", round(v[1][0] * 127 / invFactor), round(v[1][2] * 127 / invFactor), round(-v[1][1] * 127 / invFactor))) + + for v in vertdict.keys(): + out.write(struct.pack("2f", v[2][0], v[2][1])) + + for v in vertdict.keys(): + out.write(struct.pack("4B", v[3][0][0], v[3][1][0], v[3][2][0], v[3][3][0])) + + for v in vertdict.keys(): + out.write(struct.pack("4H", round(65535 * v[3][0][1]), round(65535 * v[3][1][1]), round(65535 * v[3][2][1]), round(65535 * v[3][3][1]))) + + if colorsEnabled: + for v in vertdict.keys(): + out.write(struct.pack("4B", int(255 * v.col[0]), int(255 * v.col[1]), int(255 * v.col[2]), int(255 * v.col[3]))) + + for mat in tris: + for idx in mat: + out.write(struct.pack("H", idx)) + + out.write(struct.pack("H", len(tris))) + + offset = 0 + for i, mat in enumerate(tris): + out.write(struct.pack("2H", offset, len(mat))) + out.write(obj.material_slots[i].name.encode("UTF-8")) + out.write(b"\0") + offset += len(mat) + + if arm: + actions = [a for a in bpy.data.actions if patrn.match(a.name)] + actions.sort(key = lambda a: int(patrn.match(a.name).group(1))) + + for action in actions: + matched = patrn.match(action.name) + + arm.animation_data.action = action + + id, framecount, fps = int(matched.group(1)), int(matched.group(2)), int(matched.group(3)) + + out.write(struct.pack("4H", id, framecount, fps, 0)) + + for f in range(framecount): + bpy.context.scene.frame_set(1 + int(f * context.scene.render.fps / fps)) + bpy.context.scene.update() + for bone in arm.pose.bones: + matrix = bone.matrix + if bone.parent: + matrix = bone.parent.matrix.inverted() * matrix + else: + matrix = AxisChange * matrix + translation, rotation, scale = matrix.decompose() + if rotation.w <= 0: rotation = -rotation + out.write(struct.pack("4f", translation.x, translation.y, translation.z, 1)) + out.write(struct.pack("4f", rotation.x, rotation.y, rotation.z, rotation.w)) + + bpy.ops.object.select_all(action = "DESELECT") + obj.select = True + context.scene.objects.active = obj + bpy.ops.object.delete() + + return {'FINISHED'} + + +# ExportHelper is a helper class, defines filename and +# invoke() function which calls the file selector. +from bpy_extras.io_utils import ExportHelper +from bpy.props import StringProperty, BoolProperty, EnumProperty +from bpy.types import Operator + + +class ExportSomeData(Operator, ExportHelper): + """This appears in the tooltip of the operator and in the generated docs""" + bl_idname = "export_k3m.some_data" # important since its how bpy.ops.import_test.some_data is constructed + bl_label = "Export" + + # ExportHelper mixin class uses this + filename_ext = ".k3m" + + filter_glob = StringProperty( + default="*.k3m", + options={'HIDDEN'}, + maxlen=255, # Max internal buffer length, longer would be clamped. + ) + + # List of operator properties, the attributes will be assigned + # to the class instance from the operator settings before calling. + use_setting = BoolProperty( + name="Export Everything in Layer", + description="", + default=False, + ) + + type = EnumProperty( + name="Example Enum", + description="Choose between two items", + items=(('OPT_A', "First Option", "Description one"), + ('OPT_B', "Second Option", "Description two")), + default='OPT_A', + ) + + def execute(self, context): + return write_some_data(context, self.filepath, self.use_setting) + + +# Only needed if you want to add into a dynamic menu +def menu_func_export(self, context): + self.layout.operator(ExportSomeData.bl_idname, text="k3 Model") + + +def register(): + bpy.utils.register_class(ExportSomeData) + bpy.types.INFO_MT_file_export.append(menu_func_export) + + +def unregister(): + bpy.utils.unregister_class(ExportSomeData) + bpy.types.INFO_MT_file_export.remove(menu_func_export) + + +if __name__ == "__main__": + register() + + # test call + #bpy.ops.export_test.some_data('INVOKE_DEFAULT') diff --git a/physex.py b/physex.py new file mode 100644 index 0000000..17bae13 --- /dev/null +++ b/physex.py @@ -0,0 +1,77 @@ +import bpy, bmesh, struct + + +def write_some_data(context, filepath, use_some_setting): + f = open(filepath, "wb") + + bm = bmesh.new() + bm.from_object(context.active_object, context.scene) + bmesh.ops.triangulate(bm, faces = bm.faces) + + for face in bm.faces: + for loop in face.loops: + f.write(struct.pack("3f", loop.vert.co.x, loop.vert.co.z, -loop.vert.co.y)) + + f.close() + + return {'FINISHED'} + + +# ExportHelper is a helper class, defines filename and +# invoke() function which calls the file selector. +from bpy_extras.io_utils import ExportHelper +from bpy.props import StringProperty, BoolProperty, EnumProperty +from bpy.types import Operator + + +class ExportSomeData(Operator, ExportHelper): + """This appears in the tooltip of the operator and in the generated docs""" + bl_idname = "export_trimesh.some_data" # important since its how bpy.ops.import_test.some_data is constructed + bl_label = "Export Triangle Mesh" + + # ExportHelper mixin class uses this + filename_ext = ".phys" + + filter_glob = StringProperty( + default="*.phys", + options={'HIDDEN'}, + maxlen=255, # Max internal buffer length, longer would be clamped. + ) + + # List of operator properties, the attributes will be assigned + # to the class instance from the operator settings before calling. + use_setting = BoolProperty( + name="Example Boolean", + description="Example Tooltip", + default=True, + ) + + type = EnumProperty( + name="Example Enum", + description="Choose between two items", + items=(('OPT_A', "First Option", "Description one"), + ('OPT_B', "Second Option", "Description two")), + default='OPT_A', + ) + + def execute(self, context): + return write_some_data(context, self.filepath, self.use_setting) + + +# Only needed if you want to add into a dynamic menu +def menu_func_export(self, context): + self.layout.operator(ExportSomeData.bl_idname, text="Export Raw Triangle Mesh") + + +def register(): + bpy.utils.register_class(ExportSomeData) + bpy.types.INFO_MT_file_export.append(menu_func_export) + + +def unregister(): + bpy.utils.unregister_class(ExportSomeData) + bpy.types.INFO_MT_file_export.remove(menu_func_export) + + +if __name__ == "__main__": + register() diff --git a/src/cwalk.c b/src/cwalk.c new file mode 100644 index 0000000..005bac0 --- /dev/null +++ b/src/cwalk.c @@ -0,0 +1,1479 @@ +#include +#include +#include "cwalk.h" +#include +#include +#include + +/** + * We try to default to a different path style depending on the operating + * system. So this should detect whether we should use windows or unix paths. + */ +#if defined(WIN32) || defined(_WIN32) || \ + defined(__WIN32) && !defined(__CYGWIN__) +static enum cwk_path_style path_style = CWK_STYLE_WINDOWS; +#else +static enum cwk_path_style path_style = CWK_STYLE_UNIX; +#endif + +/** + * This is a list of separators used in different styles. Windows can read + * multiple separators, but it generally outputs just a backslash. The output + * will always use the first character for the output. + */ +static const char *separators[] = { + "\\/", // CWK_STYLE_WINDOWS + "/" // CWK_STYLE_UNIX +}; + +/** + * A joined path represents multiple path strings which are concatenated, but + * not (necessarily) stored in contiguous memory. The joined path allows to + * iterate over the segments as if it was one piece of path. + */ +struct cwk_segment_joined +{ + struct cwk_segment segment; + const char **paths; + size_t path_index; +}; + +static size_t cwk_path_output_sized(char *buffer, size_t buffer_size, + size_t position, const char *str, size_t length) +{ + size_t amount_written; + + // First we determine the amount which we can write to the buffer. There are + // three cases. In the first case we have enough to store the whole string in + // it. In the second one we can only store a part of it, and in the third we + // have no space left. + if (buffer_size > position + length) { + amount_written = length; + } else if (buffer_size > position) { + amount_written = buffer_size - position; + } else { + amount_written = 0; + } + + // If we actually want to write out something we will do that here. We will + // always append a '\0', this way we are guaranteed to have a valid string at + // all times. + if (amount_written > 0) { + memmove(&buffer[position], str, amount_written); + } + + // Return the theoretical length which would have been written when everything + // would have fit in the buffer. + return length; +} + +static size_t cwk_path_output_current(char *buffer, size_t buffer_size, + size_t position) +{ + // We output a "current" directory, which is a single character. This + // character is currently not style dependant. + return cwk_path_output_sized(buffer, buffer_size, position, ".", 1); +} + +static size_t cwk_path_output_back(char *buffer, size_t buffer_size, + size_t position) +{ + // We output a "back" directory, which ahs two characters. This + // character is currently not style dependant. + return cwk_path_output_sized(buffer, buffer_size, position, "..", 2); +} + +static size_t cwk_path_output_separator(char *buffer, size_t buffer_size, + size_t position) +{ + // We output a separator, which is a single character. + return cwk_path_output_sized(buffer, buffer_size, position, + separators[path_style], 1); +} + +static size_t cwk_path_output_dot(char *buffer, size_t buffer_size, + size_t position) +{ + // We output a dot, which is a single character. This is used for extensions. + return cwk_path_output_sized(buffer, buffer_size, position, ".", 1); +} + +static size_t cwk_path_output(char *buffer, size_t buffer_size, size_t position, + const char *str) +{ + size_t length; + + // This just does a sized output internally, but first measuring the + // null-terminated string. + length = strlen(str); + return cwk_path_output_sized(buffer, buffer_size, position, str, length); +} + +static void cwk_path_terminate_output(char *buffer, size_t buffer_size, + size_t pos) +{ + if (buffer_size > 0) { + if (pos >= buffer_size) { + buffer[buffer_size - 1] = '\0'; + } else { + buffer[pos] = '\0'; + } + } +} + +static bool cwk_path_is_string_equal(const char *first, const char *second, + size_t first_size, size_t second_size) +{ + bool are_both_separators; + + // The two strings are not equal if the sizes are not equal. + if (first_size != second_size) { + return false; + } + + // If the path style is UNIX, we will compare case sensitively. This can be + // done easily using strncmp. + if (path_style == CWK_STYLE_UNIX) { + return strncmp(first, second, first_size) == 0; + } + + // However, if this is windows we will have to compare case insensitively. + // Since there is no standard method to do that we will have to do it on our + // own. + while (*first && *second && first_size > 0) { + // We can consider the string to be not equal if the two lowercase + // characters are not equal. The two chars may also be separators, which + // means they would be equal. + are_both_separators = strchr(separators[path_style], *first) != NULL && + strchr(separators[path_style], *second) != NULL; + + if (tolower(*first) != tolower(*second) && !are_both_separators) { + return false; + } + + first++; + second++; + + --first_size; + } + + // The string must be equal since they both have the same length and all the + // characters are the same. + return true; +} + +static const char *cwk_path_find_next_stop(const char *c) +{ + // We just move forward until we find a '\0' or a separator, which will be our + // next "stop". + while (*c != '\0' && !cwk_path_is_separator(c)) { + ++c; + } + + // Return the pointer of the next stop. + return c; +} + +static const char *cwk_path_find_previous_stop(const char *begin, const char *c) +{ + // We just move back until we find a separator or reach the beginning of the + // path, which will be our previous "stop". + while (c > begin && !cwk_path_is_separator(c)) { + --c; + } + + // Return the pointer to the previous stop. We have to return the first + // character after the separator, not on the separator itself. + if (cwk_path_is_separator(c)) { + return c + 1; + } else { + return c; + } +} + +static bool cwk_path_get_first_segment_without_root(const char *path, + const char *segments, struct cwk_segment *segment) +{ + // Let's remember the path. We will move the path pointer afterwards, that's + // why this has to be done first. + segment->path = path; + segment->segments = segments; + segment->begin = segments; + segment->end = segments; + segment->size = 0; + + // Now let's check whether this is an empty string. An empty string has no + // segment it could use. + if (*segments == '\0') { + return false; + } + + // If the string starts with separators, we will jump over those. If there is + // only a slash and a '\0' after it, we can't determine the first segment + // since there is none. + while (cwk_path_is_separator(segments)) { + ++segments; + if (*segments == '\0') { + return false; + } + } + + // So this is the beginning of our segment. + segment->begin = segments; + + // Now let's determine the end of the segment, which we do by moving the path + // pointer further until we find a separator. + segments = cwk_path_find_next_stop(segments); + + // And finally, calculate the size of the segment by subtracting the position + // from the end. + segment->size = (size_t)(segments - segment->begin); + segment->end = segments; + + // Tell the caller that we found a segment. + return true; +} + +static bool cwk_path_get_last_segment_without_root(const char *path, + struct cwk_segment *segment) +{ + // Now this is fairly similar to the normal algorithm, however, it will assume + // that there is no root in the path. So we grab the first segment at this + // position, assuming there is no root. + if (!cwk_path_get_first_segment_without_root(path, path, segment)) { + return false; + } + + // Now we find our last segment. The segment struct of the caller + // will contain the last segment, since the function we call here will not + // change the segment struct when it reaches the end. + while (cwk_path_get_next_segment(segment)) { + // We just loop until there is no other segment left. + } + + return true; +} + +static bool cwk_path_get_first_segment_joined(const char **paths, + struct cwk_segment_joined *sj) +{ + bool result; + + // Prepare the first segment. We position the joined segment on the first path + // and assign the path array to the struct. + sj->path_index = 0; + sj->paths = paths; + + // We loop through all paths until we find one which has a segment. The result + // is stored in a variable, so we can let the caller know whether we found one + // or not. + result = false; + while (paths[sj->path_index] != NULL && + (result = cwk_path_get_first_segment(paths[sj->path_index], + &sj->segment)) == false) { + ++sj->path_index; + } + + return result; +} + +static bool cwk_path_get_next_segment_joined(struct cwk_segment_joined *sj) +{ + bool result; + + if (sj->paths[sj->path_index] == NULL) { + // We reached already the end of all paths, so there is no other segment + // left. + return false; + } else if (cwk_path_get_next_segment(&sj->segment)) { + // There was another segment on the current path, so we are good to + // continue. + return true; + } + + // We try to move to the next path which has a segment available. We must at + // least move one further since the current path reached the end. + result = false; + + do { + ++sj->path_index; + + // And we obviously have to stop this loop if there are no more paths left. + if (sj->paths[sj->path_index] == NULL) { + break; + } + + // Grab the first segment of the next path and determine whether this path + // has anything useful in it. There is one more thing we have to consider + // here - for the first time we do this we want to skip the root, but + // afterwards we will consider that to be part of the segments. + result = cwk_path_get_first_segment_without_root(sj->paths[sj->path_index], + sj->paths[sj->path_index], &sj->segment); + + } while (!result); + + // Finally, report the result back to the caller. + return result; +} + +static bool cwk_path_get_previous_segment_joined(struct cwk_segment_joined *sj) +{ + bool result; + + if (*sj->paths == NULL) { + // It's possible that there is no initialized segment available in the + // struct since there are no paths. In that case we can return false, since + // there is no previous segment. + return false; + } else if (cwk_path_get_previous_segment(&sj->segment)) { + // Now we try to get the previous segment from the current path. If we can + // do that successfully, we can let the caller know that we found one. + return true; + } + + result = false; + + do { + // We are done once we reached index 0. In that case there are no more + // segments left. + if (sj->path_index == 0) { + break; + } + + // There is another path which we have to inspect. So we decrease the path + // index. + --sj->path_index; + + // If this is the first path we will have to consider that this path might + // include a root, otherwise we just treat is as a segment. + if (sj->path_index == 0) { + result = cwk_path_get_last_segment(sj->paths[sj->path_index], + &sj->segment); + } else { + result = cwk_path_get_last_segment_without_root(sj->paths[sj->path_index], + &sj->segment); + } + + } while (!result); + + return result; +} + +static bool cwk_path_segment_back_will_be_removed(struct cwk_segment_joined *sj) +{ + enum cwk_segment_type type; + int counter; + + // We are handling back segments here. We must verify how many back segments + // and how many normal segments come before this one to decide whether we keep + // or remove it. + + // The counter determines how many normal segments are our current segment, + // which will popped off before us. If the counter goes above zero it means + // that our segment will be popped as well. + counter = 0; + + // We loop over all previous segments until we either reach the beginning, + // which means our segment will not be dropped or the counter goes above zero. + while (cwk_path_get_previous_segment_joined(sj)) { + + // Now grab the type. The type determines whether we will increase or + // decrease the counter. We don't handle a CWK_CURRENT frame here since it + // has no influence. + type = cwk_path_get_segment_type(&sj->segment); + if (type == CWK_NORMAL) { + // This is a normal segment. The normal segment will increase the counter + // since it neutralizes one back segment. If we go above zero we can + // return immediately. + ++counter; + if (counter > 0) { + return true; + } + } else if (type == CWK_BACK) { + // A CWK_BACK segment will reduce the counter by one. We can not remove a + // back segment as long we are not above zero since we don't have the + // opposite normal segment which we would remove. + --counter; + } + } + + // We never got a count larger than zero, so we will keep this segment alive. + return false; +} + +static bool cwk_path_segment_normal_will_be_removed( + struct cwk_segment_joined *sj) +{ + enum cwk_segment_type type; + int counter; + + // The counter determines how many segments are above our current segment, + // which will popped off before us. If the counter goes below zero it means + // that our segment will be popped as well. + counter = 0; + + // We loop over all following segments until we either reach the end, which + // means our segment will not be dropped or the counter goes below zero. + while (cwk_path_get_next_segment_joined(sj)) { + + // First, grab the type. The type determines whether we will increase or + // decrease the counter. We don't handle a CWK_CURRENT frame here since it + // has no influence. + type = cwk_path_get_segment_type(&sj->segment); + if (type == CWK_NORMAL) { + // This is a normal segment. The normal segment will increase the counter + // since it will be removed by a "../" before us. + ++counter; + } else if (type == CWK_BACK) { + // A CWK_BACK segment will reduce the counter by one. If we are below zero + // we can return immediately. + --counter; + if (counter < 0) { + return true; + } + } + } + + // We never got a negative count, so we will keep this segment alive. + return false; +} + +static bool +cwk_path_segment_will_be_removed(const struct cwk_segment_joined *sj, + bool absolute) +{ + enum cwk_segment_type type; + struct cwk_segment_joined sjc; + + // We copy the joined path so we don't need to modify it. + sjc = *sj; + + // First we check whether this is a CWK_CURRENT or CWK_BACK segment, since + // those will always be dropped. + type = cwk_path_get_segment_type(&sj->segment); + if (type == CWK_CURRENT || (type == CWK_BACK && absolute)) { + return true; + } else if (type == CWK_BACK) { + return cwk_path_segment_back_will_be_removed(&sjc); + } else { + return cwk_path_segment_normal_will_be_removed(&sjc); + } +} + +static bool +cwk_path_segment_joined_skip_invisible(struct cwk_segment_joined *sj, + bool absolute) +{ + while (cwk_path_segment_will_be_removed(sj, absolute)) { + if (!cwk_path_get_next_segment_joined(sj)) { + return false; + } + } + + return true; +} + +static void cwk_path_get_root_windows(const char *path, size_t *length) +{ + const char *c; + bool is_device_path; + + // We can not determine the root if this is an empty string. So we set the + // root to NULL and the length to zero and cancel the whole thing. + c = path; + *length = 0; + if (!*c) { + return; + } + + // Now we have to verify whether this is a windows network path (UNC), which + // we will consider our root. + if (cwk_path_is_separator(c)) { + ++c; + + // Check whether the path starts with a single backslash, which means this + // is not a network path - just a normal path starting with a backslash. + if (!cwk_path_is_separator(c)) { + // Okay, this is not a network path but we still use the backslash as a + // root. + ++(*length); + return; + } + + // A device path is a path which starts with "\\." or "\\?". A device path + // can be a UNC path as well, in which case it will take up one more + // segment. So, this is a network or device path. Skip the previous + // separator. Now we need to determine whether this is a device path. We + // might advance one character here if the server name starts with a '?' or + // a '.', but that's fine since we will search for a separator afterwards + // anyway. + ++c; + is_device_path = (*c == '?' || *c == '.') && cwk_path_is_separator(++c); + if (is_device_path) { + // That's a device path, and the root must be either "\\.\" or "\\?\" + // which is 4 characters long. (at least that's how Windows + // GetFullPathName behaves.) + *length = 4; + return; + } + + // We will grab anything up to the next stop. The next stop might be a '\0' + // or another separator. That will be the server name. + c = cwk_path_find_next_stop(c); + + // If this is a separator and not the end of a string we wil have to include + // it. However, if this is a '\0' we must not skip it. + while (cwk_path_is_separator(c)) { + ++c; + } + + // We are now skipping the shared folder name, which will end after the + // next stop. + c = cwk_path_find_next_stop(c); + + // Then there might be a separator at the end. We will include that as well, + // it will mark the path as absolute. + if (cwk_path_is_separator(c)) { + ++c; + } + + // Finally, calculate the size of the root. + *length = (size_t)(c - path); + return; + } + + // Move to the next and check whether this is a colon. + if (*++c == ':') { + *length = 2; + + // Now check whether this is a backslash (or slash). If it is not, we could + // assume that the next character is a '\0' if it is a valid path. However, + // we will not assume that - since ':' is not valid in a path it must be a + // mistake by the caller than. We will try to understand it anyway. + if (cwk_path_is_separator(++c)) { + *length = 3; + } + } +} + +static void cwk_path_get_root_unix(const char *path, size_t *length) +{ + // The slash of the unix path represents the root. There is no root if there + // is no slash. + if (cwk_path_is_separator(path)) { + *length = 1; + } else { + *length = 0; + } +} + +static bool cwk_path_is_root_absolute(const char *path, size_t length) +{ + // This is definitely not absolute if there is no root. + if (length == 0) { + return false; + } + + // If there is a separator at the end of the root, we can safely consider this + // to be an absolute path. + return cwk_path_is_separator(&path[length - 1]); +} + +static void cwk_path_fix_root(char *buffer, size_t buffer_size, size_t length) +{ + size_t i; + + // This only affects windows. + if (path_style != CWK_STYLE_WINDOWS) { + return; + } + + // Make sure we are not writing further than we are actually allowed to. + if (length > buffer_size) { + length = buffer_size; + } + + // Replace all forward slashes with backwards slashes. Since this is windows + // we can't have any forward slashes in the root. + for (i = 0; i < length; ++i) { + if (cwk_path_is_separator(&buffer[i])) { + buffer[i] = *separators[CWK_STYLE_WINDOWS]; + } + } +} + +static size_t cwk_path_join_and_normalize_multiple(const char **paths, + char *buffer, size_t buffer_size) +{ + size_t pos; + bool absolute, has_segment_output; + struct cwk_segment_joined sj; + + // We initialize the position after the root, which should get us started. + cwk_path_get_root(paths[0], &pos); + + // Determine whether the path is absolute or not. We need that to determine + // later on whether we can remove superfluous "../" or not. + absolute = cwk_path_is_root_absolute(paths[0], pos); + + // First copy the root to the output. After copying, we will normalize the + // root. + cwk_path_output_sized(buffer, buffer_size, 0, paths[0], pos); + cwk_path_fix_root(buffer, buffer_size, pos); + + // So we just grab the first segment. If there is no segment we will always + // output a "/", since we currently only support absolute paths here. + if (!cwk_path_get_first_segment_joined(paths, &sj)) { + goto done; + } + + // Let's assume that we don't have any segment output for now. We will toggle + // this flag once there is some output. + has_segment_output = false; + + do { + // Check whether we have to drop this segment because of resolving a + // relative path or because it is a CWK_CURRENT segment. + if (cwk_path_segment_will_be_removed(&sj, absolute)) { + continue; + } + + // We add a separator if we previously wrote a segment. The last segment + // must not have a trailing separator. This must happen before the segment + // output, since we would override the null terminating character with + // reused buffers if this was done afterwards. + if (has_segment_output) { + pos += cwk_path_output_separator(buffer, buffer_size, pos); + } + + // Remember that we have segment output, so we can handle the trailing slash + // later on. This is necessary since we might have segments but they are all + // removed. + has_segment_output = true; + + // Write out the segment but keep in mind that we need to follow the + // buffer size limitations. That's why we use the path output functions + // here. + pos += cwk_path_output_sized(buffer, buffer_size, pos, sj.segment.begin, + sj.segment.size); + } while (cwk_path_get_next_segment_joined(&sj)); + + // Remove the trailing slash, but only if we have segment output. We don't + // want to remove anything from the root. + if (!has_segment_output && pos == 0) { + // This may happen if the path is absolute and all segments have been + // removed. We can not have an empty output - and empty output means we stay + // in the current directory. So we will output a ".". + assert(absolute == false); + pos += cwk_path_output_current(buffer, buffer_size, pos); + } + + // We must append a '\0' in any case, unless the buffer size is zero. If the + // buffer size is zero, which means we can not. +done: + cwk_path_terminate_output(buffer, buffer_size, pos); + + // And finally let our caller know about the total size of the normalized + // path. + return pos; +} + +size_t cwk_path_get_absolute(const char *base, const char *path, char *buffer, + size_t buffer_size) +{ + size_t i; + const char *paths[4]; + + // The basename should be an absolute path if the caller is using the API + // correctly. However, he might not and in that case we will append a fake + // root at the beginning. + if (cwk_path_is_absolute(base)) { + i = 0; + } else if (path_style == CWK_STYLE_WINDOWS) { + paths[0] = "\\"; + i = 1; + } else { + paths[0] = "/"; + i = 1; + } + + if (cwk_path_is_absolute(path)) { + // If the submitted path is not relative the base path becomes irrelevant. + // We will only normalize the submitted path instead. + paths[i++] = path; + paths[i] = NULL; + } else { + // Otherwise we append the relative path to the base path and normalize it. + // The result will be a new absolute path. + paths[i++] = base; + paths[i++] = path; + paths[i] = NULL; + } + + // Finally join everything together and normalize it. + return cwk_path_join_and_normalize_multiple(paths, buffer, buffer_size); +} + +static void cwk_path_skip_segments_until_diverge(struct cwk_segment_joined *bsj, + struct cwk_segment_joined *osj, bool absolute, bool *base_available, + bool *other_available) +{ + // Now looping over all segments until they start to diverge. A path may + // diverge if two segments are not equal or if one path reaches the end. + do { + + // Check whether there is anything available after we skip everything which + // is invisible. We do that for both paths, since we want to let the caller + // know which path has some trailing segments after they diverge. + *base_available = cwk_path_segment_joined_skip_invisible(bsj, absolute); + *other_available = cwk_path_segment_joined_skip_invisible(osj, absolute); + + // We are done if one or both of those paths reached the end. They either + // diverge or both reached the end - but in both cases we can not continue + // here. + if (!*base_available || !*other_available) { + break; + } + + // Compare the content of both segments. We are done if they are not equal, + // since they diverge. + if (!cwk_path_is_string_equal(bsj->segment.begin, osj->segment.begin, + bsj->segment.size, osj->segment.size)) { + break; + } + + // We keep going until one of those segments reached the end. The next + // segment might be invisible, but we will check for that in the beginning + // of the loop once again. + *base_available = cwk_path_get_next_segment_joined(bsj); + *other_available = cwk_path_get_next_segment_joined(osj); + } while (*base_available && *other_available); +} + +size_t cwk_path_get_relative(const char *base_directory, const char *path, + char *buffer, size_t buffer_size) +{ + size_t pos, base_root_length, path_root_length; + bool absolute, base_available, other_available, has_output; + const char *base_paths[2], *other_paths[2]; + struct cwk_segment_joined bsj, osj; + + pos = 0; + + // First we compare the roots of those two paths. If the roots are not equal + // we can't continue, since there is no way to get a relative path from + // different roots. + cwk_path_get_root(base_directory, &base_root_length); + cwk_path_get_root(path, &path_root_length); + if (base_root_length != path_root_length || + !cwk_path_is_string_equal(base_directory, path, base_root_length, + path_root_length)) { + cwk_path_terminate_output(buffer, buffer_size, pos); + return pos; + } + + // Verify whether this is an absolute path. We need to know that since we can + // remove all back-segments if it is. + absolute = cwk_path_is_root_absolute(base_directory, base_root_length); + + // Initialize our joined segments. This will allow us to use the internal + // functions to skip until diverge and invisible. We only have one path in + // them though. + base_paths[0] = base_directory; + base_paths[1] = NULL; + other_paths[0] = path; + other_paths[1] = NULL; + cwk_path_get_first_segment_joined(base_paths, &bsj); + cwk_path_get_first_segment_joined(other_paths, &osj); + + // Okay, now we skip until the segments diverge. We don't have anything to do + // with the segments which are equal. + cwk_path_skip_segments_until_diverge(&bsj, &osj, absolute, &base_available, + &other_available); + + // Assume there is no output until we have got some. We will need this + // information later on to remove trailing slashes or alternatively output a + // current-segment. + has_output = false; + + // So if we still have some segments left in the base path we will now output + // a back segment for all of them. + if (base_available) { + do { + // Skip any invisible segment. We don't care about those and we don't need + // to navigate back because of them. + if (!cwk_path_segment_joined_skip_invisible(&bsj, absolute)) { + break; + } + + // Toggle the flag if we have output. We need to remember that, since we + // want to remove the trailing slash. + has_output = true; + + // Output the back segment and a separator. No need to worry about the + // superfluous segment since it will be removed later on. + pos += cwk_path_output_back(buffer, buffer_size, pos); + pos += cwk_path_output_separator(buffer, buffer_size, pos); + } while (cwk_path_get_next_segment_joined(&bsj)); + } + + // And if we have some segments available of the target path we will output + // all of those. + if (other_available) { + do { + // Again, skip any invisible segments since we don't need to navigate into + // them. + if (!cwk_path_segment_joined_skip_invisible(&osj, absolute)) { + break; + } + + // Toggle the flag if we have output. We need to remember that, since we + // want to remove the trailing slash. + has_output = true; + + // Output the current segment and a separator. No need to worry about the + // superfluous segment since it will be removed later on. + pos += cwk_path_output_sized(buffer, buffer_size, pos, osj.segment.begin, + osj.segment.size); + pos += cwk_path_output_separator(buffer, buffer_size, pos); + } while (cwk_path_get_next_segment_joined(&osj)); + } + + // If we have some output by now we will have to remove the trailing slash. We + // simply do that by moving back one character. The terminate output function + // will then place the '\0' on this position. Otherwise, if there is no + // output, we will have to output a "current directory", since the target path + // points to the base path. + if (has_output) { + --pos; + } else { + pos += cwk_path_output_current(buffer, buffer_size, pos); + } + + // Finally, we can terminate the output - which means we place a '\0' at the + // current position or at the end of the buffer. + cwk_path_terminate_output(buffer, buffer_size, pos); + + return pos; +} + +size_t cwk_path_join(const char *path_a, const char *path_b, char *buffer, + size_t buffer_size) +{ + const char *paths[3]; + + // This is simple. We will just create an array with the two paths which we + // wish to join. + paths[0] = path_a; + paths[1] = path_b; + paths[2] = NULL; + + // And then call the join and normalize function which will do the hard work + // for us. + return cwk_path_join_and_normalize_multiple(paths, buffer, buffer_size); +} + +size_t cwk_path_join_multiple(const char **paths, char *buffer, + size_t buffer_size) +{ + // We can just call the internal join and normalize function for this one, + // since it will handle everything. + return cwk_path_join_and_normalize_multiple(paths, buffer, buffer_size); +} + +void cwk_path_get_root(const char *path, size_t *length) +{ + // We use a different implementation here based on the configuration of the + // library. + if (path_style == CWK_STYLE_WINDOWS) { + cwk_path_get_root_windows(path, length); + } else { + cwk_path_get_root_unix(path, length); + } +} + +size_t cwk_path_change_root(const char *path, const char *new_root, + char *buffer, size_t buffer_size) +{ + const char *tail; + size_t root_length, path_length, tail_length, new_root_length, new_path_size; + + // First we need to determine the actual size of the root which we will + // change. + cwk_path_get_root(path, &root_length); + + // Now we determine the sizes of the new root and the path. We need that to + // determine the size of the part after the root (the tail). + new_root_length = strlen(new_root); + path_length = strlen(path); + + // Okay, now we calculate the position of the tail and the length of it. + tail = path + root_length; + tail_length = path_length - root_length; + + // We first output the tail and then the new root, that's because the source + // path and the buffer may be overlapping. This way the root will not + // overwrite the tail. + cwk_path_output_sized(buffer, buffer_size, new_root_length, tail, + tail_length); + cwk_path_output_sized(buffer, buffer_size, 0, new_root, new_root_length); + + // Finally we calculate the size o the new path and terminate the output with + // a '\0'. + new_path_size = tail_length + new_root_length; + cwk_path_terminate_output(buffer, buffer_size, new_path_size); + + return new_path_size; +} + +bool cwk_path_is_absolute(const char *path) +{ + size_t length; + + // We grab the root of the path. This root does not include the first + // separator of a path. + cwk_path_get_root(path, &length); + + // Now we can determine whether the root is absolute or not. + return cwk_path_is_root_absolute(path, length); +} + +bool cwk_path_is_relative(const char *path) +{ + // The path is relative if it is not absolute. + return !cwk_path_is_absolute(path); +} + +void cwk_path_get_basename(const char *path, const char **basename, + size_t *length) +{ + struct cwk_segment segment; + + // We get the last segment of the path. The last segment will contain the + // basename if there is any. If there are no segments we will set the basename + // to NULL and the length to 0. + if (!cwk_path_get_last_segment(path, &segment)) { + *basename = NULL; + if (length) { + *length = 0; + } + return; + } + + // Now we can just output the segment contents, since that's our basename. + // There might be trailing separators after the basename, but the size does + // not include those. + *basename = segment.begin; + if (length) { + *length = segment.size; + } +} + +size_t cwk_path_change_basename(const char *path, const char *new_basename, + char *buffer, size_t buffer_size) +{ + struct cwk_segment segment; + size_t pos, root_size, new_basename_size; + + // First we try to get the last segment. We may only have a root without any + // segments, in which case we will create one. + if (!cwk_path_get_last_segment(path, &segment)) { + + // So there is no segment in this path. First we grab the root and output + // that. We are not going to modify the root in any way. + cwk_path_get_root(path, &root_size); + pos = cwk_path_output_sized(buffer, buffer_size, 0, path, root_size); + + // We have to trim the separators from the beginning of the new basename. + // This is quite easy to do. + while (cwk_path_is_separator(new_basename)) { + ++new_basename; + } + + // Now we measure the length of the new basename, this is a two step + // process. First we find the '\0' character at the end of the string. + new_basename_size = 0; + while (new_basename[new_basename_size]) { + ++new_basename_size; + } + + // And then we trim the separators at the end of the basename until we reach + // the first valid character. + while (new_basename_size > 0 && + cwk_path_is_separator(&new_basename[new_basename_size - 1])) { + --new_basename_size; + } + + // Now we will output the new basename after the root. + pos += cwk_path_output_sized(buffer, buffer_size, pos, new_basename, + new_basename_size); + + // And finally terminate the output and return the total size of the path. + cwk_path_terminate_output(buffer, buffer_size, pos); + return pos; + } + + // If there is a last segment we can just forward this call, which is fairly + // easy. + return cwk_path_change_segment(&segment, new_basename, buffer, buffer_size); +} + +void cwk_path_get_dirname(const char *path, size_t *length) +{ + struct cwk_segment segment; + + // We get the last segment of the path. The last segment will contain the + // basename if there is any. If there are no segments we will set the length + // to 0. + if (!cwk_path_get_last_segment(path, &segment)) { + *length = 0; + return; + } + + // We can now return the length from the beginning of the string up to the + // beginning of the last segment. + *length = (size_t)(segment.begin - path); +} + +bool cwk_path_get_extension(const char *path, const char **extension, + size_t *length) +{ + struct cwk_segment segment; + const char *c; + + // We get the last segment of the path. The last segment will contain the + // extension if there is any. + if (!cwk_path_get_last_segment(path, &segment)) { + return false; + } + + // Now we search for a dot within the segment. If there is a dot, we consider + // the rest of the segment the extension. We do this from the end towards the + // beginning, since we want to find the last dot. + for (c = segment.end; c >= segment.begin; --c) { + if (*c == '.') { + // Okay, we found an extension. We can stop looking now. + *extension = c; + *length = (size_t)(segment.end - c); + return true; + } + } + + // We couldn't find any extension. + return false; +} + +bool cwk_path_has_extension(const char *path) +{ + const char *extension; + size_t length; + + // We just wrap the get_extension call which will then do the work for us. + return cwk_path_get_extension(path, &extension, &length); +} + +size_t cwk_path_change_extension(const char *path, const char *new_extension, + char *buffer, size_t buffer_size) +{ + struct cwk_segment segment; + const char *c, *old_extension; + size_t pos, root_size, trail_size, new_extension_size; + + // First we try to get the last segment. We may only have a root without any + // segments, in which case we will create one. + if (!cwk_path_get_last_segment(path, &segment)) { + + // So there is no segment in this path. First we grab the root and output + // that. We are not going to modify the root in any way. If there is no + // root, this will end up with a root size 0, and nothing will be written. + cwk_path_get_root(path, &root_size); + pos = cwk_path_output_sized(buffer, buffer_size, 0, path, root_size); + + // Add a dot if the submitted value doesn't have any. + if (*new_extension != '.') { + pos += cwk_path_output_dot(buffer, buffer_size, pos); + } + + // And finally terminate the output and return the total size of the path. + pos += cwk_path_output(buffer, buffer_size, pos, new_extension); + cwk_path_terminate_output(buffer, buffer_size, pos); + return pos; + } + + // Now we seek the old extension in the last segment, which we will replace + // with the new one. If there is no old extension, it will point to the end of + // the segment. + old_extension = segment.end; + for (c = segment.begin; c < segment.end; ++c) { + if (*c == '.') { + old_extension = c; + } + } + + pos = cwk_path_output_sized(buffer, buffer_size, 0, segment.path, + (size_t)(old_extension - segment.path)); + + // If the new extension starts with a dot, we will skip that dot. We always + // output exactly one dot before the extension. If the extension contains + // multiple dots, we will output those as part of the extension. + if (*new_extension == '.') { + ++new_extension; + } + + // We calculate the size of the new extension, including the dot, in order to + // output the trail - which is any part of the path coming after the + // extension. We must output this first, since the buffer may overlap with the + // submitted path - and it would be overridden by longer extensions. + new_extension_size = strlen(new_extension) + 1; + trail_size = cwk_path_output(buffer, buffer_size, pos + new_extension_size, + segment.end); + + // Finally we output the dot and the new extension. The new extension itself + // doesn't contain the dot anymore, so we must output that first. + pos += cwk_path_output_dot(buffer, buffer_size, pos); + pos += cwk_path_output(buffer, buffer_size, pos, new_extension); + + // Now we terminate the output with a null-terminating character, but before + // we do that we must add the size of the trail to the position which we + // output before. + pos += trail_size; + cwk_path_terminate_output(buffer, buffer_size, pos); + + // And the position is our output size now. + return pos; +} + +size_t cwk_path_normalize(const char *path, char *buffer, size_t buffer_size) +{ + const char *paths[2]; + + // Now we initialize the paths which we will normalize. Since this function + // only supports submitting a single path, we will only add that one. + paths[0] = path; + paths[1] = NULL; + + return cwk_path_join_and_normalize_multiple(paths, buffer, buffer_size); +} + +size_t cwk_path_get_intersection(const char *path_base, const char *path_other) +{ + bool absolute; + size_t base_root_length, other_root_length; + const char *end; + const char *paths_base[2], *paths_other[2]; + struct cwk_segment_joined base, other; + + // We first compare the two roots. We just return zero if they are not equal. + // This will also happen to return zero if the paths are mixed relative and + // absolute. + cwk_path_get_root(path_base, &base_root_length); + cwk_path_get_root(path_other, &other_root_length); + if (!cwk_path_is_string_equal(path_base, path_other, base_root_length, + other_root_length)) { + return 0; + } + + // Configure our paths. We just have a single path in here for now. + paths_base[0] = path_base; + paths_base[1] = NULL; + paths_other[0] = path_other; + paths_other[1] = NULL; + + // So we get the first segment of both paths. If one of those paths don't have + // any segment, we will return 0. + if (!cwk_path_get_first_segment_joined(paths_base, &base) || + !cwk_path_get_first_segment_joined(paths_other, &other)) { + return base_root_length; + } + + // We now determine whether the path is absolute or not. This is required + // because if will ignore removed segments, and this behaves differently if + // the path is absolute. However, we only need to check the base path because + // we are guaranteed that both paths are either relative or absolute. + absolute = cwk_path_is_root_absolute(path_base, base_root_length); + + // We must keep track of the end of the previous segment. Initially, this is + // set to the beginning of the path. This means that 0 is returned if the + // first segment is not equal. + end = path_base + base_root_length; + + // Now we loop over both segments until one of them reaches the end or their + // contents are not equal. + do { + // We skip all segments which will be removed in each path, since we want to + // know about the true path. + if (!cwk_path_segment_joined_skip_invisible(&base, absolute) || + !cwk_path_segment_joined_skip_invisible(&other, absolute)) { + break; + } + + if (!cwk_path_is_string_equal(base.segment.begin, other.segment.begin, + base.segment.size, other.segment.size)) { + // So the content of those two segments are not equal. We will return the + // size up to the beginning. + return (size_t)(end - path_base); + } + + // Remember the end of the previous segment before we go to the next one. + end = base.segment.end; + } while (cwk_path_get_next_segment_joined(&base) && + cwk_path_get_next_segment_joined(&other)); + + // Now we calculate the length up to the last point where our paths pointed to + // the same place. + return (size_t)(end - path_base); +} + +bool cwk_path_get_first_segment(const char *path, struct cwk_segment *segment) +{ + size_t length; + const char *segments; + + // We skip the root since that's not part of the first segment. The root is + // treated as a separate entity. + cwk_path_get_root(path, &length); + segments = path + length; + + // Now, after we skipped the root we can continue and find the actual segment + // content. + return cwk_path_get_first_segment_without_root(path, segments, segment); +} + +bool cwk_path_get_last_segment(const char *path, struct cwk_segment *segment) +{ + // We first grab the first segment. This might be our last segment as well, + // but we don't know yet. There is no last segment if there is no first + // segment, so we return false in that case. + if (!cwk_path_get_first_segment(path, segment)) { + return false; + } + + // Now we find our last segment. The segment struct of the caller + // will contain the last segment, since the function we call here will not + // change the segment struct when it reaches the end. + while (cwk_path_get_next_segment(segment)) { + // We just loop until there is no other segment left. + } + + return true; +} + +bool cwk_path_get_next_segment(struct cwk_segment *segment) +{ + const char *c; + + // First we jump to the end of the previous segment. The first character must + // be either a '\0' or a separator. + c = segment->begin + segment->size; + if (*c == '\0') { + return false; + } + + // Now we skip all separator until we reach something else. We are not yet + // guaranteed to have a segment, since the string could just end afterwards. + assert(cwk_path_is_separator(c)); + do { + ++c; + } while (cwk_path_is_separator(c)); + + // If the string ends here, we can safely assume that there is no other + // segment after this one. + if (*c == '\0') { + return false; + } + + // Now we are safe to assume there is a segment. We store the beginning of + // this segment in the segment struct of the caller. + segment->begin = c; + + // And now determine the size of this segment, and store it in the struct of + // the caller as well. + c = cwk_path_find_next_stop(c); + segment->end = c; + segment->size = (size_t)(c - segment->begin); + + // Tell the caller that we found a segment. + return true; +} + +bool cwk_path_get_previous_segment(struct cwk_segment *segment) +{ + const char *c; + + // The current position might point to the first character of the path, which + // means there are no previous segments available. + c = segment->begin; + if (c <= segment->segments) { + return false; + } + + // We move towards the beginning of the path until we either reached the + // beginning or the character is no separator anymore. + do { + --c; + if (c < segment->segments) { + // So we reached the beginning here and there is no segment. So we return + // false and don't change the segment structure submitted by the caller. + return false; + } + } while (cwk_path_is_separator(c)); + + // We are guaranteed now that there is another segment, since we moved before + // the previous separator and did not reach the segment path beginning. + segment->end = c + 1; + segment->begin = cwk_path_find_previous_stop(segment->segments, c); + segment->size = (size_t)(segment->end - segment->begin); + + return true; +} + +enum cwk_segment_type cwk_path_get_segment_type( + const struct cwk_segment *segment) +{ + // We just make a string comparison with the segment contents and return the + // appropriate type. + if (strncmp(segment->begin, ".", segment->size) == 0) { + return CWK_CURRENT; + } else if (strncmp(segment->begin, "..", segment->size) == 0) { + return CWK_BACK; + } + + return CWK_NORMAL; +} + +bool cwk_path_is_separator(const char *str) +{ + const char *c; + + // We loop over all characters in the read symbols. + c = separators[path_style]; + while (*c) { + if (*c == *str) { + return true; + } + + ++c; + } + + return false; +} + +size_t cwk_path_change_segment(struct cwk_segment *segment, const char *value, + char *buffer, size_t buffer_size) +{ + size_t pos, value_size, tail_size; + + // First we have to output the head, which is the whole string up to the + // beginning of the segment. This part of the path will just stay the same. + pos = cwk_path_output_sized(buffer, buffer_size, 0, segment->path, + (size_t)(segment->begin - segment->path)); + + // In order to trip the submitted value, we will skip any separator at the + // beginning of it and behave as if it was never there. + while (cwk_path_is_separator(value)) { + ++value; + } + + // Now we determine the length of the value. In order to do that we first + // locate the '\0'. + value_size = 0; + while (value[value_size]) { + ++value_size; + } + + // Since we trim separators at the beginning and in the end of the value we + // have to subtract from the size until there are either no more characters + // left or the last character is no separator. + while (value_size > 0 && cwk_path_is_separator(&value[value_size - 1])) { + --value_size; + } + + // We also have to determine the tail size, which is the part of the string + // following the current segment. This part will not change. + tail_size = strlen(segment->end); + + // Now we output the tail. We have to do that, because if the buffer and the + // source are overlapping we would override the tail if the value is + // increasing in length. + cwk_path_output_sized(buffer, buffer_size, pos + value_size, segment->end, + tail_size); + + // Finally we can output the value in the middle of the head and the tail, + // where we have enough space to fit the whole trimmed value. + pos += cwk_path_output_sized(buffer, buffer_size, pos, value, value_size); + + // Now we add the tail size to the current position and terminate the output - + // basically, ensure that there is a '\0' at the end of the buffer. + pos += tail_size; + cwk_path_terminate_output(buffer, buffer_size, pos); + + // And now tell the caller how long the whole path would be. + return pos; +} + +enum cwk_path_style cwk_path_guess_style(const char *path) +{ + const char *c; + size_t root_length; + struct cwk_segment segment; + + // First we determine the root. Only windows roots can be longer than a single + // slash, so if we can determine that it starts with something like "C:", we + // know that this is a windows path. + cwk_path_get_root_windows(path, &root_length); + if (root_length > 1) { + return CWK_STYLE_WINDOWS; + } + + // Next we check for slashes. Windows uses backslashes, while unix uses + // forward slashes. Windows actually supports both, but our best guess is to + // assume windows with backslashes and unix with forward slashes. + for (c = path; *c; ++c) { + if (*c == *separators[CWK_STYLE_UNIX]) { + return CWK_STYLE_UNIX; + } else if (*c == *separators[CWK_STYLE_WINDOWS]) { + return CWK_STYLE_WINDOWS; + } + } + + // This path does not have any slashes. We grab the last segment (which + // actually must be the first one), and determine whether the segment starts + // with a dot. A dot is a hidden folder or file in the UNIX world, in that + // case we assume the path to have UNIX style. + if (!cwk_path_get_last_segment(path, &segment)) { + // We couldn't find any segments, so we default to a UNIX path style since + // there is no way to make any assumptions. + return CWK_STYLE_UNIX; + } + + if (*segment.begin == '.') { + return CWK_STYLE_UNIX; + } + + // And finally we check whether the last segment contains a dot. If it + // contains a dot, that might be an extension. Windows is more likely to have + // file names with extensions, so our guess would be windows. + for (c = segment.begin; *c; ++c) { + if (*c == '.') { + return CWK_STYLE_WINDOWS; + } + } + + // All our checks failed, so we will return a default value which is currently + // UNIX. + return CWK_STYLE_UNIX; +} + +void cwk_path_set_style(enum cwk_path_style style) +{ + // We can just set the global path style variable and then the behaviour for + // all functions will change accordingly. + assert(style == CWK_STYLE_UNIX || style == CWK_STYLE_WINDOWS); + path_style = style; +} + +enum cwk_path_style cwk_path_get_style(void) +{ + // Simply return the path style which we store in a global variable. + return path_style; +} diff --git a/src/cwalk.h b/src/cwalk.h new file mode 100644 index 0000000..bfb5ff9 --- /dev/null +++ b/src/cwalk.h @@ -0,0 +1,498 @@ +#pragma once + +#ifndef CWK_LIBRARY_H +#define CWK_LIBRARY_H + +#include +#include + +#if defined(_WIN32) || defined(__CYGWIN__) +#define CWK_EXPORT __declspec(dllexport) +#define CWK_IMPORT __declspec(dllimport) +#elif __GNUC__ >= 4 +#define CWK_EXPORT __attribute__((visibility("default"))) +#define CWK_IMPORT __attribute__((visibility("default"))) +#else +#define CWK_EXPORT +#define CWK_IMPORT +#endif + +#if defined(CWK_SHARED) +#if defined(CWK_EXPORTS) +#define CWK_PUBLIC CWK_EXPORT +#else +#define CWK_PUBLIC CWK_IMPORT +#endif +#else +#define CWK_PUBLIC +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * A segment represents a single component of a path. For instance, on linux a + * path might look like this "/var/log/", which consists of two segments "var" + * and "log". + */ +struct cwk_segment +{ + const char *path; + const char *segments; + const char *begin; + const char *end; + size_t size; +}; + +/** + * The segment type can be used to identify whether a segment is a special + * segment or not. + * + * CWK_NORMAL - normal folder or file segment + * CWK_CURRENT - "./" current folder segment + * CWK_BACK - "../" relative back navigation segment + */ +enum cwk_segment_type +{ + CWK_NORMAL, + CWK_CURRENT, + CWK_BACK +}; + +/** + * @brief Determines the style which is used for the path parsing and + * generation. + */ +enum cwk_path_style +{ + CWK_STYLE_WINDOWS, + CWK_STYLE_UNIX +}; + +/** + * @brief Generates an absolute path based on a base. + * + * This function generates an absolute path based on a base path and another + * path. It is guaranteed to return an absolute path. If the second submitted + * path is absolute, it will override the base path. The result will be + * written to a buffer, which might be truncated if the buffer is not large + * enough to hold the full path. However, the truncated result will always be + * null-terminated. The returned value is the amount of characters which the + * resulting path would take if it was not truncated (excluding the + * null-terminating character). + * + * @param base The absolute base path on which the relative path will be + * applied. + * @param path The relative path which will be applied on the base path. + * @param buffer The buffer where the result will be written to. + * @param buffer_size The size of the result buffer. + * @return Returns the total amount of characters of the new absolute path. + */ +CWK_PUBLIC size_t cwk_path_get_absolute(const char *base, const char *path, + char *buffer, size_t buffer_size); + +/** + * @brief Generates a relative path based on a base. + * + * This function generates a relative path based on a base path and another + * path. It determines how to get to the submitted path, starting from the + * base directory. The result will be written to a buffer, which might be + * truncated if the buffer is not large enough to hold the full path. However, + * the truncated result will always be null-terminated. The returned value is + * the amount of characters which the resulting path would take if it was not + * truncated (excluding the null-terminating character). + * + * @param base_directory The base path from which the relative path will + * start. + * @param path The target path where the relative path will point to. + * @param buffer The buffer where the result will be written to. + * @param buffer_size The size of the result buffer. + * @return Returns the total amount of characters of the full path. + */ +CWK_PUBLIC size_t cwk_path_get_relative(const char *base_directory, + const char *path, char *buffer, size_t buffer_size); + +/** + * @brief Joins two paths together. + * + * This function generates a new path by combining the two submitted paths. It + * will remove double separators, and unlike cwk_path_get_absolute it permits + * the use of two relative paths to combine. The result will be written to a + * buffer, which might be truncated if the buffer is not large enough to hold + * the full path. However, the truncated result will always be + * null-terminated. The returned value is the amount of characters which the + * resulting path would take if it was not truncated (excluding the + * null-terminating character). + * + * @param path_a The first path which comes first. + * @param path_b The second path which comes after the first. + * @param buffer The buffer where the result will be written to. + * @param buffer_size The size of the result buffer. + * @return Returns the total amount of characters of the full, combined path. + */ +CWK_PUBLIC size_t cwk_path_join(const char *path_a, const char *path_b, + char *buffer, size_t buffer_size); + +/** + * @brief Joins multiple paths together. + * + * This function generates a new path by joining multiple paths together. It + * will remove double separators, and unlike cwk_path_get_absolute it permits + * the use of multiple relative paths to combine. The last path of the + * submitted string array must be set to NULL. The result will be written to a + * buffer, which might be truncated if the buffer is not large enough to hold + * the full path. However, the truncated result will always be + * null-terminated. The returned value is the amount of characters which the + * resulting path would take if it was not truncated (excluding the + * null-terminating character). + * + * @param paths An array of paths which will be joined. + * @param buffer The buffer where the result will be written to. + * @param buffer_size The size of the result buffer. + * @return Returns the total amount of characters of the full, combined path. + */ +CWK_PUBLIC size_t cwk_path_join_multiple(const char **paths, char *buffer, + size_t buffer_size); + +/** + * @brief Determines the root of a path. + * + * This function determines the root of a path by finding its length. The + * root always starts at the submitted path. If the path has no root, the + * length will be set to zero. + * + * @param path The path which will be inspected. + * @param length The output of the root length. + */ +CWK_PUBLIC void cwk_path_get_root(const char *path, size_t *length); + +/** + * @brief Changes the root of a path. + * + * This function changes the root of a path. It does not normalize the result. + * The result will be written to a buffer, which might be truncated if the + * buffer is not large enough to hold the full path. However, the truncated + * result will always be null-terminated. The returned value is the amount of + * characters which the resulting path would take if it was not truncated + * (excluding the null-terminating character). + * + * @param path The original path which will get a new root. + * @param new_root The new root which will be placed in the path. + * @param buffer The output buffer where the result is written to. + * @param buffer_size The size of the output buffer where the result is + * written to. + * @return Returns the total amount of characters of the new path. + */ +CWK_PUBLIC size_t cwk_path_change_root(const char *path, const char *new_root, + char *buffer, size_t buffer_size); + +/** + * @brief Determine whether the path is absolute or not. + * + * This function checks whether the path is an absolute path or not. A path is + * considered to be absolute if the root ends with a separator. + * + * @param path The path which will be checked. + * @return Returns true if the path is absolute or false otherwise. + */ +CWK_PUBLIC bool cwk_path_is_absolute(const char *path); + +/** + * @brief Determine whether the path is relative or not. + * + * This function checks whether the path is a relative path or not. A path is + * considered to be relative if the root does not end with a separator. + * + * @param path The path which will be checked. + * @return Returns true if the path is relative or false otherwise. + */ +CWK_PUBLIC bool cwk_path_is_relative(const char *path); + +/** + * @brief Gets the basename of a file path. + * + * This function gets the basename of a file path. A pointer to the beginning + * of the basename will be returned through the basename parameter. This + * pointer will be positioned on the first letter after the separator. The + * length of the file path will be returned through the length parameter. The + * length will be set to zero and the basename to NULL if there is no basename + * available. + * + * @param path The path which will be inspected. + * @param basename The output of the basename pointer. + * @param length The output of the length of the basename. This may be + * null if not required. + */ +CWK_PUBLIC void cwk_path_get_basename(const char *path, const char **basename, + size_t *length); + +/** + * @brief Changes the basename of a file path. + * + * This function changes the basename of a file path. This function will not + * write out more than the specified buffer can contain. However, the + * generated string is always null-terminated - even if not the whole path is + * written out. The function returns the total number of characters the + * complete buffer would have, even if it was not written out completely. The + * path may be the same memory address as the buffer. + * + * @param path The original path which will be used for the modified path. + * @param new_basename The new basename which will replace the old one. + * @param buffer The buffer where the changed path will be written to. + * @param buffer_size The size of the result buffer where the changed path is + * written to. + * @return Returns the size which the complete new path would have if it was + * not truncated. + */ +CWK_PUBLIC size_t cwk_path_change_basename(const char *path, + const char *new_basename, char *buffer, size_t buffer_size); + +/** + * @brief Gets the dirname of a file path. + * + * This function determines the dirname of a file path and returns the length + * up to which character is considered to be part of it. If no dirname is + * found, the length will be set to zero. The beginning of the dirname is + * always equal to the submitted path pointer. + * + * @param path The path which will be inspected. + * @param length The length of the dirname. + */ +CWK_PUBLIC void cwk_path_get_dirname(const char *path, size_t *length); + +/** + * @brief Gets the extension of a file path. + * + * This function extracts the extension portion of a file path. A pointer to + * the beginning of the extension will be returned through the extension + * parameter if an extension is found and true is returned. This pointer will + * be positioned on the dot. The length of the extension name will be returned + * through the length parameter. If no extension is found both parameters + * won't be touched and false will be returned. + * + * @param path The path which will be inspected. + * @param extension The output of the extension pointer. + * @param length The output of the length of the extension. + * @return Returns true if an extension is found or false otherwise. + */ +CWK_PUBLIC bool cwk_path_get_extension(const char *path, const char **extension, + size_t *length); + +/** + * @brief Determines whether the file path has an extension. + * + * This function determines whether the submitted file path has an extension. + * This will evaluate to true if the last segment of the path contains a dot. + * + * @param path The path which will be inspected. + * @return Returns true if the path has an extension or false otherwise. + */ +CWK_PUBLIC bool cwk_path_has_extension(const char *path); + +/** + * @brief Changes the extension of a file path. + * + * This function changes the extension of a file name. The function will + * append an extension if the basename does not have an extension, or use the + * extension as a basename if the path does not have a basename. This function + * will not write out more than the specified buffer can contain. However, the + * generated string is always null-terminated - even if not the whole path is + * written out. The function returns the total number of characters the + * complete buffer would have, even if it was not written out completely. The + * path may be the same memory address as the buffer. + * + * @param path The path which will be used to make the change. + * @param new_extension The extension which will be placed within the new + * path. + * @param buffer The output buffer where the result will be written to. + * @param buffer_size The size of the output buffer where the result will be + * written to. + * @return Returns the total size which the output would have if it was not + * truncated. + */ +CWK_PUBLIC size_t cwk_path_change_extension(const char *path, + const char *new_extension, char *buffer, size_t buffer_size); + +/** + * @brief Creates a normalized version of the path. + * + * This function creates a normalized version of the path within the specified + * buffer. This function will not write out more than the specified buffer can + * contain. However, the generated string is always null-terminated - even if + * not the whole path is written out. The function returns the total number of + * characters the complete buffer would have, even if it was not written out + * completely. The path may be the same memory address as the buffer. + * + * The following will be true for the normalized path: + * 1) "../" will be resolved. + * 2) "./" will be removed. + * 3) double separators will be fixed with a single separator. + * 4) separator suffixes will be removed. + * + * @param path The path which will be normalized. + * @param buffer The buffer where the new path is written to. + * @param buffer_size The size of the buffer. + * @return The size which the complete normalized path has if it was not + * truncated. + */ +CWK_PUBLIC size_t cwk_path_normalize(const char *path, char *buffer, + size_t buffer_size); + +/** + * @brief Finds common portions in two paths. + * + * This function finds common portions in two paths and returns the number + * characters from the beginning of the base path which are equal to the other + * path. + * + * @param path_base The base path which will be compared with the other path. + * @param path_other The other path which will compared with the base path. + * @return Returns the number of characters which are common in the base path. + */ +CWK_PUBLIC size_t cwk_path_get_intersection(const char *path_base, + const char *path_other); + +/** + * @brief Gets the first segment of a path. + * + * This function finds the first segment of a path. The position of the + * segment is set to the first character after the separator, and the length + * counts all characters until the next separator (excluding the separator). + * + * @param path The path which will be inspected. + * @param segment The segment which will be extracted. + * @return Returns true if there is a segment or false if there is none. + */ +CWK_PUBLIC bool cwk_path_get_first_segment(const char *path, + struct cwk_segment *segment); + +/** + * @brief Gets the last segment of the path. + * + * This function gets the last segment of a path. This function may return + * false if the path doesn't contain any segments, in which case the submitted + * segment parameter is not modified. The position of the segment is set to + * the first character after the separator, and the length counts all + * characters until the end of the path (excluding the separator). + * + * @param path The path which will be inspected. + * @param segment The segment which will be extracted. + * @return Returns true if there is a segment or false if there is none. + */ +CWK_PUBLIC bool cwk_path_get_last_segment(const char *path, + struct cwk_segment *segment); + +/** + * @brief Advances to the next segment. + * + * This function advances the current segment to the next segment. If there + * are no more segments left, the submitted segment structure will stay + * unchanged and false is returned. + * + * @param segment The current segment which will be advanced to the next one. + * @return Returns true if another segment was found or false otherwise. + */ +CWK_PUBLIC bool cwk_path_get_next_segment(struct cwk_segment *segment); + +/** + * @brief Moves to the previous segment. + * + * This function moves the current segment to the previous segment. If the + * current segment is the first one, the submitted segment structure will stay + * unchanged and false is returned. + * + * @param segment The current segment which will be moved to the previous one. + * @return Returns true if there is a segment before this one or false + * otherwise. + */ +CWK_PUBLIC bool cwk_path_get_previous_segment(struct cwk_segment *segment); + +/** + * @brief Gets the type of the submitted path segment. + * + * This function inspects the contents of the segment and determines the type + * of it. Currently, there are three types CWK_NORMAL, CWK_CURRENT and + * CWK_BACK. A CWK_NORMAL segment is a normal folder or file entry. A + * CWK_CURRENT is a "./" and a CWK_BACK a "../" segment. + * + * @param segment The segment which will be inspected. + * @return Returns the type of the segment. + */ +CWK_PUBLIC enum cwk_segment_type cwk_path_get_segment_type( + const struct cwk_segment *segment); + +/** + * @brief Changes the content of a segment. + * + * This function overrides the content of a segment to the submitted value and + * outputs the whole new path to the submitted buffer. The result might + * require less or more space than before if the new value length differs from + * the original length. The output is truncated if the new path is larger than + * the submitted buffer size, but it is always null-terminated. The source of + * the segment and the submitted buffer may be the same. + * + * @param segment The segment which will be modifier. + * @param value The new content of the segment. + * @param buffer The buffer where the modified path will be written to. + * @param buffer_size The size of the output buffer. + * @return Returns the total size which would have been written if the output + * was not truncated. + */ +CWK_PUBLIC size_t cwk_path_change_segment(struct cwk_segment *segment, + const char *value, char *buffer, size_t buffer_size); + +/** + * @brief Checks whether the submitted pointer points to a separator. + * + * This function simply checks whether the submitted pointer points to a + * separator, which has to be null-terminated (but not necessarily after the + * separator). The function will return true if it is a separator, or false + * otherwise. + * + * @param symbol A pointer to a string. + * @return Returns true if it is a separator, or false otherwise. + */ +CWK_PUBLIC bool cwk_path_is_separator(const char *str); + +/** + * @brief Guesses the path style. + * + * This function guesses the path style based on a submitted path-string. The + * guessing will look at the root and the type of slashes contained in the + * path and return the style which is more likely used in the path. + * + * @param path The path which will be inspected. + * @return Returns the style which is most likely used for the path. + */ +CWK_PUBLIC enum cwk_path_style cwk_path_guess_style(const char *path); + +/** + * @brief Configures which path style is used. + * + * This function configures which path style is used. The following styles are + * currently supported. + * + * CWK_STYLE_WINDOWS: Use backslashes as a separator and volume for the root. + * CWK_STYLE_UNIX: Use slashes as a separator and a slash for the root. + * + * @param style The style which will be used from now on. + */ +CWK_PUBLIC void cwk_path_set_style(enum cwk_path_style style); + +/** + * @brief Gets the path style configuration. + * + * This function gets the style configuration which is currently used for the + * paths. This configuration determines how paths are parsed and generated. + * + * @return Returns the current path style configuration. + */ +CWK_PUBLIC enum cwk_path_style cwk_path_get_style(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/src/enet.h b/src/enet.h new file mode 100644 index 0000000..a40a17a --- /dev/null +++ b/src/enet.h @@ -0,0 +1,6069 @@ +/** + * include/enet.h - a Single-Header auto-generated variant of enet.h library. + * + * Usage: + * #define ENET_IMPLEMENTATION exactly in ONE source file right BEFORE including the library, like: + * + * #define ENET_IMPLEMENTATION + * #include + * + * License: + * The MIT License (MIT) + * + * Copyright (c) 2002-2016 Lee Salzman + * Copyright (c) 2017-2021 Vladyslav Hrytsenko, Dominik Madarász + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * 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 OR COPYRIGHT HOLDERS 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. + * + */ +#ifndef ENET_INCLUDE_H +#define ENET_INCLUDE_H + +#include +#include +#include +#include + +#define ENET_VERSION_MAJOR 2 +#define ENET_VERSION_MINOR 3 +#define ENET_VERSION_PATCH 6 +#define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch)) +#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF) +#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF) +#define ENET_VERSION_GET_PATCH(version) ((version)&0xFF) +#define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH) + +#define ENET_TIME_OVERFLOW 86400000 +#define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW) +#define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW) +#define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b)) +#define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b)) +#define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b)) + +// =======================================================================// +// ! +// ! System differences +// ! +// =======================================================================// + +#if defined(_WIN32) + #if defined(_MSC_VER) && defined(ENET_IMPLEMENTATION) + #pragma warning (disable: 4267) // size_t to int conversion + #pragma warning (disable: 4244) // 64bit to 32bit int + #pragma warning (disable: 4018) // signed/unsigned mismatch + #pragma warning (disable: 4146) // unary minus operator applied to unsigned type + #endif + + #ifndef ENET_NO_PRAGMA_LINK + #pragma comment(lib, "ws2_32.lib") + #pragma comment(lib, "winmm.lib") + #endif + + #if _MSC_VER >= 1910 + /* It looks like there were changes as of Visual Studio 2017 and there are no 32/64 bit + versions of _InterlockedExchange[operation], only InterlockedExchange[operation] + (without leading underscore), so we have to distinguish between compiler versions */ + #define NOT_UNDERSCORED_INTERLOCKED_EXCHANGE + #endif + + #ifdef __GNUC__ + #if (_WIN32_WINNT < 0x0600) + #undef _WIN32_WINNT + #define _WIN32_WINNT 0x0600 + #endif + #endif + + #include + #include + #include + + #include + + #if defined(_WIN32) && defined(_MSC_VER) + #if _MSC_VER < 1900 + typedef struct timespec { + long tv_sec; + long tv_nsec; + }; + #endif + #define CLOCK_MONOTONIC 0 + #endif + + typedef SOCKET ENetSocket; + #define ENET_SOCKET_NULL INVALID_SOCKET + + #define ENET_HOST_TO_NET_16(value) (htons(value)) + #define ENET_HOST_TO_NET_32(value) (htonl(value)) + + #define ENET_NET_TO_HOST_16(value) (ntohs(value)) + #define ENET_NET_TO_HOST_32(value) (ntohl(value)) + + typedef struct { + size_t dataLength; + void * data; + } ENetBuffer; + + #define ENET_CALLBACK __cdecl + + #ifdef ENET_DLL + #ifdef ENET_IMPLEMENTATION + #define ENET_API __declspec( dllexport ) + #else + #define ENET_API __declspec( dllimport ) + #endif // ENET_IMPLEMENTATION + #else + #define ENET_API extern + #endif // ENET_DLL + + typedef fd_set ENetSocketSet; + + #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO(&(sockset)) + #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET(socket, &(sockset)) + #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR(socket, &(sockset)) + #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET(socket, &(sockset)) +#else + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #ifdef __APPLE__ + #include + #include + #include + #endif + + #ifndef MSG_NOSIGNAL + #define MSG_NOSIGNAL 0 + #endif + + #ifdef MSG_MAXIOVLEN + #define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN + #endif + + typedef int ENetSocket; + + #define ENET_SOCKET_NULL -1 + + #define ENET_HOST_TO_NET_16(value) (htons(value)) /**< macro that converts host to net byte-order of a 16-bit value */ + #define ENET_HOST_TO_NET_32(value) (htonl(value)) /**< macro that converts host to net byte-order of a 32-bit value */ + + #define ENET_NET_TO_HOST_16(value) (ntohs(value)) /**< macro that converts net to host byte-order of a 16-bit value */ + #define ENET_NET_TO_HOST_32(value) (ntohl(value)) /**< macro that converts net to host byte-order of a 32-bit value */ + + typedef struct { + void * data; + size_t dataLength; + } ENetBuffer; + + #define ENET_CALLBACK + #define ENET_API extern + + typedef fd_set ENetSocketSet; + + #define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO(&(sockset)) + #define ENET_SOCKETSET_ADD(sockset, socket) FD_SET(socket, &(sockset)) + #define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR(socket, &(sockset)) + #define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET(socket, &(sockset)) +#endif + +#ifdef __GNUC__ +#define ENET_DEPRECATED(func) func __attribute__ ((deprecated)) +#elif defined(_MSC_VER) +#define ENET_DEPRECATED(func) __declspec(deprecated) func +#else +#pragma message("WARNING: Please ENET_DEPRECATED for this compiler") +#define ENET_DEPRECATED(func) func +#endif + +#ifndef ENET_BUFFER_MAXIMUM +#define ENET_BUFFER_MAXIMUM (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS) +#endif + +#define ENET_UNUSED(x) (void)x; + +#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y)) +#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y)) + +#define ENET_IPV6 1 +static const struct in6_addr enet_v4_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }}}; +static const struct in6_addr enet_v4_noaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; +static const struct in6_addr enet_v4_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x01 }}}; +static const struct in6_addr enet_v6_anyaddr = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}}; +static const struct in6_addr enet_v6_noaddr = {{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}}; +static const struct in6_addr enet_v6_localhost = {{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }}}; +#define ENET_HOST_ANY in6addr_any +#define ENET_HOST_BROADCAST 0xFFFFFFFFU +#define ENET_PORT_ANY 0 + +#ifdef __cplusplus +extern "C" { +#endif + +// =======================================================================// +// ! +// ! Basic stuff +// ! +// =======================================================================// + + typedef uint8_t enet_uint8; /**< unsigned 8-bit type */ + typedef uint16_t enet_uint16; /**< unsigned 16-bit type */ + typedef uint32_t enet_uint32; /**< unsigned 32-bit type */ + typedef uint64_t enet_uint64; /**< unsigned 64-bit type */ + + typedef enet_uint32 ENetVersion; + typedef struct _ENetPacket ENetPacket; + + typedef struct _ENetCallbacks { + void *(ENET_CALLBACK *malloc) (size_t size); + void (ENET_CALLBACK *free) (void *memory); + void (ENET_CALLBACK *no_memory) (void); + + ENetPacket *(ENET_CALLBACK *packet_create) (const void *data, size_t dataLength, enet_uint32 flags); + void (ENET_CALLBACK *packet_destroy) (ENetPacket *packet); + } ENetCallbacks; + + extern void *enet_malloc(size_t); + extern void enet_free(void *); + extern ENetPacket* enet_packet_create(const void*,size_t,enet_uint32); + extern ENetPacket* enet_packet_copy(ENetPacket*); + extern void enet_packet_destroy(ENetPacket*); + +// =======================================================================// +// ! +// ! List +// ! +// =======================================================================// + + typedef struct _ENetListNode { + struct _ENetListNode *next; + struct _ENetListNode *previous; + } ENetListNode; + + typedef ENetListNode *ENetListIterator; + + typedef struct _ENetList { + ENetListNode sentinel; + } ENetList; + + extern ENetListIterator enet_list_insert(ENetListIterator, void *); + extern ENetListIterator enet_list_move(ENetListIterator, void *, void *); + + extern void *enet_list_remove(ENetListIterator); + extern void enet_list_clear(ENetList *); + extern size_t enet_list_size(ENetList *); + + #define enet_list_begin(list) ((list)->sentinel.next) + #define enet_list_end(list) (&(list)->sentinel) + #define enet_list_empty(list) (enet_list_begin(list) == enet_list_end(list)) + #define enet_list_next(iterator) ((iterator)->next) + #define enet_list_previous(iterator) ((iterator)->previous) + #define enet_list_front(list) ((void *)(list)->sentinel.next) + #define enet_list_back(list) ((void *)(list)->sentinel.previous) + + +// =======================================================================// +// ! +// ! Protocol +// ! +// =======================================================================// + + enum { + ENET_PROTOCOL_MINIMUM_MTU = 576, + ENET_PROTOCOL_MAXIMUM_MTU = 4096, + ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32, + ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096, + ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536, + ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1, + ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255, + ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF, + ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024 + }; + + typedef enum _ENetProtocolCommand { + ENET_PROTOCOL_COMMAND_NONE = 0, + ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1, + ENET_PROTOCOL_COMMAND_CONNECT = 2, + ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3, + ENET_PROTOCOL_COMMAND_DISCONNECT = 4, + ENET_PROTOCOL_COMMAND_PING = 5, + ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6, + ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7, + ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8, + ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9, + ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10, + ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11, + ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12, + ENET_PROTOCOL_COMMAND_COUNT = 13, + + ENET_PROTOCOL_COMMAND_MASK = 0x0F + } ENetProtocolCommand; + + typedef enum _ENetProtocolFlag { + ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7), + ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6), + + ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14), + ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15), + ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME, + + ENET_PROTOCOL_HEADER_SESSION_MASK = (3 << 12), + ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12 + } ENetProtocolFlag; + + #ifdef _MSC_VER + #pragma pack(push, 1) + #define ENET_PACKED + #elif defined(__GNUC__) || defined(__clang__) + #define ENET_PACKED __attribute__ ((packed)) + #else + #define ENET_PACKED + #endif + + typedef struct _ENetProtocolHeader { + enet_uint16 peerID; + enet_uint16 sentTime; + } ENET_PACKED ENetProtocolHeader; + + typedef struct _ENetProtocolCommandHeader { + enet_uint8 command; + enet_uint8 channelID; + enet_uint16 reliableSequenceNumber; + } ENET_PACKED ENetProtocolCommandHeader; + + typedef struct _ENetProtocolAcknowledge { + ENetProtocolCommandHeader header; + enet_uint16 receivedReliableSequenceNumber; + enet_uint16 receivedSentTime; + } ENET_PACKED ENetProtocolAcknowledge; + + typedef struct _ENetProtocolConnect { + ENetProtocolCommandHeader header; + enet_uint16 outgoingPeerID; + enet_uint8 incomingSessionID; + enet_uint8 outgoingSessionID; + enet_uint32 mtu; + enet_uint32 windowSize; + enet_uint32 channelCount; + enet_uint32 incomingBandwidth; + enet_uint32 outgoingBandwidth; + enet_uint32 packetThrottleInterval; + enet_uint32 packetThrottleAcceleration; + enet_uint32 packetThrottleDeceleration; + enet_uint32 connectID; + enet_uint32 data; + } ENET_PACKED ENetProtocolConnect; + + typedef struct _ENetProtocolVerifyConnect { + ENetProtocolCommandHeader header; + enet_uint16 outgoingPeerID; + enet_uint8 incomingSessionID; + enet_uint8 outgoingSessionID; + enet_uint32 mtu; + enet_uint32 windowSize; + enet_uint32 channelCount; + enet_uint32 incomingBandwidth; + enet_uint32 outgoingBandwidth; + enet_uint32 packetThrottleInterval; + enet_uint32 packetThrottleAcceleration; + enet_uint32 packetThrottleDeceleration; + enet_uint32 connectID; + } ENET_PACKED ENetProtocolVerifyConnect; + + typedef struct _ENetProtocolBandwidthLimit { + ENetProtocolCommandHeader header; + enet_uint32 incomingBandwidth; + enet_uint32 outgoingBandwidth; + } ENET_PACKED ENetProtocolBandwidthLimit; + + typedef struct _ENetProtocolThrottleConfigure { + ENetProtocolCommandHeader header; + enet_uint32 packetThrottleInterval; + enet_uint32 packetThrottleAcceleration; + enet_uint32 packetThrottleDeceleration; + } ENET_PACKED ENetProtocolThrottleConfigure; + + typedef struct _ENetProtocolDisconnect { + ENetProtocolCommandHeader header; + enet_uint32 data; + } ENET_PACKED ENetProtocolDisconnect; + + typedef struct _ENetProtocolPing { + ENetProtocolCommandHeader header; + } ENET_PACKED ENetProtocolPing; + + typedef struct _ENetProtocolSendReliable { + ENetProtocolCommandHeader header; + enet_uint16 dataLength; + } ENET_PACKED ENetProtocolSendReliable; + + typedef struct _ENetProtocolSendUnreliable { + ENetProtocolCommandHeader header; + enet_uint16 unreliableSequenceNumber; + enet_uint16 dataLength; + } ENET_PACKED ENetProtocolSendUnreliable; + + typedef struct _ENetProtocolSendUnsequenced { + ENetProtocolCommandHeader header; + enet_uint16 unsequencedGroup; + enet_uint16 dataLength; + } ENET_PACKED ENetProtocolSendUnsequenced; + + typedef struct _ENetProtocolSendFragment { + ENetProtocolCommandHeader header; + enet_uint16 startSequenceNumber; + enet_uint16 dataLength; + enet_uint32 fragmentCount; + enet_uint32 fragmentNumber; + enet_uint32 totalLength; + enet_uint32 fragmentOffset; + } ENET_PACKED ENetProtocolSendFragment; + + typedef union _ENetProtocol { + ENetProtocolCommandHeader header; + ENetProtocolAcknowledge acknowledge; + ENetProtocolConnect connect; + ENetProtocolVerifyConnect verifyConnect; + ENetProtocolDisconnect disconnect; + ENetProtocolPing ping; + ENetProtocolSendReliable sendReliable; + ENetProtocolSendUnreliable sendUnreliable; + ENetProtocolSendUnsequenced sendUnsequenced; + ENetProtocolSendFragment sendFragment; + ENetProtocolBandwidthLimit bandwidthLimit; + ENetProtocolThrottleConfigure throttleConfigure; + } ENET_PACKED ENetProtocol; + + #ifdef _MSC_VER + #pragma pack(pop) + #endif + +// =======================================================================// +// ! +// ! General ENet structs/enums +// ! +// =======================================================================// + + typedef enum _ENetSocketType { + ENET_SOCKET_TYPE_STREAM = 1, + ENET_SOCKET_TYPE_DATAGRAM = 2 + } ENetSocketType; + + typedef enum _ENetSocketWait { + ENET_SOCKET_WAIT_NONE = 0, + ENET_SOCKET_WAIT_SEND = (1 << 0), + ENET_SOCKET_WAIT_RECEIVE = (1 << 1), + ENET_SOCKET_WAIT_INTERRUPT = (1 << 2) + } ENetSocketWait; + + typedef enum _ENetSocketOption { + ENET_SOCKOPT_NONBLOCK = 1, + ENET_SOCKOPT_BROADCAST = 2, + ENET_SOCKOPT_RCVBUF = 3, + ENET_SOCKOPT_SNDBUF = 4, + ENET_SOCKOPT_REUSEADDR = 5, + ENET_SOCKOPT_RCVTIMEO = 6, + ENET_SOCKOPT_SNDTIMEO = 7, + ENET_SOCKOPT_ERROR = 8, + ENET_SOCKOPT_NODELAY = 9, + ENET_SOCKOPT_IPV6_V6ONLY = 10, + } ENetSocketOption; + + typedef enum _ENetSocketShutdown { + ENET_SOCKET_SHUTDOWN_READ = 0, + ENET_SOCKET_SHUTDOWN_WRITE = 1, + ENET_SOCKET_SHUTDOWN_READ_WRITE = 2 + } ENetSocketShutdown; + + /** + * Portable internet address structure. + * + * The host must be specified in network byte-order, and the port must be in host + * byte-order. The constant ENET_HOST_ANY may be used to specify the default + * server host. The constant ENET_HOST_BROADCAST may be used to specify the + * broadcast address (255.255.255.255). This makes sense for enet_host_connect, + * but not for enet_host_create. Once a server responds to a broadcast, the + * address is updated from ENET_HOST_BROADCAST to the server's actual IP address. + */ + typedef struct _ENetAddress { + struct in6_addr host; + enet_uint16 port; + enet_uint16 sin6_scope_id; + } ENetAddress; + + #define in6_equal(in6_addr_a, in6_addr_b) (memcmp(&in6_addr_a, &in6_addr_b, sizeof(struct in6_addr)) == 0) + + /** + * Packet flag bit constants. + * + * The host must be specified in network byte-order, and the port must be in + * host byte-order. The constant ENET_HOST_ANY may be used to specify the + * default server host. + * + * @sa ENetPacket + */ + typedef enum _ENetPacketFlag { + ENET_PACKET_FLAG_RELIABLE = (1 << 0), /** packet must be received by the target peer and resend attempts should be made until the packet is delivered */ + ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1), /** packet will not be sequenced with other packets not supported for reliable packets */ + ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2), /** packet will not allocate data, and user must supply it instead */ + ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3), /** packet will be fragmented using unreliable (instead of reliable) sends if it exceeds the MTU */ + ENET_PACKET_FLAG_SENT = (1 << 8), /** whether the packet has been sent from all queues it has been entered into */ + } ENetPacketFlag; + + typedef void (ENET_CALLBACK *ENetPacketFreeCallback)(void *); + + /** + * ENet packet structure. + * + * An ENet data packet that may be sent to or received from a peer. The shown + * fields should only be read and never modified. The data field contains the + * allocated data for the packet. The dataLength fields specifies the length + * of the allocated data. The flags field is either 0 (specifying no flags), + * or a bitwise-or of any combination of the following flags: + * + * ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer and resend attempts should be made until the packet is delivered + * ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets (not supported for reliable packets) + * ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead + * ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT - packet will be fragmented using unreliable (instead of reliable) sends if it exceeds the MTU + * ENET_PACKET_FLAG_SENT - whether the packet has been sent from all queues it has been entered into + * @sa ENetPacketFlag + */ + typedef struct _ENetPacket { + size_t referenceCount; /**< internal use only */ + enet_uint32 flags; /**< bitwise-or of ENetPacketFlag constants */ + enet_uint8 * data; /**< allocated data for packet */ + size_t dataLength; /**< length of data */ + ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */ + void * userData; /**< application private data, may be freely modified */ + } ENetPacket; + + typedef struct _ENetAcknowledgement { + ENetListNode acknowledgementList; + enet_uint32 sentTime; + ENetProtocol command; + } ENetAcknowledgement; + + typedef struct _ENetOutgoingCommand { + ENetListNode outgoingCommandList; + enet_uint16 reliableSequenceNumber; + enet_uint16 unreliableSequenceNumber; + enet_uint32 sentTime; + enet_uint32 roundTripTimeout; + enet_uint32 roundTripTimeoutLimit; + enet_uint32 fragmentOffset; + enet_uint16 fragmentLength; + enet_uint16 sendAttempts; + ENetProtocol command; + ENetPacket * packet; + } ENetOutgoingCommand; + + typedef struct _ENetIncomingCommand { + ENetListNode incomingCommandList; + enet_uint16 reliableSequenceNumber; + enet_uint16 unreliableSequenceNumber; + ENetProtocol command; + enet_uint32 fragmentCount; + enet_uint32 fragmentsRemaining; + enet_uint32 *fragments; + ENetPacket * packet; + } ENetIncomingCommand; + + typedef enum _ENetPeerState { + ENET_PEER_STATE_DISCONNECTED = 0, + ENET_PEER_STATE_CONNECTING = 1, + ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2, + ENET_PEER_STATE_CONNECTION_PENDING = 3, + ENET_PEER_STATE_CONNECTION_SUCCEEDED = 4, + ENET_PEER_STATE_CONNECTED = 5, + ENET_PEER_STATE_DISCONNECT_LATER = 6, + ENET_PEER_STATE_DISCONNECTING = 7, + ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8, + ENET_PEER_STATE_ZOMBIE = 9 + } ENetPeerState; + + enum { + ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024, + ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024, + ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000, + ENET_HOST_DEFAULT_MTU = 1400, + ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024, + ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024, + + ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500, + ENET_PEER_DEFAULT_PACKET_THROTTLE = 32, + ENET_PEER_PACKET_THROTTLE_SCALE = 32, + ENET_PEER_PACKET_THROTTLE_COUNTER = 7, + ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2, + ENET_PEER_PACKET_THROTTLE_DECELERATION = 2, + ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000, + ENET_PEER_PACKET_LOSS_SCALE = (1 << 16), + ENET_PEER_PACKET_LOSS_INTERVAL = 10000, + ENET_PEER_WINDOW_SIZE_SCALE = 64 * 1024, + ENET_PEER_TIMEOUT_LIMIT = 32, + ENET_PEER_TIMEOUT_MINIMUM = 5000, + ENET_PEER_TIMEOUT_MAXIMUM = 30000, + ENET_PEER_PING_INTERVAL = 500, + ENET_PEER_UNSEQUENCED_WINDOWS = 64, + ENET_PEER_UNSEQUENCED_WINDOW_SIZE = 1024, + ENET_PEER_FREE_UNSEQUENCED_WINDOWS = 32, + ENET_PEER_RELIABLE_WINDOWS = 16, + ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000, + ENET_PEER_FREE_RELIABLE_WINDOWS = 8 + }; + + typedef struct _ENetChannel { + enet_uint16 outgoingReliableSequenceNumber; + enet_uint16 outgoingUnreliableSequenceNumber; + enet_uint16 usedReliableWindows; + enet_uint16 reliableWindows[ENET_PEER_RELIABLE_WINDOWS]; + enet_uint16 incomingReliableSequenceNumber; + enet_uint16 incomingUnreliableSequenceNumber; + ENetList incomingReliableCommands; + ENetList incomingUnreliableCommands; + } ENetChannel; + + /** + * An ENet peer which data packets may be sent or received from. + * + * No fields should be modified unless otherwise specified. + */ + typedef struct _ENetPeer { + ENetListNode dispatchList; + struct _ENetHost *host; + enet_uint16 outgoingPeerID; + enet_uint16 incomingPeerID; + enet_uint32 connectID; + enet_uint8 outgoingSessionID; + enet_uint8 incomingSessionID; + ENetAddress address; /**< Internet address of the peer */ + void * data; /**< Application private data, may be freely modified */ + ENetPeerState state; + ENetChannel * channels; + size_t channelCount; /**< Number of channels allocated for communication with peer */ + enet_uint32 incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */ + enet_uint32 outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */ + enet_uint32 incomingBandwidthThrottleEpoch; + enet_uint32 outgoingBandwidthThrottleEpoch; + enet_uint32 incomingDataTotal; + enet_uint64 totalDataReceived; + enet_uint32 outgoingDataTotal; + enet_uint64 totalDataSent; + enet_uint32 lastSendTime; + enet_uint32 lastReceiveTime; + enet_uint32 nextTimeout; + enet_uint32 earliestTimeout; + enet_uint32 packetLossEpoch; + enet_uint32 packetsSent; + enet_uint64 totalPacketsSent; /**< total number of packets sent during a session */ + enet_uint32 packetsLost; + enet_uint32 totalPacketsLost; /**< total number of packets lost during a session */ + enet_uint32 packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */ + enet_uint32 packetLossVariance; + enet_uint32 packetThrottle; + enet_uint32 packetThrottleLimit; + enet_uint32 packetThrottleCounter; + enet_uint32 packetThrottleEpoch; + enet_uint32 packetThrottleAcceleration; + enet_uint32 packetThrottleDeceleration; + enet_uint32 packetThrottleInterval; + enet_uint32 pingInterval; + enet_uint32 timeoutLimit; + enet_uint32 timeoutMinimum; + enet_uint32 timeoutMaximum; + enet_uint32 lastRoundTripTime; + enet_uint32 lowestRoundTripTime; + enet_uint32 lastRoundTripTimeVariance; + enet_uint32 highestRoundTripTimeVariance; + enet_uint32 roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement */ + enet_uint32 roundTripTimeVariance; + enet_uint32 mtu; + enet_uint32 windowSize; + enet_uint32 reliableDataInTransit; + enet_uint16 outgoingReliableSequenceNumber; + ENetList acknowledgements; + ENetList sentReliableCommands; + ENetList sentUnreliableCommands; + ENetList outgoingReliableCommands; + ENetList outgoingUnreliableCommands; + ENetList dispatchedCommands; + int needsDispatch; + enet_uint16 incomingUnsequencedGroup; + enet_uint16 outgoingUnsequencedGroup; + enet_uint32 unsequencedWindow[ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32]; + enet_uint32 eventData; + size_t totalWaitingData; + } ENetPeer; + + /** An ENet packet compressor for compressing UDP packets before socket sends or receives. */ + typedef struct _ENetCompressor { + /** Context data for the compressor. Must be non-NULL. */ + void *context; + + /** Compresses from inBuffers[0:inBufferCount-1], containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */ + size_t(ENET_CALLBACK * compress) (void *context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit); + + /** Decompresses from inData, containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */ + size_t(ENET_CALLBACK * decompress) (void *context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit); + + /** Destroys the context when compression is disabled or the host is destroyed. May be NULL. */ + void (ENET_CALLBACK * destroy)(void *context); + } ENetCompressor; + + /** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */ + typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback)(const ENetBuffer *buffers, size_t bufferCount); + + /** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */ + typedef int (ENET_CALLBACK * ENetInterceptCallback)(struct _ENetHost *host, void *event); + + /** An ENet host for communicating with peers. + * + * No fields should be modified unless otherwise stated. + * + * @sa enet_host_create() + * @sa enet_host_destroy() + * @sa enet_host_connect() + * @sa enet_host_service() + * @sa enet_host_flush() + * @sa enet_host_broadcast() + * @sa enet_host_compress() + * @sa enet_host_channel_limit() + * @sa enet_host_bandwidth_limit() + * @sa enet_host_bandwidth_throttle() + */ + typedef struct _ENetHost { + ENetSocket socket; + ENetAddress address; /**< Internet address of the host */ + enet_uint32 incomingBandwidth; /**< downstream bandwidth of the host */ + enet_uint32 outgoingBandwidth; /**< upstream bandwidth of the host */ + enet_uint32 bandwidthThrottleEpoch; + enet_uint32 mtu; + enet_uint32 randomSeed; + int recalculateBandwidthLimits; + ENetPeer * peers; /**< array of peers allocated for this host */ + size_t peerCount; /**< number of peers allocated for this host */ + size_t channelLimit; /**< maximum number of channels allowed for connected peers */ + enet_uint32 serviceTime; + ENetList dispatchQueue; + int continueSending; + size_t packetSize; + enet_uint16 headerFlags; + ENetProtocol commands[ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS]; + size_t commandCount; + ENetBuffer buffers[ENET_BUFFER_MAXIMUM]; + size_t bufferCount; + ENetChecksumCallback checksum; /**< callback the user can set to enable packet checksums for this host */ + ENetCompressor compressor; + enet_uint8 packetData[2][ENET_PROTOCOL_MAXIMUM_MTU]; + ENetAddress receivedAddress; + enet_uint8 * receivedData; + size_t receivedDataLength; + enet_uint32 totalSentData; /**< total data sent, user should reset to 0 as needed to prevent overflow */ + enet_uint32 totalSentPackets; /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */ + enet_uint32 totalReceivedData; /**< total data received, user should reset to 0 as needed to prevent overflow */ + enet_uint32 totalReceivedPackets; /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */ + ENetInterceptCallback intercept; /**< callback the user can set to intercept received raw UDP packets */ + size_t connectedPeers; + size_t bandwidthLimitedPeers; + size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */ + size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */ + size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */ + } ENetHost; + + /** + * An ENet event type, as specified in @ref ENetEvent. + */ + typedef enum _ENetEventType { + /** no event occurred within the specified time limit */ + ENET_EVENT_TYPE_NONE = 0, + + /** a connection request initiated by enet_host_connect has completed. + * The peer field contains the peer which successfully connected. + */ + ENET_EVENT_TYPE_CONNECT = 1, + + /** a peer has disconnected. This event is generated on a successful + * completion of a disconnect initiated by enet_peer_disconnect, if + * a peer has timed out. The peer field contains the peer + * which disconnected. The data field contains user supplied data + * describing the disconnection, or 0, if none is available. + */ + ENET_EVENT_TYPE_DISCONNECT = 2, + + /** a packet has been received from a peer. The peer field specifies the + * peer which sent the packet. The channelID field specifies the channel + * number upon which the packet was received. The packet field contains + * the packet that was received; this packet must be destroyed with + * enet_packet_destroy after use. + */ + ENET_EVENT_TYPE_RECEIVE = 3, + + /** a peer is disconnected because the host didn't receive the acknowledgment + * packet within certain maximum time out. The reason could be because of bad + * network connection or host crashed. + */ + ENET_EVENT_TYPE_DISCONNECT_TIMEOUT = 4, + } ENetEventType; + + /** + * An ENet event as returned by enet_host_service(). + * + * @sa enet_host_service + */ + typedef struct _ENetEvent { + ENetEventType type; /**< type of the event */ + ENetPeer * peer; /**< peer that generated a connect, disconnect or receive event */ + enet_uint8 channelID; /**< channel on the peer that generated the event, if appropriate */ + enet_uint32 data; /**< data associated with the event, if appropriate */ + ENetPacket * packet; /**< packet associated with the event, if appropriate */ + } ENetEvent; + +// =======================================================================// +// ! +// ! Public API +// ! +// =======================================================================// + + /** + * Initializes ENet globally. Must be called prior to using any functions in ENet. + * @returns 0 on success, < 0 on failure + */ + ENET_API int enet_initialize(void); + + /** + * Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored. + * + * @param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use + * @param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults + * @returns 0 on success, < 0 on failure + */ + ENET_API int enet_initialize_with_callbacks(ENetVersion version, const ENetCallbacks * inits); + + /** + * Shuts down ENet globally. Should be called when a program that has initialized ENet exits. + */ + ENET_API void enet_deinitialize(void); + + /** + * Gives the linked version of the ENet library. + * @returns the version number + */ + ENET_API ENetVersion enet_linked_version(void); + + /** Returns the monotonic time in milliseconds. Its initial value is unspecified unless otherwise set. */ + ENET_API enet_uint32 enet_time_get(void); + + /** ENet socket functions */ + ENET_API ENetSocket enet_socket_create(ENetSocketType); + ENET_API int enet_socket_bind(ENetSocket, const ENetAddress *); + ENET_API int enet_socket_get_address(ENetSocket, ENetAddress *); + ENET_API int enet_socket_listen(ENetSocket, int); + ENET_API ENetSocket enet_socket_accept(ENetSocket, ENetAddress *); + ENET_API int enet_socket_connect(ENetSocket, const ENetAddress *); + ENET_API int enet_socket_send(ENetSocket, const ENetAddress *, const ENetBuffer *, size_t); + ENET_API int enet_socket_receive(ENetSocket, ENetAddress *, ENetBuffer *, size_t); + ENET_API int enet_socket_wait(ENetSocket, enet_uint32 *, enet_uint64); + ENET_API int enet_socket_set_option(ENetSocket, ENetSocketOption, int); + ENET_API int enet_socket_get_option(ENetSocket, ENetSocketOption, int *); + ENET_API int enet_socket_shutdown(ENetSocket, ENetSocketShutdown); + ENET_API void enet_socket_destroy(ENetSocket); + ENET_API int enet_socketset_select(ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32); + + /** Attempts to parse the printable form of the IP address in the parameter hostName + and sets the host field in the address parameter if successful. + @param address destination to store the parsed IP address + @param hostName IP address to parse + @retval 0 on success + @retval < 0 on failure + @returns the address of the given hostName in address on success + */ + ENET_API int enet_address_set_host_ip_old(ENetAddress * address, const char * hostName); + + /** Attempts to resolve the host named by the parameter hostName and sets + the host field in the address parameter if successful. + @param address destination to store resolved address + @param hostName host name to lookup + @retval 0 on success + @retval < 0 on failure + @returns the address of the given hostName in address on success + */ + ENET_API int enet_address_set_host_old(ENetAddress * address, const char * hostName); + + /** Gives the printable form of the IP address specified in the address parameter. + @param address address printed + @param hostName destination for name, must not be NULL + @param nameLength maximum length of hostName. + @returns the null-terminated name of the host in hostName on success + @retval 0 on success + @retval < 0 on failure + */ + ENET_API int enet_address_get_host_ip_old(const ENetAddress * address, char * hostName, size_t nameLength); + + /** Attempts to do a reverse lookup of the host field in the address parameter. + @param address address used for reverse lookup + @param hostName destination for name, must not be NULL + @param nameLength maximum length of hostName. + @returns the null-terminated name of the host in hostName on success + @retval 0 on success + @retval < 0 on failure + */ + ENET_API int enet_address_get_host_old(const ENetAddress * address, char * hostName, size_t nameLength); + + ENET_API int enet_address_set_host_ip_new(ENetAddress * address, const char * hostName); + ENET_API int enet_address_set_host_new(ENetAddress * address, const char * hostName); + ENET_API int enet_address_get_host_ip_new(const ENetAddress * address, char * hostName, size_t nameLength); + ENET_API int enet_address_get_host_new(const ENetAddress * address, char * hostName, size_t nameLength); + +#ifdef ENET_FEATURE_ADDRESS_MAPPING +#define enet_address_set_host_ip enet_address_set_host_ip_new +#define enet_address_set_host enet_address_set_host_new +#define enet_address_get_host_ip enet_address_get_host_ip_new +#define enet_address_get_host enet_address_get_host_new +#else +#define enet_address_set_host_ip enet_address_set_host_ip_old +#define enet_address_set_host enet_address_set_host_old +#define enet_address_get_host_ip enet_address_get_host_ip_old +#define enet_address_get_host enet_address_get_host_old +#endif + + ENET_API enet_uint32 enet_host_get_peers_count(ENetHost *); + ENET_API enet_uint32 enet_host_get_packets_sent(ENetHost *); + ENET_API enet_uint32 enet_host_get_packets_received(ENetHost *); + ENET_API enet_uint32 enet_host_get_bytes_sent(ENetHost *); + ENET_API enet_uint32 enet_host_get_bytes_received(ENetHost *); + ENET_API enet_uint32 enet_host_get_received_data(ENetHost *, enet_uint8** data); + ENET_API enet_uint32 enet_host_get_mtu(ENetHost *); + + ENET_API enet_uint32 enet_peer_get_id(ENetPeer *); + ENET_API enet_uint32 enet_peer_get_ip(ENetPeer *, char * ip, size_t ipLength); + ENET_API enet_uint16 enet_peer_get_port(ENetPeer *); + ENET_API enet_uint32 enet_peer_get_rtt(ENetPeer *); + ENET_API enet_uint64 enet_peer_get_packets_sent(ENetPeer *); + ENET_API enet_uint32 enet_peer_get_packets_lost(ENetPeer *); + ENET_API enet_uint64 enet_peer_get_bytes_sent(ENetPeer *); + ENET_API enet_uint64 enet_peer_get_bytes_received(ENetPeer *); + + ENET_API ENetPeerState enet_peer_get_state(ENetPeer *); + + ENET_API void * enet_peer_get_data(ENetPeer *); + ENET_API void enet_peer_set_data(ENetPeer *, const void *); + + ENET_API void * enet_packet_get_data(ENetPacket *); + ENET_API enet_uint32 enet_packet_get_length(ENetPacket *); + ENET_API void enet_packet_set_free_callback(ENetPacket *, void *); + + ENET_API ENetPacket * enet_packet_create_offset(const void *, size_t, size_t, enet_uint32); + ENET_API enet_uint32 enet_crc32(const ENetBuffer *, size_t); + + ENET_API ENetHost * enet_host_create(const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32); + ENET_API void enet_host_destroy(ENetHost *); + ENET_API ENetPeer * enet_host_connect(ENetHost *, const ENetAddress *, size_t, enet_uint32); + ENET_API int enet_host_check_events(ENetHost *, ENetEvent *); + ENET_API int enet_host_service(ENetHost *, ENetEvent *, enet_uint32); + ENET_API int enet_host_send_raw(ENetHost *, const ENetAddress *, enet_uint8 *, size_t); + ENET_API int enet_host_send_raw_ex(ENetHost *host, const ENetAddress* address, enet_uint8* data, size_t skipBytes, size_t bytesToSend); + ENET_API void enet_host_set_intercept(ENetHost *, const ENetInterceptCallback); + ENET_API void enet_host_flush(ENetHost *); + ENET_API void enet_host_broadcast(ENetHost *, enet_uint8, ENetPacket *); + ENET_API void enet_host_compress(ENetHost *, const ENetCompressor *); + ENET_API void enet_host_channel_limit(ENetHost *, size_t); + ENET_API void enet_host_bandwidth_limit(ENetHost *, enet_uint32, enet_uint32); + extern void enet_host_bandwidth_throttle(ENetHost *); + extern enet_uint64 enet_host_random_seed(void); + + ENET_API int enet_peer_send(ENetPeer *, enet_uint8, ENetPacket *); + ENET_API ENetPacket * enet_peer_receive(ENetPeer *, enet_uint8 * channelID); + ENET_API void enet_peer_ping(ENetPeer *); + ENET_API void enet_peer_ping_interval(ENetPeer *, enet_uint32); + ENET_API void enet_peer_timeout(ENetPeer *, enet_uint32, enet_uint32, enet_uint32); + ENET_API void enet_peer_reset(ENetPeer *); + ENET_API void enet_peer_disconnect(ENetPeer *, enet_uint32); + ENET_API void enet_peer_disconnect_now(ENetPeer *, enet_uint32); + ENET_API void enet_peer_disconnect_later(ENetPeer *, enet_uint32); + ENET_API void enet_peer_throttle_configure(ENetPeer *, enet_uint32, enet_uint32, enet_uint32); + extern int enet_peer_throttle(ENetPeer *, enet_uint32); + extern void enet_peer_reset_queues(ENetPeer *); + extern void enet_peer_setup_outgoing_command(ENetPeer *, ENetOutgoingCommand *); + extern ENetOutgoingCommand * enet_peer_queue_outgoing_command(ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16); + extern ENetIncomingCommand * enet_peer_queue_incoming_command(ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32); + extern ENetAcknowledgement * enet_peer_queue_acknowledgement(ENetPeer *, const ENetProtocol *, enet_uint16); + extern void enet_peer_dispatch_incoming_unreliable_commands(ENetPeer *, ENetChannel *); + extern void enet_peer_dispatch_incoming_reliable_commands(ENetPeer *, ENetChannel *); + extern void enet_peer_on_connect(ENetPeer *); + extern void enet_peer_on_disconnect(ENetPeer *); + + extern size_t enet_protocol_command_size (enet_uint8); + +#ifdef __cplusplus +} +#endif + +#if defined(ENET_IMPLEMENTATION) && !defined(ENET_IMPLEMENTATION_DONE) +#define ENET_IMPLEMENTATION_DONE 1 + +#ifdef __cplusplus +extern "C" { +#endif + +// =======================================================================// +// ! +// ! Atomics +// ! +// =======================================================================// + +#if defined(_MSC_VER) + + #define ENET_AT_CASSERT_PRED(predicate) sizeof(char[2 * !!(predicate)-1]) + #define ENET_IS_SUPPORTED_ATOMIC(size) ENET_AT_CASSERT_PRED(size == 1 || size == 2 || size == 4 || size == 8) + #define ENET_ATOMIC_SIZEOF(variable) (ENET_IS_SUPPORTED_ATOMIC(sizeof(*(variable))), sizeof(*(variable))) + + __inline int64_t enet_at_atomic_read(char *ptr, size_t size) + { + switch (size) { + case 1: + return _InterlockedExchangeAdd8((volatile char *)ptr, 0); + case 2: + return _InterlockedExchangeAdd16((volatile SHORT *)ptr, 0); + case 4: + #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE + return InterlockedExchangeAdd((volatile LONG *)ptr, 0); + #else + return _InterlockedExchangeAdd((volatile LONG *)ptr, 0); + #endif + case 8: + #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE + return InterlockedExchangeAdd64((volatile LONGLONG *)ptr, 0); + #else + return _InterlockedExchangeAdd64((volatile LONGLONG *)ptr, 0); + #endif + default: + return 0xbad13bad; /* never reached */ + } + } + + __inline int64_t enet_at_atomic_write(char *ptr, int64_t value, size_t size) + { + switch (size) { + case 1: + return _InterlockedExchange8((volatile char *)ptr, (char)value); + case 2: + return _InterlockedExchange16((volatile SHORT *)ptr, (SHORT)value); + case 4: + #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE + return InterlockedExchange((volatile LONG *)ptr, (LONG)value); + #else + return _InterlockedExchange((volatile LONG *)ptr, (LONG)value); + #endif + case 8: + #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE + return InterlockedExchange64((volatile LONGLONG *)ptr, (LONGLONG)value); + #else + return _InterlockedExchange64((volatile LONGLONG *)ptr, (LONGLONG)value); + #endif + default: + return 0xbad13bad; /* never reached */ + } + } + + __inline int64_t enet_at_atomic_cas(char *ptr, int64_t new_val, int64_t old_val, size_t size) + { + switch (size) { + case 1: + return _InterlockedCompareExchange8((volatile char *)ptr, (char)new_val, (char)old_val); + case 2: + return _InterlockedCompareExchange16((volatile SHORT *)ptr, (SHORT)new_val, + (SHORT)old_val); + case 4: + #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE + return InterlockedCompareExchange((volatile LONG *)ptr, (LONG)new_val, (LONG)old_val); + #else + return _InterlockedCompareExchange((volatile LONG *)ptr, (LONG)new_val, (LONG)old_val); + #endif + case 8: + #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE + return InterlockedCompareExchange64((volatile LONGLONG *)ptr, (LONGLONG)new_val, + (LONGLONG)old_val); + #else + return _InterlockedCompareExchange64((volatile LONGLONG *)ptr, (LONGLONG)new_val, + (LONGLONG)old_val); + #endif + default: + return 0xbad13bad; /* never reached */ + } + } + + __inline int64_t enet_at_atomic_inc(char *ptr, int64_t delta, size_t data_size) + { + switch (data_size) { + case 1: + return _InterlockedExchangeAdd8((volatile char *)ptr, (char)delta); + case 2: + return _InterlockedExchangeAdd16((volatile SHORT *)ptr, (SHORT)delta); + case 4: + #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE + return InterlockedExchangeAdd((volatile LONG *)ptr, (LONG)delta); + #else + return _InterlockedExchangeAdd((volatile LONG *)ptr, (LONG)delta); + #endif + case 8: + #ifdef NOT_UNDERSCORED_INTERLOCKED_EXCHANGE + return InterlockedExchangeAdd64((volatile LONGLONG *)ptr, (LONGLONG)delta); + #else + return _InterlockedExchangeAdd64((volatile LONGLONG *)ptr, (LONGLONG)delta); + #endif + default: + return 0xbad13bad; /* never reached */ + } + } + + #define ENET_ATOMIC_READ(variable) enet_at_atomic_read((char *)(variable), ENET_ATOMIC_SIZEOF(variable)) + #define ENET_ATOMIC_WRITE(variable, new_val) \ + enet_at_atomic_write((char *)(variable), (int64_t)(new_val), ENET_ATOMIC_SIZEOF(variable)) + #define ENET_ATOMIC_CAS(variable, old_value, new_val) \ + enet_at_atomic_cas((char *)(variable), (int64_t)(new_val), (int64_t)(old_value), \ + ENET_ATOMIC_SIZEOF(variable)) + #define ENET_ATOMIC_INC(variable) enet_at_atomic_inc((char *)(variable), 1, ENET_ATOMIC_SIZEOF(variable)) + #define ENET_ATOMIC_DEC(variable) enet_at_atomic_inc((char *)(variable), -1, ENET_ATOMIC_SIZEOF(variable)) + #define ENET_ATOMIC_INC_BY(variable, delta) \ + enet_at_atomic_inc((char *)(variable), (delta), ENET_ATOMIC_SIZEOF(variable)) + #define ENET_ATOMIC_DEC_BY(variable, delta) \ + enet_at_atomic_inc((char *)(variable), -(delta), ENET_ATOMIC_SIZEOF(variable)) + +#elif defined(__GNUC__) || defined(__clang__) + + #if defined(__clang__) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) + #define AT_HAVE_ATOMICS + #endif + + /* We want to use __atomic built-ins if possible because the __sync primitives are + deprecated, because the __atomic build-ins allow us to use ENET_ATOMIC_WRITE on + uninitialized memory without running into undefined behavior, and because the + __atomic versions generate more efficient code since we don't need to rely on + CAS when we don't actually want it. + + Note that we use acquire-release memory order (like mutexes do). We could use + sequentially consistent memory order but that has lower performance and is + almost always unneeded. */ + #ifdef AT_HAVE_ATOMICS + #define ENET_ATOMIC_READ(ptr) __atomic_load_n((ptr), __ATOMIC_ACQUIRE) + #define ENET_ATOMIC_WRITE(ptr, value) __atomic_store_n((ptr), (value), __ATOMIC_RELEASE) + + #ifndef typeof + #define typeof __typeof__ + #endif + + /* clang_analyzer doesn't know that CAS writes to memory so it complains about + potentially lost data. Replace the code with the equivalent non-sync code. */ + #ifdef __clang_analyzer__ + + #define ENET_ATOMIC_CAS(ptr, old_value, new_value) \ + ({ \ + typeof(*(ptr)) ENET_ATOMIC_CAS_old_actual_ = (*(ptr)); \ + if (ATOMIC_CAS_old_actual_ == (old_value)) { \ + *(ptr) = new_value; \ + } \ + ENET_ATOMIC_CAS_old_actual_; \ + }) + + #else + + /* Could use __auto_type instead of typeof but that shouldn't work in C++. + The ({ }) syntax is a GCC extension called statement expression. It lets + us return a value out of the macro. + + TODO We should return bool here instead of the old value to avoid the ABA + problem. */ + #define ENET_ATOMIC_CAS(ptr, old_value, new_value) \ + ({ \ + typeof(*(ptr)) ENET_ATOMIC_CAS_expected_ = (old_value); \ + __atomic_compare_exchange_n((ptr), &ENET_ATOMIC_CAS_expected_, (new_value), false, \ + __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE); \ + ENET_ATOMIC_CAS_expected_; \ + }) + + #endif /* __clang_analyzer__ */ + + #define ENET_ATOMIC_INC(ptr) __atomic_fetch_add((ptr), 1, __ATOMIC_ACQ_REL) + #define ENET_ATOMIC_DEC(ptr) __atomic_fetch_sub((ptr), 1, __ATOMIC_ACQ_REL) + #define ENET_ATOMIC_INC_BY(ptr, delta) __atomic_fetch_add((ptr), (delta), __ATOMIC_ACQ_REL) + #define ENET_ATOMIC_DEC_BY(ptr, delta) __atomic_fetch_sub((ptr), (delta), __ATOMIC_ACQ_REL) + + #else + + #define ENET_ATOMIC_READ(variable) __sync_fetch_and_add(variable, 0) + #define ENET_ATOMIC_WRITE(variable, new_val) \ + (void) __sync_val_compare_and_swap((variable), *(variable), (new_val)) + #define ENET_ATOMIC_CAS(variable, old_value, new_val) \ + __sync_val_compare_and_swap((variable), (old_value), (new_val)) + #define ENET_ATOMIC_INC(variable) __sync_fetch_and_add((variable), 1) + #define ENET_ATOMIC_DEC(variable) __sync_fetch_and_sub((variable), 1) + #define ENET_ATOMIC_INC_BY(variable, delta) __sync_fetch_and_add((variable), (delta), 1) + #define ENET_ATOMIC_DEC_BY(variable, delta) __sync_fetch_and_sub((variable), (delta), 1) + + #endif /* AT_HAVE_ATOMICS */ + + #undef AT_HAVE_ATOMICS + +#endif /* defined(_MSC_VER) */ + +// =======================================================================// +// ! +// ! Callbacks +// ! +// =======================================================================// + + ENetCallbacks callbacks = { malloc, free, abort, enet_packet_create, enet_packet_destroy }; + + int enet_initialize_with_callbacks(ENetVersion version, const ENetCallbacks *inits) { + if (version < ENET_VERSION_CREATE(1, 3, 0)) { + return -1; + } + + if (inits->malloc != NULL || inits->free != NULL) { + if (inits->malloc == NULL || inits->free == NULL) { + return -1; + } + + callbacks.malloc = inits->malloc; + callbacks.free = inits->free; + } + + if (inits->no_memory != NULL) { + callbacks.no_memory = inits->no_memory; + } + + if (inits->packet_create != NULL || inits->packet_destroy != NULL) { + if (inits->packet_create == NULL || inits->packet_destroy == NULL) { + return -1; + } + + callbacks.packet_create = inits->packet_create; + callbacks.packet_destroy = inits->packet_destroy; + } + + return enet_initialize(); + } + + ENetVersion enet_linked_version(void) { + return ENET_VERSION; + } + + void * enet_malloc(size_t size) { + void *memory = callbacks.malloc(size); + + if (memory == NULL) { + callbacks.no_memory(); + } + + return memory; + } + + void enet_free(void *memory) { + callbacks.free(memory); + } + +// =======================================================================// +// ! +// ! List +// ! +// =======================================================================// + + void enet_list_clear(ENetList *list) { + list->sentinel.next = &list->sentinel; + list->sentinel.previous = &list->sentinel; + } + + ENetListIterator enet_list_insert(ENetListIterator position, void *data) { + ENetListIterator result = (ENetListIterator)data; + + result->previous = position->previous; + result->next = position; + + result->previous->next = result; + position->previous = result; + + return result; + } + + void *enet_list_remove(ENetListIterator position) { + position->previous->next = position->next; + position->next->previous = position->previous; + + return position; + } + + ENetListIterator enet_list_move(ENetListIterator position, void *dataFirst, void *dataLast) { + ENetListIterator first = (ENetListIterator)dataFirst; + ENetListIterator last = (ENetListIterator)dataLast; + + first->previous->next = last->next; + last->next->previous = first->previous; + + first->previous = position->previous; + last->next = position; + + first->previous->next = first; + position->previous = last; + + return first; + } + + size_t enet_list_size(ENetList *list) { + size_t size = 0; + ENetListIterator position; + + for (position = enet_list_begin(list); position != enet_list_end(list); position = enet_list_next(position)) { + ++size; + } + + return size; + } + +// =======================================================================// +// ! +// ! Packet +// ! +// =======================================================================// + + /** + * Creates a packet that may be sent to a peer. + * @param data initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL. + * @param dataLength size of the data allocated for this packet + * @param flags flags for this packet as described for the ENetPacket structure. + * @returns the packet on success, NULL on failure + */ + ENetPacket *enet_packet_create(const void *data, size_t dataLength, enet_uint32 flags) { + ENetPacket *packet; + if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) { + packet = (ENetPacket *)enet_malloc(sizeof (ENetPacket)); + if (packet == NULL) { + return NULL; + } + + packet->data = (enet_uint8 *)data; + } + else { + packet = (ENetPacket *)enet_malloc(sizeof (ENetPacket) + dataLength); + if (packet == NULL) { + return NULL; + } + + packet->data = (enet_uint8 *)packet + sizeof(ENetPacket); + + if (data != NULL) { + memcpy(packet->data, data, dataLength); + } + } + + packet->referenceCount = 0; + packet->flags = flags; + packet->dataLength = dataLength; + packet->freeCallback = NULL; + packet->userData = NULL; + + return packet; + } + + ENetPacket *enet_packet_create_offset(const void *data, size_t dataLength, size_t dataOffset, enet_uint32 flags) { + ENetPacket *packet; + if (flags & ENET_PACKET_FLAG_NO_ALLOCATE) { + packet = (ENetPacket *)enet_malloc(sizeof (ENetPacket)); + if (packet == NULL) { + return NULL; + } + + packet->data = (enet_uint8 *)data; + } + else { + packet = (ENetPacket *)enet_malloc(sizeof (ENetPacket) + dataLength + dataOffset); + if (packet == NULL) { + return NULL; + } + + packet->data = (enet_uint8 *)packet + sizeof(ENetPacket); + + if (data != NULL) { + memcpy(packet->data + dataOffset, data, dataLength); + } + } + + packet->referenceCount = 0; + packet->flags = flags; + packet->dataLength = dataLength + dataOffset; + packet->freeCallback = NULL; + packet->userData = NULL; + + return packet; + } + + ENetPacket *enet_packet_copy(ENetPacket *packet) { + return enet_packet_create(packet->data, packet->dataLength, packet->flags); + } + + /** + * Destroys the packet and deallocates its data. + * @param packet packet to be destroyed + */ + void enet_packet_destroy(ENetPacket *packet) { + if (packet == NULL) { + return; + } + + if (packet->freeCallback != NULL) { + (*packet->freeCallback)((void *)packet); + } + + enet_free(packet); + } + + static int initializedCRC32 = 0; + static enet_uint32 crcTable[256]; + + static enet_uint32 reflect_crc(int val, int bits) { + int result = 0, bit; + + for (bit = 0; bit < bits; bit++) { + if (val & 1) { result |= 1 << (bits - 1 - bit); } + val >>= 1; + } + + return result; + } + + static void initialize_crc32(void) { + int byte; + + for (byte = 0; byte < 256; ++byte) { + enet_uint32 crc = reflect_crc(byte, 8) << 24; + int offset; + + for (offset = 0; offset < 8; ++offset) { + if (crc & 0x80000000) { + crc = (crc << 1) ^ 0x04c11db7; + } else { + crc <<= 1; + } + } + + crcTable[byte] = reflect_crc(crc, 32); + } + + initializedCRC32 = 1; + } + + enet_uint32 enet_crc32(const ENetBuffer *buffers, size_t bufferCount) { + enet_uint32 crc = 0xFFFFFFFF; + + if (!initializedCRC32) { initialize_crc32(); } + + while (bufferCount-- > 0) { + const enet_uint8 *data = (const enet_uint8 *)buffers->data; + const enet_uint8 *dataEnd = &data[buffers->dataLength]; + + while (data < dataEnd) { + crc = (crc >> 8) ^ crcTable[(crc & 0xFF) ^ *data++]; + } + + ++buffers; + } + + return ENET_HOST_TO_NET_32(~crc); + } + +// =======================================================================// +// ! +// ! Protocol +// ! +// =======================================================================// + + static size_t commandSizes[ENET_PROTOCOL_COMMAND_COUNT] = { + 0, + sizeof(ENetProtocolAcknowledge), + sizeof(ENetProtocolConnect), + sizeof(ENetProtocolVerifyConnect), + sizeof(ENetProtocolDisconnect), + sizeof(ENetProtocolPing), + sizeof(ENetProtocolSendReliable), + sizeof(ENetProtocolSendUnreliable), + sizeof(ENetProtocolSendFragment), + sizeof(ENetProtocolSendUnsequenced), + sizeof(ENetProtocolBandwidthLimit), + sizeof(ENetProtocolThrottleConfigure), + sizeof(ENetProtocolSendFragment) + }; + + size_t enet_protocol_command_size(enet_uint8 commandNumber) { + return commandSizes[commandNumber & ENET_PROTOCOL_COMMAND_MASK]; + } + + static void enet_protocol_change_state(ENetHost *host, ENetPeer *peer, ENetPeerState state) { + ENET_UNUSED(host) + + if (state == ENET_PEER_STATE_CONNECTED || state == ENET_PEER_STATE_DISCONNECT_LATER) { + enet_peer_on_connect(peer); + } else { + enet_peer_on_disconnect(peer); + } + + peer->state = state; + } + + static void enet_protocol_dispatch_state(ENetHost *host, ENetPeer *peer, ENetPeerState state) { + enet_protocol_change_state(host, peer, state); + + if (!peer->needsDispatch) { + enet_list_insert(enet_list_end(&host->dispatchQueue), &peer->dispatchList); + peer->needsDispatch = 1; + } + } + + static int enet_protocol_dispatch_incoming_commands(ENetHost *host, ENetEvent *event) { + while (!enet_list_empty(&host->dispatchQueue)) { + ENetPeer *peer = (ENetPeer *) enet_list_remove(enet_list_begin(&host->dispatchQueue)); + peer->needsDispatch = 0; + + switch (peer->state) { + case ENET_PEER_STATE_CONNECTION_PENDING: + case ENET_PEER_STATE_CONNECTION_SUCCEEDED: + enet_protocol_change_state(host, peer, ENET_PEER_STATE_CONNECTED); + + event->type = ENET_EVENT_TYPE_CONNECT; + event->peer = peer; + event->data = peer->eventData; + + return 1; + + case ENET_PEER_STATE_ZOMBIE: + host->recalculateBandwidthLimits = 1; + + event->type = ENET_EVENT_TYPE_DISCONNECT; + event->peer = peer; + event->data = peer->eventData; + + enet_peer_reset(peer); + + return 1; + + case ENET_PEER_STATE_CONNECTED: + if (enet_list_empty(&peer->dispatchedCommands)) { + continue; + } + + event->packet = enet_peer_receive(peer, &event->channelID); + if (event->packet == NULL) { + continue; + } + + event->type = ENET_EVENT_TYPE_RECEIVE; + event->peer = peer; + + if (!enet_list_empty(&peer->dispatchedCommands)) { + peer->needsDispatch = 1; + enet_list_insert(enet_list_end(&host->dispatchQueue), &peer->dispatchList); + } + + return 1; + + default: + break; + } + } + + return 0; + } /* enet_protocol_dispatch_incoming_commands */ + + static void enet_protocol_notify_connect(ENetHost *host, ENetPeer *peer, ENetEvent *event) { + host->recalculateBandwidthLimits = 1; + + if (event != NULL) { + enet_protocol_change_state(host, peer, ENET_PEER_STATE_CONNECTED); + + peer->totalDataSent = 0; + peer->totalDataReceived = 0; + peer->totalPacketsSent = 0; + peer->totalPacketsLost = 0; + + event->type = ENET_EVENT_TYPE_CONNECT; + event->peer = peer; + event->data = peer->eventData; + } else { + enet_protocol_dispatch_state(host, peer, peer->state == ENET_PEER_STATE_CONNECTING ? ENET_PEER_STATE_CONNECTION_SUCCEEDED : ENET_PEER_STATE_CONNECTION_PENDING); + } + } + + static void enet_protocol_notify_disconnect(ENetHost *host, ENetPeer *peer, ENetEvent *event) { + if (peer->state >= ENET_PEER_STATE_CONNECTION_PENDING) { + host->recalculateBandwidthLimits = 1; + } + + if (peer->state != ENET_PEER_STATE_CONNECTING && peer->state < ENET_PEER_STATE_CONNECTION_SUCCEEDED) { + enet_peer_reset(peer); + } else if (event != NULL) { + event->type = ENET_EVENT_TYPE_DISCONNECT; + event->peer = peer; + event->data = 0; + + enet_peer_reset(peer); + } else { + peer->eventData = 0; + enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE); + } + } + + static void enet_protocol_notify_disconnect_timeout (ENetHost * host, ENetPeer * peer, ENetEvent * event) { + if (peer->state >= ENET_PEER_STATE_CONNECTION_PENDING) { + host->recalculateBandwidthLimits = 1; + } + + if (peer->state != ENET_PEER_STATE_CONNECTING && peer->state < ENET_PEER_STATE_CONNECTION_SUCCEEDED) { + enet_peer_reset (peer); + } + else if (event != NULL) { + event->type = ENET_EVENT_TYPE_DISCONNECT_TIMEOUT; + event->peer = peer; + event->data = 0; + + enet_peer_reset(peer); + } + else { + peer->eventData = 0; + enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE); + } + } + + static void enet_protocol_remove_sent_unreliable_commands(ENetPeer *peer) { + ENetOutgoingCommand *outgoingCommand; + + while (!enet_list_empty(&peer->sentUnreliableCommands)) { + outgoingCommand = (ENetOutgoingCommand *) enet_list_front(&peer->sentUnreliableCommands); + enet_list_remove(&outgoingCommand->outgoingCommandList); + + if (outgoingCommand->packet != NULL) { + --outgoingCommand->packet->referenceCount; + + if (outgoingCommand->packet->referenceCount == 0) { + outgoingCommand->packet->flags |= ENET_PACKET_FLAG_SENT; + callbacks.packet_destroy(outgoingCommand->packet); + } + } + + enet_free(outgoingCommand); + } + } + + static ENetProtocolCommand enet_protocol_remove_sent_reliable_command(ENetPeer *peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID) { + ENetOutgoingCommand *outgoingCommand = NULL; + ENetListIterator currentCommand; + ENetProtocolCommand commandNumber; + int wasSent = 1; + + for (currentCommand = enet_list_begin(&peer->sentReliableCommands); + currentCommand != enet_list_end(&peer->sentReliableCommands); + currentCommand = enet_list_next(currentCommand) + ) { + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + + if (outgoingCommand->reliableSequenceNumber == reliableSequenceNumber && outgoingCommand->command.header.channelID == channelID) { + break; + } + } + + if (currentCommand == enet_list_end(&peer->sentReliableCommands)) { + for (currentCommand = enet_list_begin(&peer->outgoingReliableCommands); + currentCommand != enet_list_end(&peer->outgoingReliableCommands); + currentCommand = enet_list_next(currentCommand) + ) { + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + + if (outgoingCommand->sendAttempts < 1) { return ENET_PROTOCOL_COMMAND_NONE; } + if (outgoingCommand->reliableSequenceNumber == reliableSequenceNumber && outgoingCommand->command.header.channelID == channelID) { + break; + } + } + + if (currentCommand == enet_list_end(&peer->outgoingReliableCommands)) { + return ENET_PROTOCOL_COMMAND_NONE; + } + + wasSent = 0; + } + + if (outgoingCommand == NULL) { + return ENET_PROTOCOL_COMMAND_NONE; + } + + if (channelID < peer->channelCount) { + ENetChannel *channel = &peer->channels[channelID]; + enet_uint16 reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + if (channel->reliableWindows[reliableWindow] > 0) { + --channel->reliableWindows[reliableWindow]; + if (!channel->reliableWindows[reliableWindow]) { + channel->usedReliableWindows &= ~(1 << reliableWindow); + } + } + } + + commandNumber = (ENetProtocolCommand) (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK); + enet_list_remove(&outgoingCommand->outgoingCommandList); + + if (outgoingCommand->packet != NULL) { + if (wasSent) { + peer->reliableDataInTransit -= outgoingCommand->fragmentLength; + } + + --outgoingCommand->packet->referenceCount; + + if (outgoingCommand->packet->referenceCount == 0) { + outgoingCommand->packet->flags |= ENET_PACKET_FLAG_SENT; + callbacks.packet_destroy(outgoingCommand->packet); + } + } + + enet_free(outgoingCommand); + + if (enet_list_empty(&peer->sentReliableCommands)) { + return commandNumber; + } + + outgoingCommand = (ENetOutgoingCommand *) enet_list_front(&peer->sentReliableCommands); + peer->nextTimeout = outgoingCommand->sentTime + outgoingCommand->roundTripTimeout; + + return commandNumber; + } /* enet_protocol_remove_sent_reliable_command */ + + static ENetPeer * enet_protocol_handle_connect(ENetHost *host, ENetProtocolHeader *header, ENetProtocol *command) { + ENET_UNUSED(header) + + enet_uint8 incomingSessionID, outgoingSessionID; + enet_uint32 mtu, windowSize; + ENetChannel *channel; + size_t channelCount, duplicatePeers = 0; + ENetPeer *currentPeer, *peer = NULL; + ENetProtocol verifyCommand; + + channelCount = ENET_NET_TO_HOST_32(command->connect.channelCount); + + if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { + return NULL; + } + + for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) { + if (currentPeer->state == ENET_PEER_STATE_DISCONNECTED) { + if (peer == NULL) { + peer = currentPeer; + } + } else if (currentPeer->state != ENET_PEER_STATE_CONNECTING && in6_equal(currentPeer->address.host, host->receivedAddress.host)) { + if (currentPeer->address.port == host->receivedAddress.port && currentPeer->connectID == command->connect.connectID) { + return NULL; + } + + ++duplicatePeers; + } + } + + if (peer == NULL || duplicatePeers >= host->duplicatePeers) { + return NULL; + } + + if (channelCount > host->channelLimit) { + channelCount = host->channelLimit; + } + peer->channels = (ENetChannel *) enet_malloc(channelCount * sizeof(ENetChannel)); + if (peer->channels == NULL) { + return NULL; + } + peer->channelCount = channelCount; + peer->state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT; + peer->connectID = command->connect.connectID; + peer->address = host->receivedAddress; + peer->outgoingPeerID = ENET_NET_TO_HOST_16(command->connect.outgoingPeerID); + peer->incomingBandwidth = ENET_NET_TO_HOST_32(command->connect.incomingBandwidth); + peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->connect.outgoingBandwidth); + peer->packetThrottleInterval = ENET_NET_TO_HOST_32(command->connect.packetThrottleInterval); + peer->packetThrottleAcceleration = ENET_NET_TO_HOST_32(command->connect.packetThrottleAcceleration); + peer->packetThrottleDeceleration = ENET_NET_TO_HOST_32(command->connect.packetThrottleDeceleration); + peer->eventData = ENET_NET_TO_HOST_32(command->connect.data); + + incomingSessionID = command->connect.incomingSessionID == 0xFF ? peer->outgoingSessionID : command->connect.incomingSessionID; + incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); + if (incomingSessionID == peer->outgoingSessionID) { + incomingSessionID = (incomingSessionID + 1) + & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); + } + peer->outgoingSessionID = incomingSessionID; + + outgoingSessionID = command->connect.outgoingSessionID == 0xFF ? peer->incomingSessionID : command->connect.outgoingSessionID; + outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); + if (outgoingSessionID == peer->incomingSessionID) { + outgoingSessionID = (outgoingSessionID + 1) + & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT); + } + peer->incomingSessionID = outgoingSessionID; + + for (channel = peer->channels; channel < &peer->channels[channelCount]; ++channel) { + channel->outgoingReliableSequenceNumber = 0; + channel->outgoingUnreliableSequenceNumber = 0; + channel->incomingReliableSequenceNumber = 0; + channel->incomingUnreliableSequenceNumber = 0; + + enet_list_clear(&channel->incomingReliableCommands); + enet_list_clear(&channel->incomingUnreliableCommands); + + channel->usedReliableWindows = 0; + memset(channel->reliableWindows, 0, sizeof(channel->reliableWindows)); + } + + mtu = ENET_NET_TO_HOST_32(command->connect.mtu); + + if (mtu < ENET_PROTOCOL_MINIMUM_MTU) { + mtu = ENET_PROTOCOL_MINIMUM_MTU; + } else if (mtu > ENET_PROTOCOL_MAXIMUM_MTU) { + mtu = ENET_PROTOCOL_MAXIMUM_MTU; + } + + peer->mtu = mtu; + + if (host->outgoingBandwidth == 0 && peer->incomingBandwidth == 0) { + peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + } else if (host->outgoingBandwidth == 0 || peer->incomingBandwidth == 0) { + peer->windowSize = (ENET_MAX(host->outgoingBandwidth, peer->incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + } else { + peer->windowSize = (ENET_MIN(host->outgoingBandwidth, peer->incomingBandwidth) / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + } + + if (peer->windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) { + peer->windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + } else if (peer->windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) { + peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + } + + if (host->incomingBandwidth == 0) { + windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + } else { + windowSize = (host->incomingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + } + + if (windowSize > ENET_NET_TO_HOST_32(command->connect.windowSize)) { + windowSize = ENET_NET_TO_HOST_32(command->connect.windowSize); + } + + if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) { + windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + } else if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) { + windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + } + + verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; + verifyCommand.header.channelID = 0xFF; + verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16(peer->incomingPeerID); + verifyCommand.verifyConnect.incomingSessionID = incomingSessionID; + verifyCommand.verifyConnect.outgoingSessionID = outgoingSessionID; + verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_32(peer->mtu); + verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32(windowSize); + verifyCommand.verifyConnect.channelCount = ENET_HOST_TO_NET_32(channelCount); + verifyCommand.verifyConnect.incomingBandwidth = ENET_HOST_TO_NET_32(host->incomingBandwidth); + verifyCommand.verifyConnect.outgoingBandwidth = ENET_HOST_TO_NET_32(host->outgoingBandwidth); + verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32(peer->packetThrottleInterval); + verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32(peer->packetThrottleAcceleration); + verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32(peer->packetThrottleDeceleration); + verifyCommand.verifyConnect.connectID = peer->connectID; + + enet_peer_queue_outgoing_command(peer, &verifyCommand, NULL, 0, 0); + return peer; + } /* enet_protocol_handle_connect */ + + static int enet_protocol_handle_send_reliable(ENetHost *host, ENetPeer *peer, const ENetProtocol *command, enet_uint8 **currentData) { + size_t dataLength; + + if (command->header.channelID >= peer->channelCount || (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) { + return -1; + } + + dataLength = ENET_NET_TO_HOST_16(command->sendReliable.dataLength); + *currentData += dataLength; + + if (dataLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) { + return -1; + } + + if (enet_peer_queue_incoming_command(peer, command, (const enet_uint8 *) command + sizeof(ENetProtocolSendReliable), dataLength, ENET_PACKET_FLAG_RELIABLE, 0) == NULL) { + return -1; + } + + return 0; + } + + static int enet_protocol_handle_send_unsequenced(ENetHost *host, ENetPeer *peer, const ENetProtocol *command, enet_uint8 **currentData) { + enet_uint32 unsequencedGroup, index; + size_t dataLength; + + if (command->header.channelID >= peer->channelCount || (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) { + return -1; + } + + dataLength = ENET_NET_TO_HOST_16(command->sendUnsequenced.dataLength); + *currentData += dataLength; + if (dataLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) { + return -1; + } + + unsequencedGroup = ENET_NET_TO_HOST_16(command->sendUnsequenced.unsequencedGroup); + index = unsequencedGroup % ENET_PEER_UNSEQUENCED_WINDOW_SIZE; + + if (unsequencedGroup < peer->incomingUnsequencedGroup) { + unsequencedGroup += 0x10000; + } + + if (unsequencedGroup >= (enet_uint32) peer->incomingUnsequencedGroup + ENET_PEER_FREE_UNSEQUENCED_WINDOWS * ENET_PEER_UNSEQUENCED_WINDOW_SIZE) { + return 0; + } + + unsequencedGroup &= 0xFFFF; + + if (unsequencedGroup - index != peer->incomingUnsequencedGroup) { + peer->incomingUnsequencedGroup = unsequencedGroup - index; + memset(peer->unsequencedWindow, 0, sizeof(peer->unsequencedWindow)); + } else if (peer->unsequencedWindow[index / 32] & (1 << (index % 32))) { + return 0; + } + + if (enet_peer_queue_incoming_command(peer, command, (const enet_uint8 *) command + sizeof(ENetProtocolSendUnsequenced), dataLength, ENET_PACKET_FLAG_UNSEQUENCED,0) == NULL) { + return -1; + } + + peer->unsequencedWindow[index / 32] |= 1 << (index % 32); + + return 0; + } /* enet_protocol_handle_send_unsequenced */ + + static int enet_protocol_handle_send_unreliable(ENetHost *host, ENetPeer *peer, const ENetProtocol *command, + enet_uint8 **currentData) { + size_t dataLength; + + if (command->header.channelID >= peer->channelCount || + (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) + { + return -1; + } + + dataLength = ENET_NET_TO_HOST_16(command->sendUnreliable.dataLength); + *currentData += dataLength; + if (dataLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) { + return -1; + } + + if (enet_peer_queue_incoming_command(peer, command, (const enet_uint8 *) command + sizeof(ENetProtocolSendUnreliable), dataLength, 0, 0) == NULL) { + return -1; + } + + return 0; + } + + static int enet_protocol_handle_send_fragment(ENetHost *host, ENetPeer *peer, const ENetProtocol *command, enet_uint8 **currentData) { + enet_uint32 fragmentNumber, fragmentCount, fragmentOffset, fragmentLength, startSequenceNumber, totalLength; + ENetChannel *channel; + enet_uint16 startWindow, currentWindow; + ENetListIterator currentCommand; + ENetIncomingCommand *startCommand = NULL; + + if (command->header.channelID >= peer->channelCount || (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) { + return -1; + } + + fragmentLength = ENET_NET_TO_HOST_16(command->sendFragment.dataLength); + *currentData += fragmentLength; + if (fragmentLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) { + return -1; + } + + channel = &peer->channels[command->header.channelID]; + startSequenceNumber = ENET_NET_TO_HOST_16(command->sendFragment.startSequenceNumber); + startWindow = startSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + currentWindow = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + + if (startSequenceNumber < channel->incomingReliableSequenceNumber) { + startWindow += ENET_PEER_RELIABLE_WINDOWS; + } + + if (startWindow < currentWindow || startWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) { + return 0; + } + + fragmentNumber = ENET_NET_TO_HOST_32(command->sendFragment.fragmentNumber); + fragmentCount = ENET_NET_TO_HOST_32(command->sendFragment.fragmentCount); + fragmentOffset = ENET_NET_TO_HOST_32(command->sendFragment.fragmentOffset); + totalLength = ENET_NET_TO_HOST_32(command->sendFragment.totalLength); + + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || + fragmentNumber >= fragmentCount || + totalLength > host->maximumPacketSize || + fragmentOffset >= totalLength || + fragmentLength > totalLength - fragmentOffset + ) { + return -1; + } + + for (currentCommand = enet_list_previous(enet_list_end(&channel->incomingReliableCommands)); + currentCommand != enet_list_end(&channel->incomingReliableCommands); + currentCommand = enet_list_previous(currentCommand) + ) { + ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand; + + if (startSequenceNumber >= channel->incomingReliableSequenceNumber) { + if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) { + continue; + } + } else if (incomingCommand->reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { + break; + } + + if (incomingCommand->reliableSequenceNumber <= startSequenceNumber) { + if (incomingCommand->reliableSequenceNumber < startSequenceNumber) { + break; + } + + if ((incomingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK) != + ENET_PROTOCOL_COMMAND_SEND_FRAGMENT || + totalLength != incomingCommand->packet->dataLength || + fragmentCount != incomingCommand->fragmentCount + ) { + return -1; + } + + startCommand = incomingCommand; + break; + } + } + + if (startCommand == NULL) { + ENetProtocol hostCommand = *command; + hostCommand.header.reliableSequenceNumber = startSequenceNumber; + startCommand = enet_peer_queue_incoming_command(peer, &hostCommand, NULL, totalLength, ENET_PACKET_FLAG_RELIABLE, fragmentCount); + if (startCommand == NULL) { + return -1; + } + } + + if ((startCommand->fragments[fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0) { + --startCommand->fragmentsRemaining; + startCommand->fragments[fragmentNumber / 32] |= (1 << (fragmentNumber % 32)); + + if (fragmentOffset + fragmentLength > startCommand->packet->dataLength) { + fragmentLength = startCommand->packet->dataLength - fragmentOffset; + } + + memcpy(startCommand->packet->data + fragmentOffset, (enet_uint8 *) command + sizeof(ENetProtocolSendFragment), fragmentLength); + + if (startCommand->fragmentsRemaining <= 0) { + enet_peer_dispatch_incoming_reliable_commands(peer, channel); + } + } + + return 0; + } /* enet_protocol_handle_send_fragment */ + + static int enet_protocol_handle_send_unreliable_fragment(ENetHost *host, ENetPeer *peer, const ENetProtocol *command, enet_uint8 **currentData) { + enet_uint32 fragmentNumber, fragmentCount, fragmentOffset, fragmentLength, reliableSequenceNumber, startSequenceNumber, totalLength; + enet_uint16 reliableWindow, currentWindow; + ENetChannel *channel; + ENetListIterator currentCommand; + ENetIncomingCommand *startCommand = NULL; + + if (command->header.channelID >= peer->channelCount || (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER)) { + return -1; + } + + fragmentLength = ENET_NET_TO_HOST_16(command->sendFragment.dataLength); + *currentData += fragmentLength; + if (fragmentLength > host->maximumPacketSize || *currentData < host->receivedData || *currentData > &host->receivedData[host->receivedDataLength]) { + return -1; + } + + channel = &peer->channels[command->header.channelID]; + reliableSequenceNumber = command->header.reliableSequenceNumber; + startSequenceNumber = ENET_NET_TO_HOST_16(command->sendFragment.startSequenceNumber); + + reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + currentWindow = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + + if (reliableSequenceNumber < channel->incomingReliableSequenceNumber) { + reliableWindow += ENET_PEER_RELIABLE_WINDOWS; + } + + if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) { + return 0; + } + + if (reliableSequenceNumber == channel->incomingReliableSequenceNumber && startSequenceNumber <= channel->incomingUnreliableSequenceNumber) { + return 0; + } + + fragmentNumber = ENET_NET_TO_HOST_32(command->sendFragment.fragmentNumber); + fragmentCount = ENET_NET_TO_HOST_32(command->sendFragment.fragmentCount); + fragmentOffset = ENET_NET_TO_HOST_32(command->sendFragment.fragmentOffset); + totalLength = ENET_NET_TO_HOST_32(command->sendFragment.totalLength); + + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT || + fragmentNumber >= fragmentCount || + totalLength > host->maximumPacketSize || + fragmentOffset >= totalLength || + fragmentLength > totalLength - fragmentOffset + ) { + return -1; + } + + for (currentCommand = enet_list_previous(enet_list_end(&channel->incomingUnreliableCommands)); + currentCommand != enet_list_end(&channel->incomingUnreliableCommands); + currentCommand = enet_list_previous(currentCommand) + ) { + ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand; + + if (reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { + if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) { + continue; + } + } else if (incomingCommand->reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { + break; + } + + if (incomingCommand->reliableSequenceNumber < reliableSequenceNumber) { + break; + } + + if (incomingCommand->reliableSequenceNumber > reliableSequenceNumber) { + continue; + } + + if (incomingCommand->unreliableSequenceNumber <= startSequenceNumber) { + if (incomingCommand->unreliableSequenceNumber < startSequenceNumber) { + break; + } + + if ((incomingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK) != + ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT || + totalLength != incomingCommand->packet->dataLength || + fragmentCount != incomingCommand->fragmentCount + ) { + return -1; + } + + startCommand = incomingCommand; + break; + } + } + + if (startCommand == NULL) { + startCommand = enet_peer_queue_incoming_command(peer, command, NULL, totalLength, + ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT, fragmentCount); + if (startCommand == NULL) { + return -1; + } + } + + if ((startCommand->fragments[fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0) { + --startCommand->fragmentsRemaining; + startCommand->fragments[fragmentNumber / 32] |= (1 << (fragmentNumber % 32)); + + if (fragmentOffset + fragmentLength > startCommand->packet->dataLength) { + fragmentLength = startCommand->packet->dataLength - fragmentOffset; + } + + memcpy(startCommand->packet->data + fragmentOffset, (enet_uint8 *) command + sizeof(ENetProtocolSendFragment), fragmentLength); + + if (startCommand->fragmentsRemaining <= 0) { + enet_peer_dispatch_incoming_unreliable_commands(peer, channel); + } + } + + return 0; + } /* enet_protocol_handle_send_unreliable_fragment */ + + static int enet_protocol_handle_ping(ENetHost *host, ENetPeer *peer, const ENetProtocol *command) { + ENET_UNUSED(host) + ENET_UNUSED(command) + + if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { + return -1; + } + + return 0; + } + + static int enet_protocol_handle_bandwidth_limit(ENetHost *host, ENetPeer *peer, const ENetProtocol *command) { + if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { + return -1; + } + if (peer->incomingBandwidth != 0) { + --host->bandwidthLimitedPeers; + } + + peer->incomingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.incomingBandwidth); + if (peer->incomingBandwidth != 0) { + ++host->bandwidthLimitedPeers; + } + + peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->bandwidthLimit.outgoingBandwidth); + + if (peer->incomingBandwidth == 0 && host->outgoingBandwidth == 0) { + peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + } else if (peer->incomingBandwidth == 0 || host->outgoingBandwidth == 0) { + peer->windowSize = (ENET_MAX(peer->incomingBandwidth, host->outgoingBandwidth) + / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + } else { + peer->windowSize = (ENET_MIN(peer->incomingBandwidth, host->outgoingBandwidth) + / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + } + + if (peer->windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) { + peer->windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + } else if (peer->windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) { + peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + } + + return 0; + } /* enet_protocol_handle_bandwidth_limit */ + + static int enet_protocol_handle_throttle_configure(ENetHost *host, ENetPeer *peer, const ENetProtocol *command) { + ENET_UNUSED(host) + + if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { + return -1; + } + + peer->packetThrottleInterval = ENET_NET_TO_HOST_32(command->throttleConfigure.packetThrottleInterval); + peer->packetThrottleAcceleration = ENET_NET_TO_HOST_32(command->throttleConfigure.packetThrottleAcceleration); + peer->packetThrottleDeceleration = ENET_NET_TO_HOST_32(command->throttleConfigure.packetThrottleDeceleration); + + return 0; + } + + static int enet_protocol_handle_disconnect(ENetHost *host, ENetPeer *peer, const ENetProtocol *command) { + if (peer->state == ENET_PEER_STATE_DISCONNECTED || peer->state == ENET_PEER_STATE_ZOMBIE || + peer->state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT + ) { + return 0; + } + + enet_peer_reset_queues(peer); + + if (peer->state == ENET_PEER_STATE_CONNECTION_SUCCEEDED || peer->state == ENET_PEER_STATE_DISCONNECTING || peer->state == ENET_PEER_STATE_CONNECTING) { + enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE); + } + else if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { + if (peer->state == ENET_PEER_STATE_CONNECTION_PENDING) { host->recalculateBandwidthLimits = 1; } + enet_peer_reset(peer); + } + else if (command->header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { + enet_protocol_change_state(host, peer, ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT); + } + else { + enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE); + } + + if (peer->state != ENET_PEER_STATE_DISCONNECTED) { + peer->eventData = ENET_NET_TO_HOST_32(command->disconnect.data); + } + + return 0; + } + + static int enet_protocol_handle_acknowledge(ENetHost *host, ENetEvent *event, ENetPeer *peer, const ENetProtocol *command) { + enet_uint32 roundTripTime, receivedSentTime, receivedReliableSequenceNumber; + ENetProtocolCommand commandNumber; + + if (peer->state == ENET_PEER_STATE_DISCONNECTED || peer->state == ENET_PEER_STATE_ZOMBIE) { + return 0; + } + + receivedSentTime = ENET_NET_TO_HOST_16(command->acknowledge.receivedSentTime); + receivedSentTime |= host->serviceTime & 0xFFFF0000; + if ((receivedSentTime & 0x8000) > (host->serviceTime & 0x8000)) { + receivedSentTime -= 0x10000; + } + + if (ENET_TIME_LESS(host->serviceTime, receivedSentTime)) { + return 0; + } + + peer->lastReceiveTime = host->serviceTime; + peer->earliestTimeout = 0; + roundTripTime = ENET_TIME_DIFFERENCE(host->serviceTime, receivedSentTime); + + enet_peer_throttle(peer, roundTripTime); + peer->roundTripTimeVariance -= peer->roundTripTimeVariance / 4; + + if (roundTripTime >= peer->roundTripTime) { + peer->roundTripTime += (roundTripTime - peer->roundTripTime) / 8; + peer->roundTripTimeVariance += (roundTripTime - peer->roundTripTime) / 4; + } else { + peer->roundTripTime -= (peer->roundTripTime - roundTripTime) / 8; + peer->roundTripTimeVariance += (peer->roundTripTime - roundTripTime) / 4; + } + + if (peer->roundTripTime < peer->lowestRoundTripTime) { + peer->lowestRoundTripTime = peer->roundTripTime; + } + + if (peer->roundTripTimeVariance > peer->highestRoundTripTimeVariance) { + peer->highestRoundTripTimeVariance = peer->roundTripTimeVariance; + } + + if (peer->packetThrottleEpoch == 0 || + ENET_TIME_DIFFERENCE(host->serviceTime, peer->packetThrottleEpoch) >= peer->packetThrottleInterval + ) { + peer->lastRoundTripTime = peer->lowestRoundTripTime; + peer->lastRoundTripTimeVariance = peer->highestRoundTripTimeVariance; + peer->lowestRoundTripTime = peer->roundTripTime; + peer->highestRoundTripTimeVariance = peer->roundTripTimeVariance; + peer->packetThrottleEpoch = host->serviceTime; + } + + receivedReliableSequenceNumber = ENET_NET_TO_HOST_16(command->acknowledge.receivedReliableSequenceNumber); + commandNumber = enet_protocol_remove_sent_reliable_command(peer, receivedReliableSequenceNumber, command->header.channelID); + + switch (peer->state) { + case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT: + if (commandNumber != ENET_PROTOCOL_COMMAND_VERIFY_CONNECT) { + return -1; + } + + enet_protocol_notify_connect(host, peer, event); + break; + + case ENET_PEER_STATE_DISCONNECTING: + if (commandNumber != ENET_PROTOCOL_COMMAND_DISCONNECT) { + return -1; + } + + enet_protocol_notify_disconnect(host, peer, event); + break; + + case ENET_PEER_STATE_DISCONNECT_LATER: + if (enet_list_empty(&peer->outgoingReliableCommands) && + enet_list_empty(&peer->outgoingUnreliableCommands) && + enet_list_empty(&peer->sentReliableCommands)) + { + enet_peer_disconnect(peer, peer->eventData); + } + break; + + default: + break; + } + + return 0; + } /* enet_protocol_handle_acknowledge */ + + static int enet_protocol_handle_verify_connect(ENetHost *host, ENetEvent *event, ENetPeer *peer, const ENetProtocol *command) { + enet_uint32 mtu, windowSize; + size_t channelCount; + + if (peer->state != ENET_PEER_STATE_CONNECTING) { + return 0; + } + + channelCount = ENET_NET_TO_HOST_32(command->verifyConnect.channelCount); + + if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT || + ENET_NET_TO_HOST_32(command->verifyConnect.packetThrottleInterval) != peer->packetThrottleInterval || + ENET_NET_TO_HOST_32(command->verifyConnect.packetThrottleAcceleration) != peer->packetThrottleAcceleration || + ENET_NET_TO_HOST_32(command->verifyConnect.packetThrottleDeceleration) != peer->packetThrottleDeceleration || + command->verifyConnect.connectID != peer->connectID + ) { + peer->eventData = 0; + enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE); + return -1; + } + + enet_protocol_remove_sent_reliable_command(peer, 1, 0xFF); + + if (channelCount < peer->channelCount) { + peer->channelCount = channelCount; + } + + peer->outgoingPeerID = ENET_NET_TO_HOST_16(command->verifyConnect.outgoingPeerID); + peer->incomingSessionID = command->verifyConnect.incomingSessionID; + peer->outgoingSessionID = command->verifyConnect.outgoingSessionID; + + mtu = ENET_NET_TO_HOST_32(command->verifyConnect.mtu); + + if (mtu < ENET_PROTOCOL_MINIMUM_MTU) { + mtu = ENET_PROTOCOL_MINIMUM_MTU; + } else if (mtu > ENET_PROTOCOL_MAXIMUM_MTU) { + mtu = ENET_PROTOCOL_MAXIMUM_MTU; + } + + if (mtu < peer->mtu) { + peer->mtu = mtu; + } + + windowSize = ENET_NET_TO_HOST_32(command->verifyConnect.windowSize); + if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) { + windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + } + + if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) { + windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + } + + if (windowSize < peer->windowSize) { + peer->windowSize = windowSize; + } + + peer->incomingBandwidth = ENET_NET_TO_HOST_32(command->verifyConnect.incomingBandwidth); + peer->outgoingBandwidth = ENET_NET_TO_HOST_32(command->verifyConnect.outgoingBandwidth); + + enet_protocol_notify_connect(host, peer, event); + return 0; + } /* enet_protocol_handle_verify_connect */ + + static int enet_protocol_handle_incoming_commands(ENetHost *host, ENetEvent *event) { + ENetProtocolHeader *header; + ENetProtocol *command; + ENetPeer *peer; + enet_uint8 *currentData; + size_t headerSize; + enet_uint16 peerID, flags; + enet_uint8 sessionID; + + if (host->receivedDataLength < (size_t) &((ENetProtocolHeader *) 0)->sentTime) { + return 0; + } + + header = (ENetProtocolHeader *) host->receivedData; + + peerID = ENET_NET_TO_HOST_16(header->peerID); + sessionID = (peerID & ENET_PROTOCOL_HEADER_SESSION_MASK) >> ENET_PROTOCOL_HEADER_SESSION_SHIFT; + flags = peerID & ENET_PROTOCOL_HEADER_FLAG_MASK; + peerID &= ~(ENET_PROTOCOL_HEADER_FLAG_MASK | ENET_PROTOCOL_HEADER_SESSION_MASK); + + headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof(ENetProtocolHeader) : (size_t) &((ENetProtocolHeader *) 0)->sentTime); + if (host->checksum != NULL) { + headerSize += sizeof(enet_uint32); + } + + if (peerID == ENET_PROTOCOL_MAXIMUM_PEER_ID) { + peer = NULL; + } else if (peerID >= host->peerCount) { + return 0; + } else { + peer = &host->peers[peerID]; + + if (peer->state == ENET_PEER_STATE_DISCONNECTED || + peer->state == ENET_PEER_STATE_ZOMBIE || + ((!in6_equal(host->receivedAddress.host , peer->address.host) || + host->receivedAddress.port != peer->address.port) && + 1 /* no broadcast in ipv6 !in6_equal(peer->address.host , ENET_HOST_BROADCAST)*/) || + (peer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID && + sessionID != peer->incomingSessionID) + ) { + return 0; + } + } + + if (flags & ENET_PROTOCOL_HEADER_FLAG_COMPRESSED) { + size_t originalSize; + if (host->compressor.context == NULL || host->compressor.decompress == NULL) { + return 0; + } + + originalSize = host->compressor.decompress(host->compressor.context, + host->receivedData + headerSize, + host->receivedDataLength - headerSize, + host->packetData[1] + headerSize, + sizeof(host->packetData[1]) - headerSize + ); + + if (originalSize <= 0 || originalSize > sizeof(host->packetData[1]) - headerSize) { + return 0; + } + + memcpy(host->packetData[1], header, headerSize); + host->receivedData = host->packetData[1]; + host->receivedDataLength = headerSize + originalSize; + } + + if (host->checksum != NULL) { + enet_uint32 *checksum = (enet_uint32 *) &host->receivedData[headerSize - sizeof(enet_uint32)]; + enet_uint32 desiredChecksum = *checksum; + ENetBuffer buffer; + + *checksum = peer != NULL ? peer->connectID : 0; + + buffer.data = host->receivedData; + buffer.dataLength = host->receivedDataLength; + + if (host->checksum(&buffer, 1) != desiredChecksum) { + return 0; + } + } + + if (peer != NULL) { + peer->address.host = host->receivedAddress.host; + peer->address.port = host->receivedAddress.port; + peer->incomingDataTotal += host->receivedDataLength; + peer->totalDataReceived += host->receivedDataLength; + } + + currentData = host->receivedData + headerSize; + + while (currentData < &host->receivedData[host->receivedDataLength]) { + enet_uint8 commandNumber; + size_t commandSize; + + command = (ENetProtocol *) currentData; + + if (currentData + sizeof(ENetProtocolCommandHeader) > &host->receivedData[host->receivedDataLength]) { + break; + } + + commandNumber = command->header.command & ENET_PROTOCOL_COMMAND_MASK; + if (commandNumber >= ENET_PROTOCOL_COMMAND_COUNT) { + break; + } + + commandSize = commandSizes[commandNumber]; + if (commandSize == 0 || currentData + commandSize > &host->receivedData[host->receivedDataLength]) { + break; + } + + currentData += commandSize; + + if (peer == NULL && (commandNumber != ENET_PROTOCOL_COMMAND_CONNECT || currentData < &host->receivedData[host->receivedDataLength])) { + break; + } + + command->header.reliableSequenceNumber = ENET_NET_TO_HOST_16(command->header.reliableSequenceNumber); + + switch (commandNumber) { + case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE: + if (enet_protocol_handle_acknowledge(host, event, peer, command)) { + goto commandError; + } + break; + + case ENET_PROTOCOL_COMMAND_CONNECT: + if (peer != NULL) { + goto commandError; + } + peer = enet_protocol_handle_connect(host, header, command); + if (peer == NULL) { + goto commandError; + } + break; + + case ENET_PROTOCOL_COMMAND_VERIFY_CONNECT: + if (enet_protocol_handle_verify_connect(host, event, peer, command)) { + goto commandError; + } + break; + + case ENET_PROTOCOL_COMMAND_DISCONNECT: + if (enet_protocol_handle_disconnect(host, peer, command)) { + goto commandError; + } + break; + + case ENET_PROTOCOL_COMMAND_PING: + if (enet_protocol_handle_ping(host, peer, command)) { + goto commandError; + } + break; + + case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: + if (enet_protocol_handle_send_reliable(host, peer, command, ¤tData)) { + goto commandError; + } + break; + + case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: + if (enet_protocol_handle_send_unreliable(host, peer, command, ¤tData)) { + goto commandError; + } + break; + + case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: + if (enet_protocol_handle_send_unsequenced(host, peer, command, ¤tData)) { + goto commandError; + } + break; + + case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: + if (enet_protocol_handle_send_fragment(host, peer, command, ¤tData)) { + goto commandError; + } + break; + + case ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT: + if (enet_protocol_handle_bandwidth_limit(host, peer, command)) { + goto commandError; + } + break; + + case ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE: + if (enet_protocol_handle_throttle_configure(host, peer, command)) { + goto commandError; + } + break; + + case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT: + if (enet_protocol_handle_send_unreliable_fragment(host, peer, command, ¤tData)) { + goto commandError; + } + break; + + default: + goto commandError; + } + + if (peer != NULL && (command->header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0) { + enet_uint16 sentTime; + + if (!(flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)) { + break; + } + + sentTime = ENET_NET_TO_HOST_16(header->sentTime); + + switch (peer->state) { + case ENET_PEER_STATE_DISCONNECTING: + case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT: + case ENET_PEER_STATE_DISCONNECTED: + case ENET_PEER_STATE_ZOMBIE: + break; + + case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT: + if ((command->header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT) { + enet_peer_queue_acknowledgement(peer, command, sentTime); + } + break; + + default: + enet_peer_queue_acknowledgement(peer, command, sentTime); + break; + } + } + } + + commandError: + if (event != NULL && event->type != ENET_EVENT_TYPE_NONE) { + return 1; + } + + return 0; + } /* enet_protocol_handle_incoming_commands */ + + static int enet_protocol_receive_incoming_commands(ENetHost *host, ENetEvent *event) { + int packets; + + for (packets = 0; packets < 256; ++packets) { + int receivedLength; + ENetBuffer buffer; + + buffer.data = host->packetData[0]; + // buffer.dataLength = sizeof (host->packetData[0]); + buffer.dataLength = host->mtu; + + receivedLength = enet_socket_receive(host->socket, &host->receivedAddress, &buffer, 1); + + if (receivedLength == -2) + continue; + + if (receivedLength < 0) { + return -1; + } + + if (receivedLength == 0) { + return 0; + } + + host->receivedData = host->packetData[0]; + host->receivedDataLength = receivedLength; + + host->totalReceivedData += receivedLength; + host->totalReceivedPackets++; + + if (host->intercept != NULL) { + switch (host->intercept(host, (void *)event)) { + case 1: + if (event != NULL && event->type != ENET_EVENT_TYPE_NONE) { + return 1; + } + + continue; + + case -1: + return -1; + + default: + break; + } + } + + switch (enet_protocol_handle_incoming_commands(host, event)) { + case 1: + return 1; + + case -1: + return -1; + + default: + break; + } + } + + return -1; + } /* enet_protocol_receive_incoming_commands */ + + static void enet_protocol_send_acknowledgements(ENetHost *host, ENetPeer *peer) { + ENetProtocol *command = &host->commands[host->commandCount]; + ENetBuffer *buffer = &host->buffers[host->bufferCount]; + ENetAcknowledgement *acknowledgement; + ENetListIterator currentAcknowledgement; + enet_uint16 reliableSequenceNumber; + + currentAcknowledgement = enet_list_begin(&peer->acknowledgements); + + while (currentAcknowledgement != enet_list_end(&peer->acknowledgements)) { + if (command >= &host->commands[sizeof(host->commands) / sizeof(ENetProtocol)] || + buffer >= &host->buffers[sizeof(host->buffers) / sizeof(ENetBuffer)] || + peer->mtu - host->packetSize < sizeof(ENetProtocolAcknowledge) + ) { + host->continueSending = 1; + break; + } + + acknowledgement = (ENetAcknowledgement *) currentAcknowledgement; + currentAcknowledgement = enet_list_next(currentAcknowledgement); + + buffer->data = command; + buffer->dataLength = sizeof(ENetProtocolAcknowledge); + host->packetSize += buffer->dataLength; + + reliableSequenceNumber = ENET_HOST_TO_NET_16(acknowledgement->command.header.reliableSequenceNumber); + + command->header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE; + command->header.channelID = acknowledgement->command.header.channelID; + command->header.reliableSequenceNumber = reliableSequenceNumber; + command->acknowledge.receivedReliableSequenceNumber = reliableSequenceNumber; + command->acknowledge.receivedSentTime = ENET_HOST_TO_NET_16(acknowledgement->sentTime); + + if ((acknowledgement->command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT) { + enet_protocol_dispatch_state(host, peer, ENET_PEER_STATE_ZOMBIE); + } + + enet_list_remove(&acknowledgement->acknowledgementList); + enet_free(acknowledgement); + + ++command; + ++buffer; + } + + host->commandCount = command - host->commands; + host->bufferCount = buffer - host->buffers; + } /* enet_protocol_send_acknowledgements */ + + static void enet_protocol_send_unreliable_outgoing_commands(ENetHost *host, ENetPeer *peer) { + ENetProtocol *command = &host->commands[host->commandCount]; + ENetBuffer *buffer = &host->buffers[host->bufferCount]; + ENetOutgoingCommand *outgoingCommand; + ENetListIterator currentCommand; + + currentCommand = enet_list_begin(&peer->outgoingUnreliableCommands); + while (currentCommand != enet_list_end(&peer->outgoingUnreliableCommands)) { + size_t commandSize; + + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + commandSize = commandSizes[outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK]; + + if (command >= &host->commands[sizeof(host->commands) / sizeof(ENetProtocol)] || + buffer + 1 >= &host->buffers[sizeof(host->buffers) / sizeof(ENetBuffer)] || + peer->mtu - host->packetSize < commandSize || + (outgoingCommand->packet != NULL && + peer->mtu - host->packetSize < commandSize + outgoingCommand->fragmentLength) + ) { + host->continueSending = 1; + break; + } + + currentCommand = enet_list_next(currentCommand); + + if (outgoingCommand->packet != NULL && outgoingCommand->fragmentOffset == 0) { + peer->packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER; + peer->packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE; + + if (peer->packetThrottleCounter > peer->packetThrottle) { + enet_uint16 reliableSequenceNumber = outgoingCommand->reliableSequenceNumber; + enet_uint16 unreliableSequenceNumber = outgoingCommand->unreliableSequenceNumber; + for (;;) { + --outgoingCommand->packet->referenceCount; + + if (outgoingCommand->packet->referenceCount == 0) { + callbacks.packet_destroy(outgoingCommand->packet); + } + + enet_list_remove(&outgoingCommand->outgoingCommandList); + enet_free(outgoingCommand); + + if (currentCommand == enet_list_end(&peer->outgoingUnreliableCommands)) { + break; + } + + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + if (outgoingCommand->reliableSequenceNumber != reliableSequenceNumber || outgoingCommand->unreliableSequenceNumber != unreliableSequenceNumber) { + break; + } + + currentCommand = enet_list_next(currentCommand); + } + + continue; + } + } + + buffer->data = command; + buffer->dataLength = commandSize; + host->packetSize += buffer->dataLength; + *command = outgoingCommand->command; + enet_list_remove(&outgoingCommand->outgoingCommandList); + + if (outgoingCommand->packet != NULL) { + ++buffer; + + buffer->data = outgoingCommand->packet->data + outgoingCommand->fragmentOffset; + buffer->dataLength = outgoingCommand->fragmentLength; + + host->packetSize += buffer->dataLength; + + enet_list_insert(enet_list_end(&peer->sentUnreliableCommands), outgoingCommand); + } else { + enet_free(outgoingCommand); + } + + ++command; + ++buffer; + } + + host->commandCount = command - host->commands; + host->bufferCount = buffer - host->buffers; + + if (peer->state == ENET_PEER_STATE_DISCONNECT_LATER && + enet_list_empty(&peer->outgoingReliableCommands) && + enet_list_empty(&peer->outgoingUnreliableCommands) && + enet_list_empty(&peer->sentReliableCommands)) + { + enet_peer_disconnect(peer, peer->eventData); + } + } /* enet_protocol_send_unreliable_outgoing_commands */ + + static int enet_protocol_check_timeouts(ENetHost *host, ENetPeer *peer, ENetEvent *event) { + ENetOutgoingCommand *outgoingCommand; + ENetListIterator currentCommand, insertPosition; + + currentCommand = enet_list_begin(&peer->sentReliableCommands); + insertPosition = enet_list_begin(&peer->outgoingReliableCommands); + + while (currentCommand != enet_list_end(&peer->sentReliableCommands)) { + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + + currentCommand = enet_list_next(currentCommand); + + if (ENET_TIME_DIFFERENCE(host->serviceTime, outgoingCommand->sentTime) < outgoingCommand->roundTripTimeout) { + continue; + } + + if (peer->earliestTimeout == 0 || ENET_TIME_LESS(outgoingCommand->sentTime, peer->earliestTimeout)) { + peer->earliestTimeout = outgoingCommand->sentTime; + } + + if (peer->earliestTimeout != 0 && + (ENET_TIME_DIFFERENCE(host->serviceTime, peer->earliestTimeout) >= peer->timeoutMaximum || + (outgoingCommand->roundTripTimeout >= outgoingCommand->roundTripTimeoutLimit && + ENET_TIME_DIFFERENCE(host->serviceTime, peer->earliestTimeout) >= peer->timeoutMinimum)) + ) { + enet_protocol_notify_disconnect_timeout(host, peer, event); + return 1; + } + + if (outgoingCommand->packet != NULL) { + peer->reliableDataInTransit -= outgoingCommand->fragmentLength; + } + + ++peer->packetsLost; + ++peer->totalPacketsLost; + + /* Replaced exponential backoff time with something more linear */ + /* Source: http://lists.cubik.org/pipermail/enet-discuss/2014-May/002308.html */ + outgoingCommand->roundTripTimeout = peer->roundTripTime + 4 * peer->roundTripTimeVariance; + outgoingCommand->roundTripTimeoutLimit = peer->timeoutLimit * outgoingCommand->roundTripTimeout; + + enet_list_insert(insertPosition, enet_list_remove(&outgoingCommand->outgoingCommandList)); + + if (currentCommand == enet_list_begin(&peer->sentReliableCommands) && !enet_list_empty(&peer->sentReliableCommands)) { + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + peer->nextTimeout = outgoingCommand->sentTime + outgoingCommand->roundTripTimeout; + } + } + + return 0; + } /* enet_protocol_check_timeouts */ + + static int enet_protocol_send_reliable_outgoing_commands(ENetHost *host, ENetPeer *peer) { + ENetProtocol *command = &host->commands[host->commandCount]; + ENetBuffer *buffer = &host->buffers[host->bufferCount]; + ENetOutgoingCommand *outgoingCommand; + ENetListIterator currentCommand; + ENetChannel *channel; + enet_uint16 reliableWindow; + size_t commandSize; + int windowExceeded = 0, windowWrap = 0, canPing = 1; + + currentCommand = enet_list_begin(&peer->outgoingReliableCommands); + + while (currentCommand != enet_list_end(&peer->outgoingReliableCommands)) { + outgoingCommand = (ENetOutgoingCommand *) currentCommand; + + channel = outgoingCommand->command.header.channelID < peer->channelCount ? &peer->channels[outgoingCommand->command.header.channelID] : NULL; + reliableWindow = outgoingCommand->reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + if (channel != NULL) { + if (!windowWrap && + outgoingCommand->sendAttempts < 1 && + !(outgoingCommand->reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) && + (channel->reliableWindows[(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) + % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE || + channel->usedReliableWindows & ((((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) << reliableWindow) + | (((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOWS - reliableWindow)))) + ) { + windowWrap = 1; + } + + if (windowWrap) { + currentCommand = enet_list_next(currentCommand); + continue; + } + } + + if (outgoingCommand->packet != NULL) { + if (!windowExceeded) { + enet_uint32 windowSize = (peer->packetThrottle * peer->windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE; + + if (peer->reliableDataInTransit + outgoingCommand->fragmentLength > ENET_MAX(windowSize, peer->mtu)) { + windowExceeded = 1; + } + } + if (windowExceeded) { + currentCommand = enet_list_next(currentCommand); + + continue; + } + } + + canPing = 0; + + commandSize = commandSizes[outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK]; + if (command >= &host->commands[sizeof(host->commands) / sizeof(ENetProtocol)] || + buffer + 1 >= &host->buffers[sizeof(host->buffers) / sizeof(ENetBuffer)] || + peer->mtu - host->packetSize < commandSize || + (outgoingCommand->packet != NULL && + (enet_uint16) (peer->mtu - host->packetSize) < (enet_uint16) (commandSize + outgoingCommand->fragmentLength)) + ) { + host->continueSending = 1; + break; + } + + currentCommand = enet_list_next(currentCommand); + + if (channel != NULL && outgoingCommand->sendAttempts < 1) { + channel->usedReliableWindows |= 1 << reliableWindow; + ++channel->reliableWindows[reliableWindow]; + } + + ++outgoingCommand->sendAttempts; + + if (outgoingCommand->roundTripTimeout == 0) { + outgoingCommand->roundTripTimeout = peer->roundTripTime + 4 * peer->roundTripTimeVariance; + outgoingCommand->roundTripTimeoutLimit = peer->timeoutLimit * outgoingCommand->roundTripTimeout; + } + + if (enet_list_empty(&peer->sentReliableCommands)) { + peer->nextTimeout = host->serviceTime + outgoingCommand->roundTripTimeout; + } + + enet_list_insert(enet_list_end(&peer->sentReliableCommands), enet_list_remove(&outgoingCommand->outgoingCommandList)); + + outgoingCommand->sentTime = host->serviceTime; + + buffer->data = command; + buffer->dataLength = commandSize; + + host->packetSize += buffer->dataLength; + host->headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME; + + *command = outgoingCommand->command; + + if (outgoingCommand->packet != NULL) { + ++buffer; + buffer->data = outgoingCommand->packet->data + outgoingCommand->fragmentOffset; + buffer->dataLength = outgoingCommand->fragmentLength; + host->packetSize += outgoingCommand->fragmentLength; + peer->reliableDataInTransit += outgoingCommand->fragmentLength; + } + + ++peer->packetsSent; + ++peer->totalPacketsSent; + + ++command; + ++buffer; + } + + host->commandCount = command - host->commands; + host->bufferCount = buffer - host->buffers; + + return canPing; + } /* enet_protocol_send_reliable_outgoing_commands */ + + static int enet_protocol_send_outgoing_commands(ENetHost *host, ENetEvent *event, int checkForTimeouts) { + enet_uint8 headerData[sizeof(ENetProtocolHeader) + sizeof(enet_uint32)]; + ENetProtocolHeader *header = (ENetProtocolHeader *) headerData; + ENetPeer *currentPeer; + int sentLength; + size_t shouldCompress = 0; + host->continueSending = 1; + + while (host->continueSending) + for (host->continueSending = 0, currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) { + if (currentPeer->state == ENET_PEER_STATE_DISCONNECTED || currentPeer->state == ENET_PEER_STATE_ZOMBIE) { + continue; + } + + host->headerFlags = 0; + host->commandCount = 0; + host->bufferCount = 1; + host->packetSize = sizeof(ENetProtocolHeader); + + if (!enet_list_empty(¤tPeer->acknowledgements)) { + enet_protocol_send_acknowledgements(host, currentPeer); + } + + if (checkForTimeouts != 0 && + !enet_list_empty(¤tPeer->sentReliableCommands) && + ENET_TIME_GREATER_EQUAL(host->serviceTime, currentPeer->nextTimeout) && + enet_protocol_check_timeouts(host, currentPeer, event) == 1 + ) { + if (event != NULL && event->type != ENET_EVENT_TYPE_NONE) { + return 1; + } else { + continue; + } + } + + if ((enet_list_empty(¤tPeer->outgoingReliableCommands) || + enet_protocol_send_reliable_outgoing_commands(host, currentPeer)) && + enet_list_empty(¤tPeer->sentReliableCommands) && + ENET_TIME_DIFFERENCE(host->serviceTime, currentPeer->lastReceiveTime) >= currentPeer->pingInterval && + currentPeer->mtu - host->packetSize >= sizeof(ENetProtocolPing) + ) { + enet_peer_ping(currentPeer); + enet_protocol_send_reliable_outgoing_commands(host, currentPeer); + } + + if (!enet_list_empty(¤tPeer->outgoingUnreliableCommands)) { + enet_protocol_send_unreliable_outgoing_commands(host, currentPeer); + } + + if (host->commandCount == 0) { + continue; + } + + if (currentPeer->packetLossEpoch == 0) { + currentPeer->packetLossEpoch = host->serviceTime; + } else if (ENET_TIME_DIFFERENCE(host->serviceTime, currentPeer->packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL && currentPeer->packetsSent > 0) { + enet_uint32 packetLoss = currentPeer->packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer->packetsSent; + + #ifdef ENET_DEBUG + printf( + "peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer->incomingPeerID, + currentPeer->packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, + currentPeer->packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer->roundTripTime, currentPeer->roundTripTimeVariance, + currentPeer->packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, + enet_list_size(¤tPeer->outgoingReliableCommands), + enet_list_size(¤tPeer->outgoingUnreliableCommands), + currentPeer->channels != NULL ? enet_list_size( ¤tPeer->channels->incomingReliableCommands) : 0, + currentPeer->channels != NULL ? enet_list_size(¤tPeer->channels->incomingUnreliableCommands) : 0 + ); + #endif + + currentPeer->packetLossVariance -= currentPeer->packetLossVariance / 4; + + if (packetLoss >= currentPeer->packetLoss) { + currentPeer->packetLoss += (packetLoss - currentPeer->packetLoss) / 8; + currentPeer->packetLossVariance += (packetLoss - currentPeer->packetLoss) / 4; + } else { + currentPeer->packetLoss -= (currentPeer->packetLoss - packetLoss) / 8; + currentPeer->packetLossVariance += (currentPeer->packetLoss - packetLoss) / 4; + } + + currentPeer->packetLossEpoch = host->serviceTime; + currentPeer->packetsSent = 0; + currentPeer->packetsLost = 0; + } + + host->buffers[0].data = headerData; + if (host->headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME) { + header->sentTime = ENET_HOST_TO_NET_16(host->serviceTime & 0xFFFF); + host->buffers[0].dataLength = sizeof(ENetProtocolHeader); + } else { + host->buffers[0].dataLength = (size_t) &((ENetProtocolHeader *) 0)->sentTime; + } + + shouldCompress = 0; + if (host->compressor.context != NULL && host->compressor.compress != NULL) { + size_t originalSize = host->packetSize - sizeof(ENetProtocolHeader), + compressedSize = host->compressor.compress(host->compressor.context, &host->buffers[1], host->bufferCount - 1, originalSize, host->packetData[1], originalSize); + if (compressedSize > 0 && compressedSize < originalSize) { + host->headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED; + shouldCompress = compressedSize; + #ifdef ENET_DEBUG_COMPRESS + printf("peer %u: compressed %u->%u (%u%%)\n", currentPeer->incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize); + #endif + } + } + + if (currentPeer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID) { + host->headerFlags |= currentPeer->outgoingSessionID << ENET_PROTOCOL_HEADER_SESSION_SHIFT; + } + header->peerID = ENET_HOST_TO_NET_16(currentPeer->outgoingPeerID | host->headerFlags); + if (host->checksum != NULL) { + enet_uint32 *checksum = (enet_uint32 *) &headerData[host->buffers[0].dataLength]; + *checksum = currentPeer->outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer->connectID : 0; + host->buffers[0].dataLength += sizeof(enet_uint32); + *checksum = host->checksum(host->buffers, host->bufferCount); + } + + if (shouldCompress > 0) { + host->buffers[1].data = host->packetData[1]; + host->buffers[1].dataLength = shouldCompress; + host->bufferCount = 2; + } + + currentPeer->lastSendTime = host->serviceTime; + sentLength = enet_socket_send(host->socket, ¤tPeer->address, host->buffers, host->bufferCount); + enet_protocol_remove_sent_unreliable_commands(currentPeer); + + if (sentLength < 0) { + // The local 'headerData' array (to which 'data' is assigned) goes out + // of scope on return from this function, so ensure we no longer point to it. + host->buffers[0].data = NULL; + return -1; + } + + host->totalSentData += sentLength; + currentPeer->totalDataSent += sentLength; + host->totalSentPackets++; + } + + // The local 'headerData' array (to which 'data' is assigned) goes out + // of scope on return from this function, so ensure we no longer point to it. + host->buffers[0].data = NULL; + + return 0; + } /* enet_protocol_send_outgoing_commands */ + + /** Sends any queued packets on the host specified to its designated peers. + * + * @param host host to flush + * @remarks this function need only be used in circumstances where one wishes to send queued packets earlier than in a call to enet_host_service(). + * @ingroup host + */ + void enet_host_flush(ENetHost *host) { + host->serviceTime = enet_time_get(); + enet_protocol_send_outgoing_commands(host, NULL, 0); + } + + /** Checks for any queued events on the host and dispatches one if available. + * + * @param host host to check for events + * @param event an event structure where event details will be placed if available + * @retval > 0 if an event was dispatched + * @retval 0 if no events are available + * @retval < 0 on failure + * @ingroup host + */ + int enet_host_check_events(ENetHost *host, ENetEvent *event) { + if (event == NULL) { return -1; } + + event->type = ENET_EVENT_TYPE_NONE; + event->peer = NULL; + event->packet = NULL; + + return enet_protocol_dispatch_incoming_commands(host, event); + } + + /** Waits for events on the host specified and shuttles packets between + * the host and its peers. + * + * @param host host to service + * @param event an event structure where event details will be placed if one occurs + * if event == NULL then no events will be delivered + * @param timeout number of milliseconds that ENet should wait for events + * @retval > 0 if an event occurred within the specified time limit + * @retval 0 if no event occurred + * @retval < 0 on failure + * @remarks enet_host_service should be called fairly regularly for adequate performance + * @ingroup host + */ + int enet_host_service(ENetHost *host, ENetEvent *event, enet_uint32 timeout) { + enet_uint32 waitCondition; + + if (event != NULL) { + event->type = ENET_EVENT_TYPE_NONE; + event->peer = NULL; + event->packet = NULL; + + switch (enet_protocol_dispatch_incoming_commands(host, event)) { + case 1: + return 1; + + case -1: + #ifdef ENET_DEBUG + perror("Error dispatching incoming packets"); + #endif + + return -1; + + default: + break; + } + } + + host->serviceTime = enet_time_get(); + timeout += host->serviceTime; + + do { + if (ENET_TIME_DIFFERENCE(host->serviceTime, host->bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL) { + enet_host_bandwidth_throttle(host); + } + + switch (enet_protocol_send_outgoing_commands(host, event, 1)) { + case 1: + return 1; + + case -1: + #ifdef ENET_DEBUG + perror("Error sending outgoing packets"); + #endif + + return -1; + + default: + break; + } + + switch (enet_protocol_receive_incoming_commands(host, event)) { + case 1: + return 1; + + case -1: + #ifdef ENET_DEBUG + perror("Error receiving incoming packets"); + #endif + + return -1; + + default: + break; + } + + switch (enet_protocol_send_outgoing_commands(host, event, 1)) { + case 1: + return 1; + + case -1: + #ifdef ENET_DEBUG + perror("Error sending outgoing packets"); + #endif + + return -1; + + default: + break; + } + + if (event != NULL) { + switch (enet_protocol_dispatch_incoming_commands(host, event)) { + case 1: + return 1; + + case -1: + #ifdef ENET_DEBUG + perror("Error dispatching incoming packets"); + #endif + + return -1; + + default: + break; + } + } + + if (ENET_TIME_GREATER_EQUAL(host->serviceTime, timeout)) { + return 0; + } + + do { + host->serviceTime = enet_time_get(); + + if (ENET_TIME_GREATER_EQUAL(host->serviceTime, timeout)) { + return 0; + } + + waitCondition = ENET_SOCKET_WAIT_RECEIVE | ENET_SOCKET_WAIT_INTERRUPT; + if (enet_socket_wait(host->socket, &waitCondition, ENET_TIME_DIFFERENCE(timeout, host->serviceTime)) != 0) { + return -1; + } + } while (waitCondition & ENET_SOCKET_WAIT_INTERRUPT); + + host->serviceTime = enet_time_get(); + } while (waitCondition & ENET_SOCKET_WAIT_RECEIVE); + + return 0; + } /* enet_host_service */ + + +// =======================================================================// +// ! +// ! Peer +// ! +// =======================================================================// + + /** Configures throttle parameter for a peer. + * + * Unreliable packets are dropped by ENet in response to the varying conditions + * of the Internet connection to the peer. The throttle represents a probability + * that an unreliable packet should not be dropped and thus sent by ENet to the peer. + * The lowest mean round trip time from the sending of a reliable packet to the + * receipt of its acknowledgement is measured over an amount of time specified by + * the interval parameter in milliseconds. If a measured round trip time happens to + * be significantly less than the mean round trip time measured over the interval, + * then the throttle probability is increased to allow more traffic by an amount + * specified in the acceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE + * constant. If a measured round trip time happens to be significantly greater than + * the mean round trip time measured over the interval, then the throttle probability + * is decreased to limit traffic by an amount specified in the deceleration parameter, which + * is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant. When the throttle has + * a value of ENET_PEER_PACKET_THROTTLE_SCALE, no unreliable packets are dropped by + * ENet, and so 100% of all unreliable packets will be sent. When the throttle has a + * value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable + * packets will be sent. Intermediate values for the throttle represent intermediate + * probabilities between 0% and 100% of unreliable packets being sent. The bandwidth + * limits of the local and foreign hosts are taken into account to determine a + * sensible limit for the throttle probability above which it should not raise even in + * the best of conditions. + * + * @param peer peer to configure + * @param interval interval, in milliseconds, over which to measure lowest mean RTT; the default value is ENET_PEER_PACKET_THROTTLE_INTERVAL. + * @param acceleration rate at which to increase the throttle probability as mean RTT declines + * @param deceleration rate at which to decrease the throttle probability as mean RTT increases + */ + void enet_peer_throttle_configure(ENetPeer *peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deceleration) { + ENetProtocol command; + + peer->packetThrottleInterval = interval; + peer->packetThrottleAcceleration = acceleration; + peer->packetThrottleDeceleration = deceleration; + + command.header.command = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; + command.header.channelID = 0xFF; + + command.throttleConfigure.packetThrottleInterval = ENET_HOST_TO_NET_32(interval); + command.throttleConfigure.packetThrottleAcceleration = ENET_HOST_TO_NET_32(acceleration); + command.throttleConfigure.packetThrottleDeceleration = ENET_HOST_TO_NET_32(deceleration); + + enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0); + } + + int enet_peer_throttle(ENetPeer *peer, enet_uint32 rtt) { + if (peer->lastRoundTripTime <= peer->lastRoundTripTimeVariance) { + peer->packetThrottle = peer->packetThrottleLimit; + } + else if (rtt < peer->lastRoundTripTime) { + peer->packetThrottle += peer->packetThrottleAcceleration; + + if (peer->packetThrottle > peer->packetThrottleLimit) { + peer->packetThrottle = peer->packetThrottleLimit; + } + + return 1; + } + else if (rtt > peer->lastRoundTripTime + 2 * peer->lastRoundTripTimeVariance) { + if (peer->packetThrottle > peer->packetThrottleDeceleration) { + peer->packetThrottle -= peer->packetThrottleDeceleration; + } else { + peer->packetThrottle = 0; + } + + return -1; + } + + return 0; + } + + /* Extended functionality for easier binding in other programming languages */ + enet_uint32 enet_host_get_peers_count(ENetHost *host) { + return host->connectedPeers; + } + + enet_uint32 enet_host_get_packets_sent(ENetHost *host) { + return host->totalSentPackets; + } + + enet_uint32 enet_host_get_packets_received(ENetHost *host) { + return host->totalReceivedPackets; + } + + enet_uint32 enet_host_get_bytes_sent(ENetHost *host) { + return host->totalSentData; + } + + enet_uint32 enet_host_get_bytes_received(ENetHost *host) { + return host->totalReceivedData; + } + + /** Gets received data buffer. Returns buffer length. + * @param host host to access recevie buffer + * @param data ouput parameter for recevied data + * @retval buffer length + */ + enet_uint32 enet_host_get_received_data(ENetHost *host, /*out*/ enet_uint8** data) { + *data = host->receivedData; + return host->receivedDataLength; + } + + enet_uint32 enet_host_get_mtu(ENetHost *host) { + return host->mtu; + } + + enet_uint32 enet_peer_get_id(ENetPeer *peer) { + return peer->connectID; + } + + enet_uint32 enet_peer_get_ip(ENetPeer *peer, char *ip, size_t ipLength) { + return enet_address_get_host_ip(&peer->address, ip, ipLength); + } + + enet_uint16 enet_peer_get_port(ENetPeer *peer) { + return peer->address.port; + } + + ENetPeerState enet_peer_get_state(ENetPeer *peer) { + return peer->state; + } + + enet_uint32 enet_peer_get_rtt(ENetPeer *peer) { + return peer->roundTripTime; + } + + enet_uint64 enet_peer_get_packets_sent(ENetPeer *peer) { + return peer->totalPacketsSent; + } + + enet_uint32 enet_peer_get_packets_lost(ENetPeer *peer) { + return peer->totalPacketsLost; + } + + enet_uint64 enet_peer_get_bytes_sent(ENetPeer *peer) { + return peer->totalDataSent; + } + + enet_uint64 enet_peer_get_bytes_received(ENetPeer *peer) { + return peer->totalDataReceived; + } + + void * enet_peer_get_data(ENetPeer *peer) { + return (void *) peer->data; + } + + void enet_peer_set_data(ENetPeer *peer, const void *data) { + peer->data = (enet_uint32 *) data; + } + + void * enet_packet_get_data(ENetPacket *packet) { + return (void *) packet->data; + } + + enet_uint32 enet_packet_get_length(ENetPacket *packet) { + return packet->dataLength; + } + + void enet_packet_set_free_callback(ENetPacket *packet, void *callback) { + packet->freeCallback = (ENetPacketFreeCallback)callback; + } + + /** Queues a packet to be sent. + * @param peer destination for the packet + * @param channelID channel on which to send + * @param packet packet to send + * @retval 0 on success + * @retval < 0 on failure + */ + int enet_peer_send(ENetPeer *peer, enet_uint8 channelID, ENetPacket *packet) { + ENetChannel *channel = &peer->channels[channelID]; + ENetProtocol command; + size_t fragmentLength; + + if (peer->state != ENET_PEER_STATE_CONNECTED || channelID >= peer->channelCount || packet->dataLength > peer->host->maximumPacketSize) { + return -1; + } + + fragmentLength = peer->mtu - sizeof(ENetProtocolHeader) - sizeof(ENetProtocolSendFragment); + if (peer->host->checksum != NULL) { + fragmentLength -= sizeof(enet_uint32); + } + + if (packet->dataLength > fragmentLength) { + enet_uint32 fragmentCount = (packet->dataLength + fragmentLength - 1) / fragmentLength, fragmentNumber, fragmentOffset; + enet_uint8 commandNumber; + enet_uint16 startSequenceNumber; + ENetList fragments; + ENetOutgoingCommand *fragment; + + if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) { + return -1; + } + + if ((packet->flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) == + ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT && + channel->outgoingUnreliableSequenceNumber < 0xFFFF) + { + commandNumber = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT; + startSequenceNumber = ENET_HOST_TO_NET_16(channel->outgoingUnreliableSequenceNumber + 1); + } else { + commandNumber = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; + startSequenceNumber = ENET_HOST_TO_NET_16(channel->outgoingReliableSequenceNumber + 1); + } + + enet_list_clear(&fragments); + + for (fragmentNumber = 0, fragmentOffset = 0; fragmentOffset < packet->dataLength; ++fragmentNumber, fragmentOffset += fragmentLength) { + if (packet->dataLength - fragmentOffset < fragmentLength) { + fragmentLength = packet->dataLength - fragmentOffset; + } + + fragment = (ENetOutgoingCommand *) enet_malloc(sizeof(ENetOutgoingCommand)); + + if (fragment == NULL) { + while (!enet_list_empty(&fragments)) { + fragment = (ENetOutgoingCommand *) enet_list_remove(enet_list_begin(&fragments)); + + enet_free(fragment); + } + + return -1; + } + + fragment->fragmentOffset = fragmentOffset; + fragment->fragmentLength = fragmentLength; + fragment->packet = packet; + fragment->command.header.command = commandNumber; + fragment->command.header.channelID = channelID; + + fragment->command.sendFragment.startSequenceNumber = startSequenceNumber; + + fragment->command.sendFragment.dataLength = ENET_HOST_TO_NET_16(fragmentLength); + fragment->command.sendFragment.fragmentCount = ENET_HOST_TO_NET_32(fragmentCount); + fragment->command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32(fragmentNumber); + fragment->command.sendFragment.totalLength = ENET_HOST_TO_NET_32(packet->dataLength); + fragment->command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32(fragmentOffset); + + enet_list_insert(enet_list_end(&fragments), fragment); + } + + packet->referenceCount += fragmentNumber; + + while (!enet_list_empty(&fragments)) { + fragment = (ENetOutgoingCommand *) enet_list_remove(enet_list_begin(&fragments)); + enet_peer_setup_outgoing_command(peer, fragment); + } + + return 0; + } + + command.header.channelID = channelID; + + if ((packet->flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNSEQUENCED)) == ENET_PACKET_FLAG_UNSEQUENCED) { + command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; + command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16(packet->dataLength); + } + else if (packet->flags & ENET_PACKET_FLAG_RELIABLE || channel->outgoingUnreliableSequenceNumber >= 0xFFFF) { + command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; + command.sendReliable.dataLength = ENET_HOST_TO_NET_16(packet->dataLength); + } + else { + command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE; + command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16(packet->dataLength); + } + + if (enet_peer_queue_outgoing_command(peer, &command, packet, 0, packet->dataLength) == NULL) { + return -1; + } + + return 0; + } // enet_peer_send + + /** Attempts to dequeue any incoming queued packet. + * @param peer peer to dequeue packets from + * @param channelID holds the channel ID of the channel the packet was received on success + * @returns a pointer to the packet, or NULL if there are no available incoming queued packets + */ + ENetPacket * enet_peer_receive(ENetPeer *peer, enet_uint8 *channelID) { + ENetIncomingCommand *incomingCommand; + ENetPacket *packet; + + if (enet_list_empty(&peer->dispatchedCommands)) { + return NULL; + } + + incomingCommand = (ENetIncomingCommand *) enet_list_remove(enet_list_begin(&peer->dispatchedCommands)); + + if (channelID != NULL) { + *channelID = incomingCommand->command.header.channelID; + } + + packet = incomingCommand->packet; + --packet->referenceCount; + + if (incomingCommand->fragments != NULL) { + enet_free(incomingCommand->fragments); + } + + enet_free(incomingCommand); + peer->totalWaitingData -= packet->dataLength; + + return packet; + } + + static void enet_peer_reset_outgoing_commands(ENetList *queue) { + ENetOutgoingCommand *outgoingCommand; + + while (!enet_list_empty(queue)) { + outgoingCommand = (ENetOutgoingCommand *) enet_list_remove(enet_list_begin(queue)); + + if (outgoingCommand->packet != NULL) { + --outgoingCommand->packet->referenceCount; + + if (outgoingCommand->packet->referenceCount == 0) { + callbacks.packet_destroy(outgoingCommand->packet); + } + } + + enet_free(outgoingCommand); + } + } + + static void enet_peer_remove_incoming_commands(ENetList *queue, ENetListIterator startCommand, ENetListIterator endCommand) { + ENET_UNUSED(queue) + + ENetListIterator currentCommand; + + for (currentCommand = startCommand; currentCommand != endCommand;) { + ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand; + + currentCommand = enet_list_next(currentCommand); + enet_list_remove(&incomingCommand->incomingCommandList); + + if (incomingCommand->packet != NULL) { + --incomingCommand->packet->referenceCount; + + if (incomingCommand->packet->referenceCount == 0) { + callbacks.packet_destroy(incomingCommand->packet); + } + } + + if (incomingCommand->fragments != NULL) { + enet_free(incomingCommand->fragments); + } + + enet_free(incomingCommand); + } + } + + static void enet_peer_reset_incoming_commands(ENetList *queue) { + enet_peer_remove_incoming_commands(queue, enet_list_begin(queue), enet_list_end(queue)); + } + + void enet_peer_reset_queues(ENetPeer *peer) { + ENetChannel *channel; + + if (peer->needsDispatch) { + enet_list_remove(&peer->dispatchList); + peer->needsDispatch = 0; + } + + while (!enet_list_empty(&peer->acknowledgements)) { + enet_free(enet_list_remove(enet_list_begin(&peer->acknowledgements))); + } + + enet_peer_reset_outgoing_commands(&peer->sentReliableCommands); + enet_peer_reset_outgoing_commands(&peer->sentUnreliableCommands); + enet_peer_reset_outgoing_commands(&peer->outgoingReliableCommands); + enet_peer_reset_outgoing_commands(&peer->outgoingUnreliableCommands); + enet_peer_reset_incoming_commands(&peer->dispatchedCommands); + + if (peer->channels != NULL && peer->channelCount > 0) { + for (channel = peer->channels; channel < &peer->channels[peer->channelCount]; ++channel) { + enet_peer_reset_incoming_commands(&channel->incomingReliableCommands); + enet_peer_reset_incoming_commands(&channel->incomingUnreliableCommands); + } + + enet_free(peer->channels); + } + + peer->channels = NULL; + peer->channelCount = 0; + } + + void enet_peer_on_connect(ENetPeer *peer) { + if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { + if (peer->incomingBandwidth != 0) { + ++peer->host->bandwidthLimitedPeers; + } + + ++peer->host->connectedPeers; + } + } + + void enet_peer_on_disconnect(ENetPeer *peer) { + if (peer->state == ENET_PEER_STATE_CONNECTED || peer->state == ENET_PEER_STATE_DISCONNECT_LATER) { + if (peer->incomingBandwidth != 0) { + --peer->host->bandwidthLimitedPeers; + } + + --peer->host->connectedPeers; + } + } + + /** Forcefully disconnects a peer. + * @param peer peer to forcefully disconnect + * @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout + * on its connection to the local host. + */ + void enet_peer_reset(ENetPeer *peer) { + enet_peer_on_disconnect(peer); + + // We don't want to reset connectID here, otherwise, we can't get it in the Disconnect event + // peer->connectID = 0; + peer->outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID; + peer->state = ENET_PEER_STATE_DISCONNECTED; + peer->incomingBandwidth = 0; + peer->outgoingBandwidth = 0; + peer->incomingBandwidthThrottleEpoch = 0; + peer->outgoingBandwidthThrottleEpoch = 0; + peer->incomingDataTotal = 0; + peer->totalDataReceived = 0; + peer->outgoingDataTotal = 0; + peer->totalDataSent = 0; + peer->lastSendTime = 0; + peer->lastReceiveTime = 0; + peer->nextTimeout = 0; + peer->earliestTimeout = 0; + peer->packetLossEpoch = 0; + peer->packetsSent = 0; + peer->totalPacketsSent = 0; + peer->packetsLost = 0; + peer->totalPacketsLost = 0; + peer->packetLoss = 0; + peer->packetLossVariance = 0; + peer->packetThrottle = ENET_PEER_DEFAULT_PACKET_THROTTLE; + peer->packetThrottleLimit = ENET_PEER_PACKET_THROTTLE_SCALE; + peer->packetThrottleCounter = 0; + peer->packetThrottleEpoch = 0; + peer->packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION; + peer->packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION; + peer->packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL; + peer->pingInterval = ENET_PEER_PING_INTERVAL; + peer->timeoutLimit = ENET_PEER_TIMEOUT_LIMIT; + peer->timeoutMinimum = ENET_PEER_TIMEOUT_MINIMUM; + peer->timeoutMaximum = ENET_PEER_TIMEOUT_MAXIMUM; + peer->lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; + peer->lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; + peer->lastRoundTripTimeVariance = 0; + peer->highestRoundTripTimeVariance = 0; + peer->roundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME; + peer->roundTripTimeVariance = 0; + peer->mtu = peer->host->mtu; + peer->reliableDataInTransit = 0; + peer->outgoingReliableSequenceNumber = 0; + peer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + peer->incomingUnsequencedGroup = 0; + peer->outgoingUnsequencedGroup = 0; + peer->eventData = 0; + peer->totalWaitingData = 0; + + memset(peer->unsequencedWindow, 0, sizeof(peer->unsequencedWindow)); + enet_peer_reset_queues(peer); + } + + /** Sends a ping request to a peer. + * @param peer destination for the ping request + * @remarks ping requests factor into the mean round trip time as designated by the + * roundTripTime field in the ENetPeer structure. ENet automatically pings all connected + * peers at regular intervals, however, this function may be called to ensure more + * frequent ping requests. + */ + void enet_peer_ping(ENetPeer *peer) { + ENetProtocol command; + + if (peer->state != ENET_PEER_STATE_CONNECTED) { + return; + } + + command.header.command = ENET_PROTOCOL_COMMAND_PING | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; + command.header.channelID = 0xFF; + + enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0); + } + + /** Sets the interval at which pings will be sent to a peer. + * + * Pings are used both to monitor the liveness of the connection and also to dynamically + * adjust the throttle during periods of low traffic so that the throttle has reasonable + * responsiveness during traffic spikes. + * + * @param peer the peer to adjust + * @param pingInterval the interval at which to send pings; defaults to ENET_PEER_PING_INTERVAL if 0 + */ + void enet_peer_ping_interval(ENetPeer *peer, enet_uint32 pingInterval) { + peer->pingInterval = pingInterval ? pingInterval : (enet_uint32)ENET_PEER_PING_INTERVAL; + } + + /** Sets the timeout parameters for a peer. + * + * The timeout parameter control how and when a peer will timeout from a failure to acknowledge + * reliable traffic. Timeout values use an exponential backoff mechanism, where if a reliable + * packet is not acknowledge within some multiple of the average RTT plus a variance tolerance, + * the timeout will be doubled until it reaches a set limit. If the timeout is thus at this + * limit and reliable packets have been sent but not acknowledged within a certain minimum time + * period, the peer will be disconnected. Alternatively, if reliable packets have been sent + * but not acknowledged for a certain maximum time period, the peer will be disconnected regardless + * of the current timeout limit value. + * + * @param peer the peer to adjust + * @param timeoutLimit the timeout limit; defaults to ENET_PEER_TIMEOUT_LIMIT if 0 + * @param timeoutMinimum the timeout minimum; defaults to ENET_PEER_TIMEOUT_MINIMUM if 0 + * @param timeoutMaximum the timeout maximum; defaults to ENET_PEER_TIMEOUT_MAXIMUM if 0 + */ + + void enet_peer_timeout(ENetPeer *peer, enet_uint32 timeoutLimit, enet_uint32 timeoutMinimum, enet_uint32 timeoutMaximum) { + peer->timeoutLimit = timeoutLimit ? timeoutLimit : (enet_uint32)ENET_PEER_TIMEOUT_LIMIT; + peer->timeoutMinimum = timeoutMinimum ? timeoutMinimum : (enet_uint32)ENET_PEER_TIMEOUT_MINIMUM; + peer->timeoutMaximum = timeoutMaximum ? timeoutMaximum : (enet_uint32)ENET_PEER_TIMEOUT_MAXIMUM; + } + + /** Force an immediate disconnection from a peer. + * @param peer peer to disconnect + * @param data data describing the disconnection + * @remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not + * guaranteed to receive the disconnect notification, and is reset immediately upon + * return from this function. + */ + void enet_peer_disconnect_now(ENetPeer *peer, enet_uint32 data) { + ENetProtocol command; + + if (peer->state == ENET_PEER_STATE_DISCONNECTED) { + return; + } + + if (peer->state != ENET_PEER_STATE_ZOMBIE && peer->state != ENET_PEER_STATE_DISCONNECTING) { + enet_peer_reset_queues(peer); + + command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; + command.header.channelID = 0xFF; + command.disconnect.data = ENET_HOST_TO_NET_32(data); + + enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0); + enet_host_flush(peer->host); + } + + enet_peer_reset(peer); + } + + /** Request a disconnection from a peer. + * @param peer peer to request a disconnection + * @param data data describing the disconnection + * @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service() + * once the disconnection is complete. + */ + void enet_peer_disconnect(ENetPeer *peer, enet_uint32 data) { + ENetProtocol command; + + if (peer->state == ENET_PEER_STATE_DISCONNECTING || + peer->state == ENET_PEER_STATE_DISCONNECTED || + peer->state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT || + peer->state == ENET_PEER_STATE_ZOMBIE + ) { + return; + } + + enet_peer_reset_queues(peer); + + command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT; + command.header.channelID = 0xFF; + command.disconnect.data = ENET_HOST_TO_NET_32(data); + + if (peer->state == ENET_PEER_STATE_CONNECTED || peer->state == ENET_PEER_STATE_DISCONNECT_LATER) { + command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; + } else { + command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED; + } + + enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0); + + if (peer->state == ENET_PEER_STATE_CONNECTED || peer->state == ENET_PEER_STATE_DISCONNECT_LATER) { + enet_peer_on_disconnect(peer); + + peer->state = ENET_PEER_STATE_DISCONNECTING; + } else { + enet_host_flush(peer->host); + enet_peer_reset(peer); + } + } + + /** Request a disconnection from a peer, but only after all queued outgoing packets are sent. + * @param peer peer to request a disconnection + * @param data data describing the disconnection + * @remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service() + * once the disconnection is complete. + */ + void enet_peer_disconnect_later(ENetPeer *peer, enet_uint32 data) { + if ((peer->state == ENET_PEER_STATE_CONNECTED || peer->state == ENET_PEER_STATE_DISCONNECT_LATER) && + !(enet_list_empty(&peer->outgoingReliableCommands) && + enet_list_empty(&peer->outgoingUnreliableCommands) && + enet_list_empty(&peer->sentReliableCommands)) + ) { + peer->state = ENET_PEER_STATE_DISCONNECT_LATER; + peer->eventData = data; + } else { + enet_peer_disconnect(peer, data); + } + } + + ENetAcknowledgement *enet_peer_queue_acknowledgement(ENetPeer *peer, const ENetProtocol *command, enet_uint16 sentTime) { + ENetAcknowledgement *acknowledgement; + + if (command->header.channelID < peer->channelCount) { + ENetChannel *channel = &peer->channels[command->header.channelID]; + enet_uint16 reliableWindow = command->header.reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + enet_uint16 currentWindow = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + + if (command->header.reliableSequenceNumber < channel->incomingReliableSequenceNumber) { + reliableWindow += ENET_PEER_RELIABLE_WINDOWS; + } + + if (reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1 && reliableWindow <= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS) { + return NULL; + } + } + + acknowledgement = (ENetAcknowledgement *) enet_malloc(sizeof(ENetAcknowledgement)); + if (acknowledgement == NULL) { + return NULL; + } + + peer->outgoingDataTotal += sizeof(ENetProtocolAcknowledge); + + acknowledgement->sentTime = sentTime; + acknowledgement->command = *command; + + enet_list_insert(enet_list_end(&peer->acknowledgements), acknowledgement); + return acknowledgement; + } + + void enet_peer_setup_outgoing_command(ENetPeer *peer, ENetOutgoingCommand *outgoingCommand) { + ENetChannel *channel = &peer->channels[outgoingCommand->command.header.channelID]; + peer->outgoingDataTotal += enet_protocol_command_size(outgoingCommand->command.header.command) + outgoingCommand->fragmentLength; + + if (outgoingCommand->command.header.channelID == 0xFF) { + ++peer->outgoingReliableSequenceNumber; + + outgoingCommand->reliableSequenceNumber = peer->outgoingReliableSequenceNumber; + outgoingCommand->unreliableSequenceNumber = 0; + } + else if (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { + ++channel->outgoingReliableSequenceNumber; + channel->outgoingUnreliableSequenceNumber = 0; + + outgoingCommand->reliableSequenceNumber = channel->outgoingReliableSequenceNumber; + outgoingCommand->unreliableSequenceNumber = 0; + } + else if (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED) { + ++peer->outgoingUnsequencedGroup; + + outgoingCommand->reliableSequenceNumber = 0; + outgoingCommand->unreliableSequenceNumber = 0; + } + else { + if (outgoingCommand->fragmentOffset == 0) { + ++channel->outgoingUnreliableSequenceNumber; + } + + outgoingCommand->reliableSequenceNumber = channel->outgoingReliableSequenceNumber; + outgoingCommand->unreliableSequenceNumber = channel->outgoingUnreliableSequenceNumber; + } + + outgoingCommand->sendAttempts = 0; + outgoingCommand->sentTime = 0; + outgoingCommand->roundTripTimeout = 0; + outgoingCommand->roundTripTimeoutLimit = 0; + outgoingCommand->command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16(outgoingCommand->reliableSequenceNumber); + + switch (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK) { + case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: + outgoingCommand->command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16(outgoingCommand->unreliableSequenceNumber); + break; + + case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: + outgoingCommand->command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16(peer->outgoingUnsequencedGroup); + break; + + default: + break; + } + + if (outgoingCommand->command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) { + enet_list_insert(enet_list_end(&peer->outgoingReliableCommands), outgoingCommand); + } else { + enet_list_insert(enet_list_end(&peer->outgoingUnreliableCommands), outgoingCommand); + } + } + + ENetOutgoingCommand * enet_peer_queue_outgoing_command(ENetPeer *peer, const ENetProtocol *command, ENetPacket *packet, enet_uint32 offset, enet_uint16 length) { + ENetOutgoingCommand *outgoingCommand = (ENetOutgoingCommand *) enet_malloc(sizeof(ENetOutgoingCommand)); + + if (outgoingCommand == NULL) { + return NULL; + } + + outgoingCommand->command = *command; + outgoingCommand->fragmentOffset = offset; + outgoingCommand->fragmentLength = length; + outgoingCommand->packet = packet; + if (packet != NULL) { + ++packet->referenceCount; + } + + enet_peer_setup_outgoing_command(peer, outgoingCommand); + return outgoingCommand; + } + + void enet_peer_dispatch_incoming_unreliable_commands(ENetPeer *peer, ENetChannel *channel) { + ENetListIterator droppedCommand, startCommand, currentCommand; + + for (droppedCommand = startCommand = currentCommand = enet_list_begin(&channel->incomingUnreliableCommands); + currentCommand != enet_list_end(&channel->incomingUnreliableCommands); + currentCommand = enet_list_next(currentCommand) + ) { + ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand; + + if ((incomingCommand->command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) { + continue; + } + + if (incomingCommand->reliableSequenceNumber == channel->incomingReliableSequenceNumber) { + if (incomingCommand->fragmentsRemaining <= 0) { + channel->incomingUnreliableSequenceNumber = incomingCommand->unreliableSequenceNumber; + continue; + } + + if (startCommand != currentCommand) { + enet_list_move(enet_list_end(&peer->dispatchedCommands), startCommand, enet_list_previous(currentCommand)); + + if (!peer->needsDispatch) { + enet_list_insert(enet_list_end(&peer->host->dispatchQueue), &peer->dispatchList); + peer->needsDispatch = 1; + } + + droppedCommand = currentCommand; + } else if (droppedCommand != currentCommand) { + droppedCommand = enet_list_previous(currentCommand); + } + } else { + enet_uint16 reliableWindow = incomingCommand->reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + enet_uint16 currentWindow = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + + if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) { + reliableWindow += ENET_PEER_RELIABLE_WINDOWS; + } + + if (reliableWindow >= currentWindow && reliableWindow < currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) { + break; + } + + droppedCommand = enet_list_next(currentCommand); + + if (startCommand != currentCommand) { + enet_list_move(enet_list_end(&peer->dispatchedCommands), startCommand, enet_list_previous(currentCommand)); + + if (!peer->needsDispatch) { + enet_list_insert(enet_list_end(&peer->host->dispatchQueue), &peer->dispatchList); + peer->needsDispatch = 1; + } + } + } + + startCommand = enet_list_next(currentCommand); + } + + if (startCommand != currentCommand) { + enet_list_move(enet_list_end(&peer->dispatchedCommands), startCommand, enet_list_previous(currentCommand)); + + if (!peer->needsDispatch) { + enet_list_insert(enet_list_end(&peer->host->dispatchQueue), &peer->dispatchList); + peer->needsDispatch = 1; + } + + droppedCommand = currentCommand; + } + + enet_peer_remove_incoming_commands(&channel->incomingUnreliableCommands,enet_list_begin(&channel->incomingUnreliableCommands), droppedCommand); + } + + void enet_peer_dispatch_incoming_reliable_commands(ENetPeer *peer, ENetChannel *channel) { + ENetListIterator currentCommand; + + for (currentCommand = enet_list_begin(&channel->incomingReliableCommands); + currentCommand != enet_list_end(&channel->incomingReliableCommands); + currentCommand = enet_list_next(currentCommand) + ) { + ENetIncomingCommand *incomingCommand = (ENetIncomingCommand *) currentCommand; + + if (incomingCommand->fragmentsRemaining > 0 || incomingCommand->reliableSequenceNumber != (enet_uint16) (channel->incomingReliableSequenceNumber + 1)) { + break; + } + + channel->incomingReliableSequenceNumber = incomingCommand->reliableSequenceNumber; + + if (incomingCommand->fragmentCount > 0) { + channel->incomingReliableSequenceNumber += incomingCommand->fragmentCount - 1; + } + } + + if (currentCommand == enet_list_begin(&channel->incomingReliableCommands)) { + return; + } + + channel->incomingUnreliableSequenceNumber = 0; + enet_list_move(enet_list_end(&peer->dispatchedCommands), enet_list_begin(&channel->incomingReliableCommands), enet_list_previous(currentCommand)); + + if (!peer->needsDispatch) { + enet_list_insert(enet_list_end(&peer->host->dispatchQueue), &peer->dispatchList); + peer->needsDispatch = 1; + } + + if (!enet_list_empty(&channel->incomingUnreliableCommands)) { + enet_peer_dispatch_incoming_unreliable_commands(peer, channel); + } + } + + ENetIncomingCommand * enet_peer_queue_incoming_command(ENetPeer *peer, const ENetProtocol *command, const void *data, size_t dataLength, enet_uint32 flags, enet_uint32 fragmentCount) { + static ENetIncomingCommand dummyCommand; + + ENetChannel *channel = &peer->channels[command->header.channelID]; + enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber = 0; + enet_uint16 reliableWindow, currentWindow; + ENetIncomingCommand *incomingCommand; + ENetListIterator currentCommand; + ENetPacket *packet = NULL; + + if (peer->state == ENET_PEER_STATE_DISCONNECT_LATER) { + goto discardCommand; + } + + if ((command->header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) { + reliableSequenceNumber = command->header.reliableSequenceNumber; + reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + currentWindow = channel->incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE; + + if (reliableSequenceNumber < channel->incomingReliableSequenceNumber) { + reliableWindow += ENET_PEER_RELIABLE_WINDOWS; + } + + if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1) { + goto discardCommand; + } + } + + switch (command->header.command & ENET_PROTOCOL_COMMAND_MASK) { + case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: + case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: + if (reliableSequenceNumber == channel->incomingReliableSequenceNumber) { + goto discardCommand; + } + + for (currentCommand = enet_list_previous(enet_list_end(&channel->incomingReliableCommands)); + currentCommand != enet_list_end(&channel->incomingReliableCommands); + currentCommand = enet_list_previous(currentCommand) + ) { + incomingCommand = (ENetIncomingCommand *) currentCommand; + + if (reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { + if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) { + continue; + } + } else if (incomingCommand->reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { + break; + } + + if (incomingCommand->reliableSequenceNumber <= reliableSequenceNumber) { + if (incomingCommand->reliableSequenceNumber < reliableSequenceNumber) { + break; + } + + goto discardCommand; + } + } + break; + + case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE: + case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT: + unreliableSequenceNumber = ENET_NET_TO_HOST_16(command->sendUnreliable.unreliableSequenceNumber); + + if (reliableSequenceNumber == channel->incomingReliableSequenceNumber && unreliableSequenceNumber <= channel->incomingUnreliableSequenceNumber) { + goto discardCommand; + } + + for (currentCommand = enet_list_previous(enet_list_end(&channel->incomingUnreliableCommands)); + currentCommand != enet_list_end(&channel->incomingUnreliableCommands); + currentCommand = enet_list_previous(currentCommand) + ) { + incomingCommand = (ENetIncomingCommand *) currentCommand; + + if ((command->header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED) { + continue; + } + + if (reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { + if (incomingCommand->reliableSequenceNumber < channel->incomingReliableSequenceNumber) { + continue; + } + } else if (incomingCommand->reliableSequenceNumber >= channel->incomingReliableSequenceNumber) { + break; + } + + if (incomingCommand->reliableSequenceNumber < reliableSequenceNumber) { + break; + } + + if (incomingCommand->reliableSequenceNumber > reliableSequenceNumber) { + continue; + } + + if (incomingCommand->unreliableSequenceNumber <= unreliableSequenceNumber) { + if (incomingCommand->unreliableSequenceNumber < unreliableSequenceNumber) { + break; + } + + goto discardCommand; + } + } + break; + + case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED: + currentCommand = enet_list_end(&channel->incomingUnreliableCommands); + break; + + default: + goto discardCommand; + } + + if (peer->totalWaitingData >= peer->host->maximumWaitingData) { + goto notifyError; + } + + packet = callbacks.packet_create(data, dataLength, flags); + if (packet == NULL) { + goto notifyError; + } + + incomingCommand = (ENetIncomingCommand *) enet_malloc(sizeof(ENetIncomingCommand)); + if (incomingCommand == NULL) { + goto notifyError; + } + + incomingCommand->reliableSequenceNumber = command->header.reliableSequenceNumber; + incomingCommand->unreliableSequenceNumber = unreliableSequenceNumber & 0xFFFF; + incomingCommand->command = *command; + incomingCommand->fragmentCount = fragmentCount; + incomingCommand->fragmentsRemaining = fragmentCount; + incomingCommand->packet = packet; + incomingCommand->fragments = NULL; + + if (fragmentCount > 0) { + if (fragmentCount <= ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT) { + incomingCommand->fragments = (enet_uint32 *) enet_malloc((fragmentCount + 31) / 32 * sizeof(enet_uint32)); + } + + if (incomingCommand->fragments == NULL) { + enet_free(incomingCommand); + + goto notifyError; + } + + memset(incomingCommand->fragments, 0, (fragmentCount + 31) / 32 * sizeof(enet_uint32)); + } + + if (packet != NULL) { + ++packet->referenceCount; + peer->totalWaitingData += packet->dataLength; + } + + enet_list_insert(enet_list_next(currentCommand), incomingCommand); + + switch (command->header.command & ENET_PROTOCOL_COMMAND_MASK) { + case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT: + case ENET_PROTOCOL_COMMAND_SEND_RELIABLE: + enet_peer_dispatch_incoming_reliable_commands(peer, channel); + break; + + default: + enet_peer_dispatch_incoming_unreliable_commands(peer, channel); + break; + } + + return incomingCommand; + + discardCommand: + if (fragmentCount > 0) { + goto notifyError; + } + + if (packet != NULL && packet->referenceCount == 0) { + callbacks.packet_destroy(packet); + } + + return &dummyCommand; + + notifyError: + if (packet != NULL && packet->referenceCount == 0) { + callbacks.packet_destroy(packet); + } + + return NULL; + } /* enet_peer_queue_incoming_command */ + +// =======================================================================// +// ! +// ! Host +// ! +// =======================================================================// + + /** Creates a host for communicating to peers. + * + * @param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host. + * @param peerCount the maximum number of peers that should be allocated for the host. + * @param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT + * @param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth. + * @param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth. + * + * @returns the host on success and NULL on failure + * + * @remarks ENet will strategically drop packets on specific sides of a connection between hosts + * to ensure the host's bandwidth is not overwhelmed. The bandwidth parameters also determine + * the window size of a connection which limits the amount of reliable packets that may be in transit + * at any given time. + */ + ENetHost * enet_host_create(const ENetAddress *address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth) { + ENetHost *host; + ENetPeer *currentPeer; + + if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID) { + return NULL; + } + + host = (ENetHost *) enet_malloc(sizeof(ENetHost)); + if (host == NULL) { return NULL; } + memset(host, 0, sizeof(ENetHost)); + + host->peers = (ENetPeer *) enet_malloc(peerCount * sizeof(ENetPeer)); + if (host->peers == NULL) { + enet_free(host); + return NULL; + } + + memset(host->peers, 0, peerCount * sizeof(ENetPeer)); + + host->socket = enet_socket_create(ENET_SOCKET_TYPE_DATAGRAM); + if (host->socket != ENET_SOCKET_NULL) { + enet_socket_set_option (host->socket, ENET_SOCKOPT_IPV6_V6ONLY, 0); + } + + if (host->socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind(host->socket, address) < 0)) { + if (host->socket != ENET_SOCKET_NULL) { + enet_socket_destroy(host->socket); + } + + enet_free(host->peers); + enet_free(host); + + return NULL; + } + + enet_socket_set_option(host->socket, ENET_SOCKOPT_NONBLOCK, 1); + enet_socket_set_option(host->socket, ENET_SOCKOPT_BROADCAST, 1); + enet_socket_set_option(host->socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE); + enet_socket_set_option(host->socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE); + enet_socket_set_option(host->socket, ENET_SOCKOPT_IPV6_V6ONLY, 0); + + if (address != NULL && enet_socket_get_address(host->socket, &host->address) < 0) { + host->address = *address; + } + + if (!channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { + channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; + } + + host->randomSeed = (enet_uint32) ((uintptr_t) host % UINT32_MAX); + host->randomSeed += enet_host_random_seed(); + host->randomSeed = (host->randomSeed << 16) | (host->randomSeed >> 16); + host->channelLimit = channelLimit; + host->incomingBandwidth = incomingBandwidth; + host->outgoingBandwidth = outgoingBandwidth; + host->bandwidthThrottleEpoch = 0; + host->recalculateBandwidthLimits = 0; + host->mtu = ENET_HOST_DEFAULT_MTU; + host->peerCount = peerCount; + host->commandCount = 0; + host->bufferCount = 0; + host->checksum = NULL; + host->receivedAddress.host = ENET_HOST_ANY; + host->receivedAddress.port = 0; + host->receivedData = NULL; + host->receivedDataLength = 0; + host->totalSentData = 0; + host->totalSentPackets = 0; + host->totalReceivedData = 0; + host->totalReceivedPackets = 0; + host->connectedPeers = 0; + host->bandwidthLimitedPeers = 0; + host->duplicatePeers = ENET_PROTOCOL_MAXIMUM_PEER_ID; + host->maximumPacketSize = ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE; + host->maximumWaitingData = ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA; + host->compressor.context = NULL; + host->compressor.compress = NULL; + host->compressor.decompress = NULL; + host->compressor.destroy = NULL; + host->intercept = NULL; + + enet_list_clear(&host->dispatchQueue); + + for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) { + currentPeer->host = host; + currentPeer->incomingPeerID = currentPeer - host->peers; + currentPeer->outgoingSessionID = currentPeer->incomingSessionID = 0xFF; + currentPeer->data = NULL; + + enet_list_clear(¤tPeer->acknowledgements); + enet_list_clear(¤tPeer->sentReliableCommands); + enet_list_clear(¤tPeer->sentUnreliableCommands); + enet_list_clear(¤tPeer->outgoingReliableCommands); + enet_list_clear(¤tPeer->outgoingUnreliableCommands); + enet_list_clear(¤tPeer->dispatchedCommands); + + enet_peer_reset(currentPeer); + } + + return host; + } /* enet_host_create */ + + /** Destroys the host and all resources associated with it. + * @param host pointer to the host to destroy + */ + void enet_host_destroy(ENetHost *host) { + ENetPeer *currentPeer; + + if (host == NULL) { + return; + } + + enet_socket_destroy(host->socket); + + for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) { + enet_peer_reset(currentPeer); + } + + if (host->compressor.context != NULL && host->compressor.destroy) { + (*host->compressor.destroy)(host->compressor.context); + } + + enet_free(host->peers); + enet_free(host); + } + + /** Initiates a connection to a foreign host. + * @param host host seeking the connection + * @param address destination for the connection + * @param channelCount number of channels to allocate + * @param data user data supplied to the receiving host + * @returns a peer representing the foreign host on success, NULL on failure + * @remarks The peer returned will have not completed the connection until enet_host_service() + * notifies of an ENET_EVENT_TYPE_CONNECT event for the peer. + */ + ENetPeer * enet_host_connect(ENetHost *host, const ENetAddress *address, size_t channelCount, enet_uint32 data) { + ENetPeer *currentPeer; + ENetChannel *channel; + ENetProtocol command; + + if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT) { + channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT; + } else if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { + channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; + } + + for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) { + if (currentPeer->state == ENET_PEER_STATE_DISCONNECTED) { + break; + } + } + + if (currentPeer >= &host->peers[host->peerCount]) { + return NULL; + } + + currentPeer->channels = (ENetChannel *) enet_malloc(channelCount * sizeof(ENetChannel)); + if (currentPeer->channels == NULL) { + return NULL; + } + + currentPeer->channelCount = channelCount; + currentPeer->state = ENET_PEER_STATE_CONNECTING; + currentPeer->address = *address; + currentPeer->connectID = ++host->randomSeed; + + if (host->outgoingBandwidth == 0) { + currentPeer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + } else { + currentPeer->windowSize = (host->outgoingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + } + + if (currentPeer->windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE) { + currentPeer->windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE; + } else if (currentPeer->windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE) { + currentPeer->windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE; + } + + for (channel = currentPeer->channels; channel < ¤tPeer->channels[channelCount]; ++channel) { + channel->outgoingReliableSequenceNumber = 0; + channel->outgoingUnreliableSequenceNumber = 0; + channel->incomingReliableSequenceNumber = 0; + channel->incomingUnreliableSequenceNumber = 0; + + enet_list_clear(&channel->incomingReliableCommands); + enet_list_clear(&channel->incomingUnreliableCommands); + + channel->usedReliableWindows = 0; + memset(channel->reliableWindows, 0, sizeof(channel->reliableWindows)); + } + + command.header.command = ENET_PROTOCOL_COMMAND_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; + command.header.channelID = 0xFF; + command.connect.outgoingPeerID = ENET_HOST_TO_NET_16(currentPeer->incomingPeerID); + command.connect.incomingSessionID = currentPeer->incomingSessionID; + command.connect.outgoingSessionID = currentPeer->outgoingSessionID; + command.connect.mtu = ENET_HOST_TO_NET_32(currentPeer->mtu); + command.connect.windowSize = ENET_HOST_TO_NET_32(currentPeer->windowSize); + command.connect.channelCount = ENET_HOST_TO_NET_32(channelCount); + command.connect.incomingBandwidth = ENET_HOST_TO_NET_32(host->incomingBandwidth); + command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32(host->outgoingBandwidth); + command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32(currentPeer->packetThrottleInterval); + command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32(currentPeer->packetThrottleAcceleration); + command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32(currentPeer->packetThrottleDeceleration); + command.connect.connectID = currentPeer->connectID; + command.connect.data = ENET_HOST_TO_NET_32(data); + + enet_peer_queue_outgoing_command(currentPeer, &command, NULL, 0, 0); + + return currentPeer; + } /* enet_host_connect */ + + /** Queues a packet to be sent to all peers associated with the host. + * @param host host on which to broadcast the packet + * @param channelID channel on which to broadcast + * @param packet packet to broadcast + */ + void enet_host_broadcast(ENetHost *host, enet_uint8 channelID, ENetPacket *packet) { + ENetPeer *currentPeer; + + for (currentPeer = host->peers; currentPeer < &host->peers[host->peerCount]; ++currentPeer) { + if (currentPeer->state != ENET_PEER_STATE_CONNECTED) { + continue; + } + + enet_peer_send(currentPeer, channelID, packet); + } + + if (packet->referenceCount == 0) { + callbacks.packet_destroy(packet); + } + } + + /** Sends raw data to specified address. Useful when you want to send unconnected data using host's socket. + * @param host host sending data + * @param address destination address + * @param data data pointer + * @param dataLength length of data to send + * @retval >=0 bytes sent + * @retval <0 error + * @sa enet_socket_send + */ + int enet_host_send_raw(ENetHost *host, const ENetAddress* address, enet_uint8* data, size_t dataLength) { + ENetBuffer buffer; + buffer.data = data; + buffer.dataLength = dataLength; + return enet_socket_send(host->socket, address, &buffer, 1); + } + + /** Sends raw data to specified address with extended arguments. Allows to send only part of data, handy for other programming languages. + * I.e. if you have data =- { 0, 1, 2, 3 } and call function as enet_host_send_raw_ex(data, 1, 2) then it will skip 1 byte and send 2 bytes { 1, 2 }. + * @param host host sending data + * @param address destination address + * @param data data pointer + * @param skipBytes number of bytes to skip from start of data + * @param bytesToSend number of bytes to send + * @retval >=0 bytes sent + * @retval <0 error + * @sa enet_socket_send + */ + int enet_host_send_raw_ex(ENetHost *host, const ENetAddress* address, enet_uint8* data, size_t skipBytes, size_t bytesToSend) { + ENetBuffer buffer; + buffer.data = data + skipBytes; + buffer.dataLength = bytesToSend; + return enet_socket_send(host->socket, address, &buffer, 1); + } + + /** Sets intercept callback for the host. + * @param host host to set a callback + * @param callback intercept callback + */ + void enet_host_set_intercept(ENetHost *host, const ENetInterceptCallback callback) { + host->intercept = callback; + } + + /** Sets the packet compressor the host should use to compress and decompress packets. + * @param host host to enable or disable compression for + * @param compressor callbacks for for the packet compressor; if NULL, then compression is disabled + */ + void enet_host_compress(ENetHost *host, const ENetCompressor *compressor) { + if (host->compressor.context != NULL && host->compressor.destroy) { + (*host->compressor.destroy)(host->compressor.context); + } + + if (compressor) { + host->compressor = *compressor; + } else { + host->compressor.context = NULL; + } + } + + /** Limits the maximum allowed channels of future incoming connections. + * @param host host to limit + * @param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT + */ + void enet_host_channel_limit(ENetHost *host, size_t channelLimit) { + if (!channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT) { + channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT; + } + host->channelLimit = channelLimit; + } + + /** Adjusts the bandwidth limits of a host. + * @param host host to adjust + * @param incomingBandwidth new incoming bandwidth + * @param outgoingBandwidth new outgoing bandwidth + * @remarks the incoming and outgoing bandwidth parameters are identical in function to those + * specified in enet_host_create(). + */ + void enet_host_bandwidth_limit(ENetHost *host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth) { + host->incomingBandwidth = incomingBandwidth; + host->outgoingBandwidth = outgoingBandwidth; + host->recalculateBandwidthLimits = 1; + } + + void enet_host_bandwidth_throttle(ENetHost *host) { + enet_uint32 timeCurrent = enet_time_get(); + enet_uint32 elapsedTime = timeCurrent - host->bandwidthThrottleEpoch; + enet_uint32 peersRemaining = (enet_uint32) host->connectedPeers; + enet_uint32 dataTotal = ~0; + enet_uint32 bandwidth = ~0; + enet_uint32 throttle = 0; + enet_uint32 bandwidthLimit = 0; + + int needsAdjustment = host->bandwidthLimitedPeers > 0 ? 1 : 0; + ENetPeer *peer; + ENetProtocol command; + + if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL) { + return; + } + + if (host->outgoingBandwidth == 0 && host->incomingBandwidth == 0) { + return; + } + + host->bandwidthThrottleEpoch = timeCurrent; + + if (peersRemaining == 0) { + return; + } + + if (host->outgoingBandwidth != 0) { + dataTotal = 0; + bandwidth = (host->outgoingBandwidth * elapsedTime) / 1000; + + for (peer = host->peers; peer < &host->peers[host->peerCount]; ++peer) { + if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { + continue; + } + + dataTotal += peer->outgoingDataTotal; + } + } + + while (peersRemaining > 0 && needsAdjustment != 0) { + needsAdjustment = 0; + + if (dataTotal <= bandwidth) { + throttle = ENET_PEER_PACKET_THROTTLE_SCALE; + } else { + throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal; + } + + for (peer = host->peers; peer < &host->peers[host->peerCount]; ++peer) { + enet_uint32 peerBandwidth; + + if ((peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) || + peer->incomingBandwidth == 0 || + peer->outgoingBandwidthThrottleEpoch == timeCurrent + ) { + continue; + } + + peerBandwidth = (peer->incomingBandwidth * elapsedTime) / 1000; + if ((throttle * peer->outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth) { + continue; + } + + peer->packetThrottleLimit = (peerBandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / peer->outgoingDataTotal; + + if (peer->packetThrottleLimit == 0) { + peer->packetThrottleLimit = 1; + } + + if (peer->packetThrottle > peer->packetThrottleLimit) { + peer->packetThrottle = peer->packetThrottleLimit; + } + + peer->outgoingBandwidthThrottleEpoch = timeCurrent; + + peer->incomingDataTotal = 0; + peer->outgoingDataTotal = 0; + + needsAdjustment = 1; + --peersRemaining; + bandwidth -= peerBandwidth; + dataTotal -= peerBandwidth; + } + } + + if (peersRemaining > 0) { + if (dataTotal <= bandwidth) { + throttle = ENET_PEER_PACKET_THROTTLE_SCALE; + } else { + throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal; + } + + for (peer = host->peers; + peer < &host->peers[host->peerCount]; + ++peer) + { + if ((peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) || peer->outgoingBandwidthThrottleEpoch == timeCurrent) { + continue; + } + + peer->packetThrottleLimit = throttle; + + if (peer->packetThrottle > peer->packetThrottleLimit) { + peer->packetThrottle = peer->packetThrottleLimit; + } + + peer->incomingDataTotal = 0; + peer->outgoingDataTotal = 0; + } + } + + if (host->recalculateBandwidthLimits) { + host->recalculateBandwidthLimits = 0; + + peersRemaining = (enet_uint32) host->connectedPeers; + bandwidth = host->incomingBandwidth; + needsAdjustment = 1; + + if (bandwidth == 0) { + bandwidthLimit = 0; + } else { + while (peersRemaining > 0 && needsAdjustment != 0) { + needsAdjustment = 0; + bandwidthLimit = bandwidth / peersRemaining; + + for (peer = host->peers; peer < &host->peers[host->peerCount]; ++peer) { + if ((peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) || + peer->incomingBandwidthThrottleEpoch == timeCurrent + ) { + continue; + } + + if (peer->outgoingBandwidth > 0 && peer->outgoingBandwidth >= bandwidthLimit) { + continue; + } + + peer->incomingBandwidthThrottleEpoch = timeCurrent; + + needsAdjustment = 1; + --peersRemaining; + bandwidth -= peer->outgoingBandwidth; + } + } + } + + for (peer = host->peers; peer < &host->peers[host->peerCount]; ++peer) { + if (peer->state != ENET_PEER_STATE_CONNECTED && peer->state != ENET_PEER_STATE_DISCONNECT_LATER) { + continue; + } + + command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE; + command.header.channelID = 0xFF; + command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32(host->outgoingBandwidth); + + if (peer->incomingBandwidthThrottleEpoch == timeCurrent) { + command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32(peer->outgoingBandwidth); + } else { + command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32(bandwidthLimit); + } + + enet_peer_queue_outgoing_command(peer, &command, NULL, 0, 0); + } + } + } /* enet_host_bandwidth_throttle */ + +// =======================================================================// +// ! +// ! Time +// ! +// =======================================================================// + + #ifdef _WIN32 + static LARGE_INTEGER getFILETIMEoffset() { + SYSTEMTIME s; + FILETIME f; + LARGE_INTEGER t; + + s.wYear = 1970; + s.wMonth = 1; + s.wDay = 1; + s.wHour = 0; + s.wMinute = 0; + s.wSecond = 0; + s.wMilliseconds = 0; + SystemTimeToFileTime(&s, &f); + t.QuadPart = f.dwHighDateTime; + t.QuadPart <<= 32; + t.QuadPart |= f.dwLowDateTime; + return (t); + } + int clock_gettime(int X, struct timespec *tv) { + (void)X; + LARGE_INTEGER t; + FILETIME f; + double microseconds; + static LARGE_INTEGER offset; + static double frequencyToMicroseconds; + static int initialized = 0; + static BOOL usePerformanceCounter = 0; + + if (!initialized) { + LARGE_INTEGER performanceFrequency; + initialized = 1; + usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency); + if (usePerformanceCounter) { + QueryPerformanceCounter(&offset); + frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.; + } else { + offset = getFILETIMEoffset(); + frequencyToMicroseconds = 10.; + } + } + if (usePerformanceCounter) { + QueryPerformanceCounter(&t); + } else { + GetSystemTimeAsFileTime(&f); + t.QuadPart = f.dwHighDateTime; + t.QuadPart <<= 32; + t.QuadPart |= f.dwLowDateTime; + } + + t.QuadPart -= offset.QuadPart; + microseconds = (double)t.QuadPart / frequencyToMicroseconds; + t.QuadPart = (LONGLONG)microseconds; + tv->tv_sec = (long)(t.QuadPart / 1000000); + tv->tv_nsec = t.QuadPart % 1000000 * 1000; + return (0); + } + #elif __APPLE__ && __MAC_OS_X_VERSION_MIN_REQUIRED < 101200 + #define CLOCK_MONOTONIC 0 + + int clock_gettime(int X, struct timespec *ts) { + clock_serv_t cclock; + mach_timespec_t mts; + + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_time(cclock, &mts); + mach_port_deallocate(mach_task_self(), cclock); + + ts->tv_sec = mts.tv_sec; + ts->tv_nsec = mts.tv_nsec; + + return 0; + } + #endif + + enet_uint32 enet_time_get() { + // TODO enet uses 32 bit timestamps. We should modify it to use + // 64 bit timestamps, but this is not trivial since we'd end up + // changing half the structs in enet. For now, retain 32 bits, but + // use an offset so we don't run out of bits. Basically, the first + // call of enet_time_get() will always return 1, and follow-up calls + // indicate elapsed time since the first call. + // + // Note that we don't want to return 0 from the first call, in case + // some part of enet uses 0 as a special value (meaning time not set + // for example). + static uint64_t start_time_ns = 0; + + struct timespec ts; + #if defined(CLOCK_MONOTONIC_RAW) + clock_gettime(CLOCK_MONOTONIC_RAW, &ts); + #else + clock_gettime(CLOCK_MONOTONIC, &ts); + #endif + + static const uint64_t ns_in_s = 1000 * 1000 * 1000; + static const uint64_t ns_in_ms = 1000 * 1000; + uint64_t current_time_ns = ts.tv_nsec + (uint64_t)ts.tv_sec * ns_in_s; + + // Most of the time we just want to atomically read the start time. We + // could just use a single CAS instruction instead of this if, but it + // would be slower in the average case. + // + // Note that statics are auto-initialized to zero, and starting a thread + // implies a memory barrier. So we know that whatever thread calls this, + // it correctly sees the start_time_ns as 0 initially. + uint64_t offset_ns = ENET_ATOMIC_READ(&start_time_ns); + if (offset_ns == 0) { + // We still need to CAS, since two different threads can get here + // at the same time. + // + // We assume that current_time_ns is > 1ms. + // + // Set the value of the start_time_ns, such that the first timestamp + // is at 1ms. This ensures 0 remains a special value. + uint64_t want_value = current_time_ns - 1 * ns_in_ms; + uint64_t old_value = ENET_ATOMIC_CAS(&start_time_ns, 0, want_value); + offset_ns = old_value == 0 ? want_value : old_value; + } + + uint64_t result_in_ns = current_time_ns - offset_ns; + return (enet_uint32)(result_in_ns / ns_in_ms); + } + + void enet_inaddr_map4to6(struct in_addr in, struct in6_addr *out) + { + if (in.s_addr == 0x00000000) { /* 0.0.0.0 */ + *out = enet_v6_anyaddr; + } else if (in.s_addr == 0xFFFFFFFF) { /* 255.255.255.255 */ + *out = enet_v6_noaddr; + } else { + *out = enet_v4_anyaddr; + out->s6_addr[10] = 0xFF; + out->s6_addr[11] = 0xFF; + out->s6_addr[12] = ((uint8_t *)&in.s_addr)[0]; + out->s6_addr[13] = ((uint8_t *)&in.s_addr)[1]; + out->s6_addr[14] = ((uint8_t *)&in.s_addr)[2]; + out->s6_addr[15] = ((uint8_t *)&in.s_addr)[3]; + } + } + void enet_inaddr_map6to4(const struct in6_addr *in, struct in_addr *out) + { + memset(out, 0, sizeof(struct in_addr)); + ((uint8_t *)&out->s_addr)[0] = in->s6_addr[12]; + ((uint8_t *)&out->s_addr)[1] = in->s6_addr[13]; + ((uint8_t *)&out->s_addr)[2] = in->s6_addr[14]; + ((uint8_t *)&out->s_addr)[3] = in->s6_addr[15]; + } + + int enet_in6addr_lookup_host(const char *name, bool nodns, ENetAddress *out) { + struct addrinfo hints, *resultList = NULL, *result = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + + if (nodns) + { + hints.ai_flags = AI_NUMERICHOST; /* prevent actual DNS lookups! */ + } + + if (getaddrinfo(name, NULL, &hints, &resultList) != 0) { + freeaddrinfo(resultList); + return -1; + } + + for (result = resultList; result != NULL; result = result->ai_next) { + if (result->ai_addr != NULL) { + if (result->ai_family == AF_INET || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in))) { + enet_inaddr_map4to6(((struct sockaddr_in*)result->ai_addr)->sin_addr, &out->host); + out->sin6_scope_id = 0; + freeaddrinfo(resultList); + return 0; + + } else if (result->ai_family == AF_INET6 || (result->ai_family == AF_UNSPEC && result->ai_addrlen == sizeof(struct sockaddr_in6))) { + memcpy(&out->host, &((struct sockaddr_in6*)result->ai_addr)->sin6_addr, sizeof(struct in6_addr)); + out->sin6_scope_id = (enet_uint16) ((struct sockaddr_in6*)result->ai_addr)->sin6_scope_id; + freeaddrinfo(resultList); + return 0; + } + } + } + freeaddrinfo(resultList); + return -1; + } + + int enet_address_set_host_ip_new(ENetAddress *address, const char *name) { + return enet_in6addr_lookup_host(name, true, address); + } + + int enet_address_set_host_new(ENetAddress *address, const char *name) { + return enet_in6addr_lookup_host(name, false, address); + } + + int enet_address_get_host_ip_new(const ENetAddress *address, char *name, size_t nameLength) { + if (IN6_IS_ADDR_V4MAPPED(&address->host)) { + struct in_addr buf; + enet_inaddr_map6to4(&address->host, &buf); + + if (inet_ntop(AF_INET, &buf, name, nameLength) == NULL) { + return -1; + } + } + else { + if (inet_ntop(AF_INET6, (void*)&address->host, name, nameLength) == NULL) { + return -1; + } + } + + return 0; + } /* enet_address_get_host_ip_new */ + + int enet_address_get_host_new(const ENetAddress *address, char *name, size_t nameLength) { + struct sockaddr_in6 sin; + memset(&sin, 0, sizeof(struct sockaddr_in6)); + + int err; + + + sin.sin6_family = AF_INET6; + sin.sin6_port = ENET_HOST_TO_NET_16 (address->port); + sin.sin6_addr = address->host; + sin.sin6_scope_id = address->sin6_scope_id; + + err = getnameinfo((struct sockaddr *) &sin, sizeof(sin), name, nameLength, NULL, 0, NI_NAMEREQD); + if (!err) { + if (name != NULL && nameLength > 0 && !memchr(name, '\0', nameLength)) { + return -1; + } + return 0; + } + if (err != EAI_NONAME) { + return -1; + } + + return enet_address_get_host_ip_new(address, name, nameLength); + } /* enet_address_get_host_new */ + +// =======================================================================// +// ! +// ! Platform Specific (Unix) +// ! +// =======================================================================// + + #ifndef _WIN32 + + #if defined(__MINGW32__) && defined(ENET_MINGW_COMPAT) + // inet_ntop/inet_pton for MinGW from http://mingw-users.1079350.n2.nabble.com/IPv6-getaddrinfo-amp-inet-ntop-td5891996.html + const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt) { + if (af == AF_INET) { + struct sockaddr_in in; + memset(&in, 0, sizeof(in)); + in.sin_family = AF_INET; + memcpy(&in.sin_addr, src, sizeof(struct in_addr)); + getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST); + return dst; + } + else if (af == AF_INET6) { + struct sockaddr_in6 in; + memset(&in, 0, sizeof(in)); + in.sin6_family = AF_INET6; + memcpy(&in.sin6_addr, src, sizeof(struct in_addr6)); + getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST); + return dst; + } + + return NULL; + } + + #define NS_INADDRSZ 4 + #define NS_IN6ADDRSZ 16 + #define NS_INT16SZ 2 + + int inet_pton4(const char *src, char *dst) { + uint8_t tmp[NS_INADDRSZ], *tp; + + int saw_digit = 0; + int octets = 0; + *(tp = tmp) = 0; + + int ch; + while ((ch = *src++) != '\0') + { + if (ch >= '0' && ch <= '9') + { + uint32_t n = *tp * 10 + (ch - '0'); + + if (saw_digit && *tp == 0) + return 0; + + if (n > 255) + return 0; + + *tp = n; + if (!saw_digit) + { + if (++octets > 4) + return 0; + saw_digit = 1; + } + } + else if (ch == '.' && saw_digit) + { + if (octets == 4) + return 0; + *++tp = 0; + saw_digit = 0; + } + else + return 0; + } + if (octets < 4) + return 0; + + memcpy(dst, tmp, NS_INADDRSZ); + + return 1; + } + + int inet_pton6(const char *src, char *dst) { + static const char xdigits[] = "0123456789abcdef"; + uint8_t tmp[NS_IN6ADDRSZ]; + + uint8_t *tp = (uint8_t*) memset(tmp, '\0', NS_IN6ADDRSZ); + uint8_t *endp = tp + NS_IN6ADDRSZ; + uint8_t *colonp = NULL; + + /* Leading :: requires some special handling. */ + if (*src == ':') + { + if (*++src != ':') + return 0; + } + + const char *curtok = src; + int saw_xdigit = 0; + uint32_t val = 0; + int ch; + while ((ch = tolower(*src++)) != '\0') + { + const char *pch = strchr(xdigits, ch); + if (pch != NULL) + { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return 0; + saw_xdigit = 1; + continue; + } + if (ch == ':') + { + curtok = src; + if (!saw_xdigit) + { + if (colonp) + return 0; + colonp = tp; + continue; + } + else if (*src == '\0') + { + return 0; + } + if (tp + NS_INT16SZ > endp) + return 0; + *tp++ = (uint8_t) (val >> 8) & 0xff; + *tp++ = (uint8_t) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, (char*) tp) > 0) + { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return 0; + } + if (saw_xdigit) + { + if (tp + NS_INT16SZ > endp) + return 0; + *tp++ = (uint8_t) (val >> 8) & 0xff; + *tp++ = (uint8_t) val & 0xff; + } + if (colonp != NULL) + { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + + if (tp == endp) + return 0; + + for (int i = 1; i <= n; i++) + { + endp[-i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return 0; + + memcpy(dst, tmp, NS_IN6ADDRSZ); + + return 1; + } + + + int inet_pton(int af, const char *src, struct in6_addr *dst) { + switch (af) + { + case AF_INET: + return inet_pton4(src, (char *)dst); + case AF_INET6: + return inet_pton6(src, (char *)dst); + default: + return -1; + } + } + #endif // __MINGW__ + + int enet_initialize(void) { + return 0; + } + + void enet_deinitialize(void) {} + + enet_uint64 enet_host_random_seed(void) { + return (enet_uint64) time(NULL); + } + + int enet_address_set_host_ip_old(ENetAddress *address, const char *name) { + if (!inet_pton(AF_INET6, name, &address->host)) { + return -1; + } + + return 0; + } + + int enet_address_set_host_old(ENetAddress *address, const char *name) { + struct addrinfo hints, *resultList = NULL, *result = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + + if (getaddrinfo(name, NULL, &hints, &resultList) != 0) { + return -1; + } + + for (result = resultList; result != NULL; result = result->ai_next) { + if (result->ai_addr != NULL && result->ai_addrlen >= sizeof(struct sockaddr_in)) { + if (result->ai_family == AF_INET) { + struct sockaddr_in * sin = (struct sockaddr_in *) result->ai_addr; + + ((uint32_t *)&address->host.s6_addr)[0] = 0; + ((uint32_t *)&address->host.s6_addr)[1] = 0; + ((uint32_t *)&address->host.s6_addr)[2] = htonl(0xffff); + ((uint32_t *)&address->host.s6_addr)[3] = sin->sin_addr.s_addr; + + freeaddrinfo(resultList); + return 0; + } + else if(result->ai_family == AF_INET6) { + struct sockaddr_in6 * sin = (struct sockaddr_in6 *)result->ai_addr; + + address->host = sin->sin6_addr; + address->sin6_scope_id = sin->sin6_scope_id; + + freeaddrinfo(resultList); + return 0; + } + } + } + freeaddrinfo(resultList); + + return enet_address_set_host_ip(address, name); + } /* enet_address_set_host_old */ + + int enet_address_get_host_ip_old(const ENetAddress *address, char *name, size_t nameLength) { + if (inet_ntop(AF_INET6, &address->host, name, nameLength) == NULL) { + return -1; + } + + return 0; + } + + int enet_address_get_host_old(const ENetAddress *address, char *name, size_t nameLength) { + struct sockaddr_in6 sin; + int err; + memset(&sin, 0, sizeof(struct sockaddr_in6)); + sin.sin6_family = AF_INET6; + sin.sin6_port = ENET_HOST_TO_NET_16 (address->port); + sin.sin6_addr = address->host; + sin.sin6_scope_id = address->sin6_scope_id; + err = getnameinfo((struct sockaddr *) &sin, sizeof(sin), name, nameLength, NULL, 0, NI_NAMEREQD); + if (!err) { + if (name != NULL && nameLength > 0 && !memchr(name, '\0', nameLength)) { + return -1; + } + return 0; + } + if (err != EAI_NONAME) { + return -1; + } + return enet_address_get_host_ip(address, name, nameLength); + } /* enet_address_get_host_old */ + + int enet_socket_bind(ENetSocket socket, const ENetAddress *address) { + struct sockaddr_in6 sin; + memset(&sin, 0, sizeof(struct sockaddr_in6)); + sin.sin6_family = AF_INET6; + + if (address != NULL) { + sin.sin6_port = ENET_HOST_TO_NET_16(address->port); + sin.sin6_addr = address->host; + sin.sin6_scope_id = address->sin6_scope_id; + } else { + sin.sin6_port = 0; + sin.sin6_addr = ENET_HOST_ANY; + sin.sin6_scope_id = 0; + } + + return bind(socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in6)); + } + + int enet_socket_get_address(ENetSocket socket, ENetAddress *address) { + struct sockaddr_in6 sin; + socklen_t sinLength = sizeof(struct sockaddr_in6); + + if (getsockname(socket, (struct sockaddr *) &sin, &sinLength) == -1) { + return -1; + } + + address->host = sin.sin6_addr; + address->port = ENET_NET_TO_HOST_16(sin.sin6_port); + address->sin6_scope_id = sin.sin6_scope_id; + + return 0; + } + + int enet_socket_listen(ENetSocket socket, int backlog) { + return listen(socket, backlog < 0 ? SOMAXCONN : backlog); + } + + ENetSocket enet_socket_create(ENetSocketType type) { + return socket(PF_INET6, (int)type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); + } + + int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) { + int result = -1; + + switch (option) { + case ENET_SOCKOPT_NONBLOCK: + result = fcntl(socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl(socket, F_GETFL) & ~O_NONBLOCK)); + break; + + case ENET_SOCKOPT_BROADCAST: + result = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&value, sizeof(int)); + break; + + case ENET_SOCKOPT_REUSEADDR: + result = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(int)); + break; + + case ENET_SOCKOPT_RCVBUF: + result = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&value, sizeof(int)); + break; + + case ENET_SOCKOPT_SNDBUF: + result = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&value, sizeof(int)); + break; + + case ENET_SOCKOPT_RCVTIMEO: { + struct timeval timeVal; + timeVal.tv_sec = value / 1000; + timeVal.tv_usec = (value % 1000) * 1000; + result = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeVal, sizeof(struct timeval)); + break; + } + + case ENET_SOCKOPT_SNDTIMEO: { + struct timeval timeVal; + timeVal.tv_sec = value / 1000; + timeVal.tv_usec = (value % 1000) * 1000; + result = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeVal, sizeof(struct timeval)); + break; + } + + case ENET_SOCKOPT_NODELAY: + result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&value, sizeof(int)); + break; + + case ENET_SOCKOPT_IPV6_V6ONLY: + result = setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&value, sizeof(int)); + break; + + default: + break; + } + return result == -1 ? -1 : 0; + } /* enet_socket_set_option */ + + int enet_socket_get_option(ENetSocket socket, ENetSocketOption option, int *value) { + int result = -1; + socklen_t len; + + switch (option) { + case ENET_SOCKOPT_ERROR: + len = sizeof(int); + result = getsockopt(socket, SOL_SOCKET, SO_ERROR, value, &len); + break; + + default: + break; + } + return result == -1 ? -1 : 0; + } + + int enet_socket_connect(ENetSocket socket, const ENetAddress *address) { + struct sockaddr_in6 sin; + int result; + + memset(&sin, 0, sizeof(struct sockaddr_in6)); + + sin.sin6_family = AF_INET6; + sin.sin6_port = ENET_HOST_TO_NET_16(address->port); + sin.sin6_addr = address->host; + sin.sin6_scope_id = address->sin6_scope_id; + + result = connect(socket, (struct sockaddr *)&sin, sizeof(struct sockaddr_in6)); + if (result == -1 && errno == EINPROGRESS) { + return 0; + } + + return result; + } + + ENetSocket enet_socket_accept(ENetSocket socket, ENetAddress *address) { + int result; + struct sockaddr_in6 sin; + socklen_t sinLength = sizeof(struct sockaddr_in6); + + result = accept(socket,address != NULL ? (struct sockaddr *) &sin : NULL, address != NULL ? &sinLength : NULL); + + if (result == -1) { + return ENET_SOCKET_NULL; + } + + if (address != NULL) { + address->host = sin.sin6_addr; + address->port = ENET_NET_TO_HOST_16 (sin.sin6_port); + address->sin6_scope_id = sin.sin6_scope_id; + } + + return result; + } + + int enet_socket_shutdown(ENetSocket socket, ENetSocketShutdown how) { + return shutdown(socket, (int) how); + } + + void enet_socket_destroy(ENetSocket socket) { + if (socket != -1) { + close(socket); + } + } + + int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBuffer *buffers, size_t bufferCount) { + struct msghdr msgHdr; + struct sockaddr_in6 sin; + int sentLength; + + memset(&msgHdr, 0, sizeof(struct msghdr)); + + if (address != NULL) { + memset(&sin, 0, sizeof(struct sockaddr_in6)); + + sin.sin6_family = AF_INET6; + sin.sin6_port = ENET_HOST_TO_NET_16(address->port); + sin.sin6_addr = address->host; + sin.sin6_scope_id = address->sin6_scope_id; + + msgHdr.msg_name = &sin; + msgHdr.msg_namelen = sizeof(struct sockaddr_in6); + } + + msgHdr.msg_iov = (struct iovec *) buffers; + msgHdr.msg_iovlen = bufferCount; + + sentLength = sendmsg(socket, &msgHdr, MSG_NOSIGNAL); + + if (sentLength == -1) { + if (errno == EWOULDBLOCK) { + return 0; + } + + return -1; + } + + return sentLength; + } /* enet_socket_send */ + + int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) { + struct msghdr msgHdr; + struct sockaddr_in6 sin; + int recvLength; + + memset(&msgHdr, 0, sizeof(struct msghdr)); + + if (address != NULL) { + msgHdr.msg_name = &sin; + msgHdr.msg_namelen = sizeof(struct sockaddr_in6); + } + + msgHdr.msg_iov = (struct iovec *) buffers; + msgHdr.msg_iovlen = bufferCount; + + recvLength = recvmsg(socket, &msgHdr, MSG_NOSIGNAL); + + if (recvLength == -1) { + if (errno == EWOULDBLOCK) { + return 0; + } + + return -1; + } + + if (msgHdr.msg_flags & MSG_TRUNC) { + return -1; + } + + if (address != NULL) { + address->host = sin.sin6_addr; + address->port = ENET_NET_TO_HOST_16(sin.sin6_port); + address->sin6_scope_id = sin.sin6_scope_id; + } + + return recvLength; + } /* enet_socket_receive */ + + int enet_socketset_select(ENetSocket maxSocket, ENetSocketSet *readSet, ENetSocketSet *writeSet, enet_uint32 timeout) { + struct timeval timeVal; + + timeVal.tv_sec = timeout / 1000; + timeVal.tv_usec = (timeout % 1000) * 1000; + + return select(maxSocket + 1, readSet, writeSet, NULL, &timeVal); + } + + int enet_socket_wait(ENetSocket socket, enet_uint32 *condition, enet_uint64 timeout) { + struct pollfd pollSocket; + int pollCount; + + pollSocket.fd = socket; + pollSocket.events = 0; + + if (*condition & ENET_SOCKET_WAIT_SEND) { + pollSocket.events |= POLLOUT; + } + + if (*condition & ENET_SOCKET_WAIT_RECEIVE) { + pollSocket.events |= POLLIN; + } + + pollCount = poll(&pollSocket, 1, timeout); + + if (pollCount < 0) { + if (errno == EINTR && *condition & ENET_SOCKET_WAIT_INTERRUPT) { + *condition = ENET_SOCKET_WAIT_INTERRUPT; + + return 0; + } + + return -1; + } + + *condition = ENET_SOCKET_WAIT_NONE; + + if (pollCount == 0) { + return 0; + } + + if (pollSocket.revents & POLLOUT) { + *condition |= ENET_SOCKET_WAIT_SEND; + } + + if (pollSocket.revents & POLLIN) { + *condition |= ENET_SOCKET_WAIT_RECEIVE; + } + + return 0; + } /* enet_socket_wait */ + + #endif // !_WIN32 + + +// =======================================================================// +// ! +// ! Platform Specific (Win) +// ! +// =======================================================================// + + #ifdef _WIN32 + + int enet_initialize(void) { + WORD versionRequested = MAKEWORD(1, 1); + WSADATA wsaData; + + if (WSAStartup(versionRequested, &wsaData)) { + return -1; + } + + if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1) { + WSACleanup(); + return -1; + } + + timeBeginPeriod(1); + return 0; + } + + void enet_deinitialize(void) { + timeEndPeriod(1); + WSACleanup(); + } + + enet_uint64 enet_host_random_seed(void) { + return (enet_uint64) timeGetTime(); + } + + int enet_address_set_host_ip_old(ENetAddress *address, const char *name) { + enet_uint8 vals[4] = { 0, 0, 0, 0 }; + int i; + + for (i = 0; i < 4; ++i) { + const char *next = name + 1; + if (*name != '0') { + long val = strtol(name, (char **) &next, 10); + if (val < 0 || val > 255 || next == name || next - name > 3) { + return -1; + } + vals[i] = (enet_uint8) val; + } + + if (*next != (i < 3 ? '.' : '\0')) { + return -1; + } + name = next + 1; + } + + memcpy(&address->host, vals, sizeof(enet_uint32)); + return 0; + } + + int enet_address_set_host_old(ENetAddress *address, const char *name) { + struct hostent *hostEntry = NULL; + hostEntry = gethostbyname(name); + + if (hostEntry == NULL || hostEntry->h_addrtype != AF_INET) { + if (!inet_pton(AF_INET6, name, &address->host)) { + return -1; + } + + return 0; + } + + ((enet_uint32 *)&address->host.s6_addr)[0] = 0; + ((enet_uint32 *)&address->host.s6_addr)[1] = 0; + ((enet_uint32 *)&address->host.s6_addr)[2] = htonl(0xffff); + ((enet_uint32 *)&address->host.s6_addr)[3] = *(enet_uint32 *)hostEntry->h_addr_list[0]; + + return 0; + } + + int enet_address_get_host_ip_old(const ENetAddress *address, char *name, size_t nameLength) { + if (inet_ntop(AF_INET6, (PVOID)&address->host, name, nameLength) == NULL) { + return -1; + } + + return 0; + } + + int enet_address_get_host_old(const ENetAddress *address, char *name, size_t nameLength) { + struct in6_addr in; + struct hostent *hostEntry = NULL; + in = address->host; + hostEntry = gethostbyaddr((char *)&in, sizeof(struct in6_addr), AF_INET6); + if (hostEntry == NULL) { + return enet_address_get_host_ip(address, name, nameLength); + } else { + size_t hostLen = strlen(hostEntry->h_name); + if (hostLen >= nameLength) { + return -1; + } + memcpy(name, hostEntry->h_name, hostLen + 1); + } + return 0; + } + + int enet_socket_bind(ENetSocket socket, const ENetAddress *address) { + struct sockaddr_in6 sin; + memset(&sin, 0, sizeof(struct sockaddr_in6)); + sin.sin6_family = AF_INET6; + + if (address != NULL) { + sin.sin6_port = ENET_HOST_TO_NET_16 (address->port); + sin.sin6_addr = address->host; + sin.sin6_scope_id = address->sin6_scope_id; + } else { + sin.sin6_port = 0; + sin.sin6_addr = in6addr_any; + sin.sin6_scope_id = 0; + } + + return bind(socket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in6)) == SOCKET_ERROR ? -1 : 0; + } + + int enet_socket_get_address(ENetSocket socket, ENetAddress *address) { + struct sockaddr_in6 sin; + int sinLength = sizeof(struct sockaddr_in6); + + if (getsockname(socket, (struct sockaddr *) &sin, &sinLength) == -1) { + return -1; + } + + address->host = sin.sin6_addr; + address->port = ENET_NET_TO_HOST_16(sin.sin6_port); + address->sin6_scope_id = sin.sin6_scope_id; + + return 0; + } + + int enet_socket_listen(ENetSocket socket, int backlog) { + return listen(socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0; + } + + ENetSocket enet_socket_create(ENetSocketType type) { + return socket(PF_INET6, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0); + } + + int enet_socket_set_option(ENetSocket socket, ENetSocketOption option, int value) { + int result = SOCKET_ERROR; + + switch (option) { + case ENET_SOCKOPT_NONBLOCK: { + u_long nonBlocking = (u_long) value; + result = ioctlsocket(socket, FIONBIO, &nonBlocking); + break; + } + + case ENET_SOCKOPT_BROADCAST: + result = setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&value, sizeof(int)); + break; + + case ENET_SOCKOPT_REUSEADDR: + result = setsockopt(socket, SOL_SOCKET, SO_REUSEADDR, (char *)&value, sizeof(int)); + break; + + case ENET_SOCKOPT_RCVBUF: + result = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char *)&value, sizeof(int)); + break; + + case ENET_SOCKOPT_SNDBUF: + result = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, (char *)&value, sizeof(int)); + break; + + case ENET_SOCKOPT_RCVTIMEO: + result = setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&value, sizeof(int)); + break; + + case ENET_SOCKOPT_SNDTIMEO: + result = setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&value, sizeof(int)); + break; + + case ENET_SOCKOPT_NODELAY: + result = setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&value, sizeof(int)); + break; + + case ENET_SOCKOPT_IPV6_V6ONLY: + result = setsockopt(socket, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&value, sizeof(int)); + break; + + default: + break; + } + return result == SOCKET_ERROR ? -1 : 0; + } /* enet_socket_set_option */ + + int enet_socket_get_option(ENetSocket socket, ENetSocketOption option, int *value) { + int result = SOCKET_ERROR, len; + + switch (option) { + case ENET_SOCKOPT_ERROR: + len = sizeof(int); + result = getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)value, &len); + break; + + default: + break; + } + return result == SOCKET_ERROR ? -1 : 0; + } + + int enet_socket_connect(ENetSocket socket, const ENetAddress *address) { + struct sockaddr_in6 sin; + int result; + + memset(&sin, 0, sizeof(struct sockaddr_in6)); + + sin.sin6_family = AF_INET6; + sin.sin6_port = ENET_HOST_TO_NET_16(address->port); + sin.sin6_addr = address->host; + sin.sin6_scope_id = address->sin6_scope_id; + + result = connect(socket, (struct sockaddr *) &sin, sizeof(struct sockaddr_in6)); + if (result == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK) { + return -1; + } + + return 0; + } + + ENetSocket enet_socket_accept(ENetSocket socket, ENetAddress *address) { + SOCKET result; + struct sockaddr_in6 sin; + int sinLength = sizeof(struct sockaddr_in6); + + result = accept(socket, address != NULL ? (struct sockaddr *)&sin : NULL, address != NULL ? &sinLength : NULL); + + if (result == INVALID_SOCKET) { + return ENET_SOCKET_NULL; + } + + if (address != NULL) { + address->host = sin.sin6_addr; + address->port = ENET_NET_TO_HOST_16(sin.sin6_port); + address->sin6_scope_id = sin.sin6_scope_id; + } + + return result; + } + + int enet_socket_shutdown(ENetSocket socket, ENetSocketShutdown how) { + return shutdown(socket, (int) how) == SOCKET_ERROR ? -1 : 0; + } + + void enet_socket_destroy(ENetSocket socket) { + if (socket != INVALID_SOCKET) { + closesocket(socket); + } + } + + int enet_socket_send(ENetSocket socket, const ENetAddress *address, const ENetBuffer *buffers, size_t bufferCount) { + struct sockaddr_in6 sin; + DWORD sentLength; + + if (address != NULL) { + memset(&sin, 0, sizeof(struct sockaddr_in6)); + + sin.sin6_family = AF_INET6; + sin.sin6_port = ENET_HOST_TO_NET_16(address->port); + sin.sin6_addr = address->host; + sin.sin6_scope_id = address->sin6_scope_id; + } + + if (WSASendTo(socket, + (LPWSABUF) buffers, + (DWORD) bufferCount, + &sentLength, + 0, + address != NULL ? (struct sockaddr *) &sin : NULL, + address != NULL ? sizeof(struct sockaddr_in6) : 0, + NULL, + NULL) == SOCKET_ERROR + ) { + return (WSAGetLastError() == WSAEWOULDBLOCK) ? 0 : -1; + } + + return (int) sentLength; + } + + int enet_socket_receive(ENetSocket socket, ENetAddress *address, ENetBuffer *buffers, size_t bufferCount) { + INT sinLength = sizeof(struct sockaddr_in6); + DWORD flags = 0, recvLength; + struct sockaddr_in6 sin; + + if (WSARecvFrom(socket, + (LPWSABUF) buffers, + (DWORD) bufferCount, + &recvLength, + &flags, + address != NULL ? (struct sockaddr *) &sin : NULL, + address != NULL ? &sinLength : NULL, + NULL, + NULL) == SOCKET_ERROR + ) { + switch (WSAGetLastError()) { + case WSAEWOULDBLOCK: + case WSAECONNRESET: + return 0; + } + + return -1; + } + + if (flags & MSG_PARTIAL) { + return -1; + } + + if (address != NULL) { + address->host = sin.sin6_addr; + address->port = ENET_NET_TO_HOST_16(sin.sin6_port); + address->sin6_scope_id = sin.sin6_scope_id; + } + + return (int) recvLength; + } /* enet_socket_receive */ + + int enet_socketset_select(ENetSocket maxSocket, ENetSocketSet *readSet, ENetSocketSet *writeSet, enet_uint32 timeout) { + struct timeval timeVal; + + timeVal.tv_sec = timeout / 1000; + timeVal.tv_usec = (timeout % 1000) * 1000; + + return select(maxSocket + 1, readSet, writeSet, NULL, &timeVal); + } + + int enet_socket_wait(ENetSocket socket, enet_uint32 *condition, enet_uint64 timeout) { + fd_set readSet, writeSet; + struct timeval timeVal; + int selectCount; + + timeVal.tv_sec = timeout / 1000; + timeVal.tv_usec = (timeout % 1000) * 1000; + + FD_ZERO(&readSet); + FD_ZERO(&writeSet); + + if (*condition & ENET_SOCKET_WAIT_SEND) { + FD_SET(socket, &writeSet); + } + + if (*condition & ENET_SOCKET_WAIT_RECEIVE) { + FD_SET(socket, &readSet); + } + + selectCount = select(socket + 1, &readSet, &writeSet, NULL, &timeVal); + + if (selectCount < 0) { + return -1; + } + + *condition = ENET_SOCKET_WAIT_NONE; + + if (selectCount == 0) { + return 0; + } + + if (FD_ISSET(socket, &writeSet)) { + *condition |= ENET_SOCKET_WAIT_SEND; + } + + if (FD_ISSET(socket, &readSet)) { + *condition |= ENET_SOCKET_WAIT_RECEIVE; + } + + return 0; + } /* enet_socket_wait */ + + #endif // _WIN32 + + +#ifdef __cplusplus +} +#endif + +#endif // ENET_IMPLEMENTATION +#endif // ENET_INCLUDE_H diff --git a/src/game.c b/src/game.c new file mode 100644 index 0000000..f8c65e7 --- /dev/null +++ b/src/game.c @@ -0,0 +1,898 @@ +#include"game.h" + +#include"k4.h" +#include +#include"resman.h" +#include + +struct Game Game; + +void game_init() { + static int initode = 0; + if(initode == 0) { + dInitODE(); + initode = 1; + } + + k3Log(k3_INFO, "ODE config: %s", dGetConfiguration()); + + memset(&Game, 0, sizeof(Game)); + Game.spectated = ENT_ID_INVALID; + Game.controlled = ENT_ID_INVALID; + + // Assume singleplayer first + Game.isMultiplayer = 0; + Game.isAuthority = 1; + Game.reconciliate = 1; + + game_cleanup(); +} + +struct CollisionPair { + dGeomID g1; // greater + dGeomID g2; // lesser + uint8_t x; +} __attribute__((packed)); +static size_t activeCollisionCount, activeCollisionCapacity; +static struct CollisionPair *activeCollisions; +int pair_comparator(const void *a_, const void *b_) { + const struct CollisionPair *a = a_; + const struct CollisionPair *b = b_; + if(a->g1 == b->g1) { + return (uintptr_t) a->g2 - (uintptr_t) b->g2; + } else { + return (uintptr_t) a->g1 - (uintptr_t) b->g1; + } +} +static int activate_pair(dGeomID g1, dGeomID g2) { + struct CollisionPair p = { + .g1 = g1 > g2 ? g1 : g2, + .g2 = g1 > g2 ? g2 : g1, + }; + + struct CollisionPair *peepee = bsearch(&p, activeCollisions, activeCollisionCount, sizeof(struct CollisionPair), pair_comparator); + + if(peepee) { + peepee->x++; + return TRIGGER_EV_CONTINUOUS; + } + + if(activeCollisionCount == activeCollisionCapacity) { + activeCollisions = realloc(activeCollisions, sizeof(*activeCollisions) * (activeCollisionCapacity += 32)); + } + + p.x = 2; + + memcpy(&activeCollisions[activeCollisionCount++], &p, sizeof(p)); + + qsort(activeCollisions, activeCollisionCount, sizeof(struct CollisionPair), pair_comparator); + + return TRIGGER_EV_IN; +} +static void tick_pairs() { + for(size_t i = 0; i < activeCollisionCount;) { + if(--activeCollisions[i].x == 0) { + uint16_t e1 = (uintptr_t) dGeomGetData(activeCollisions[i].g1); + uint16_t e2 = (uintptr_t) dGeomGetData(activeCollisions[i].g2); + + if(e1 != ENT_ID_INVALID) { + struct CPhysics *p1 = game_getcomponent(e1, physics); + if(p1 && p1->trigger != TRIGGER_INVALID) { + Game.triggers[p1->trigger - 1](p1->trigger, e1, e2, TRIGGER_EV_OUT); + } + } + + if(e2 != ENT_ID_INVALID) { + struct CPhysics *p2 = game_getcomponent(e2, physics); + if(p2 && p2->trigger != TRIGGER_INVALID) { + Game.triggers[p2->trigger - 1](p2->trigger, e2, e1, TRIGGER_EV_OUT); + } + } + + memmove(&activeCollisions[i], &activeCollisions[i + 1], sizeof(*activeCollisions) * (activeCollisionCount - i - 1)); + activeCollisionCount--; + } else { + i++; + } + } +} + +static void contact_callback(void *data, dGeomID g1, dGeomID g2) { + uint16_t e1 = (uintptr_t) dGeomGetData(g1); + uint16_t e2 = (uintptr_t) dGeomGetData(g2); + + dBodyID b1 = dGeomGetBody(g1); + dBodyID b2 = dGeomGetBody(g2); + + int movingPlatform = 0; + if(b1 && dBodyIsKinematic(b1)) movingPlatform = 1; + else if(b2 && dBodyIsKinematic(b2)) movingPlatform = 2; + + #define MAX_CONTACTS 8 + dContact contact[MAX_CONTACTS]; + memset(contact, 0, sizeof(contact)); + + int numc = dCollide(g1, g2, MAX_CONTACTS, &contact[0].geom, sizeof(dContact)); + + for(int i = 0; i < numc; i++) { + contact[i].surface.mode = dContactRolling; + contact[i].surface.mu = 2; + contact[i].surface.mu2 = 0; + contact[i].surface.bounce = 0.01; + contact[i].surface.bounce_vel = 0.1; + + if(movingPlatform) { + const dReal *platvel = dBodyGetLinearVel(movingPlatform == 1 ? b1 : b2); + + //if(i == 0)printf("get %f %f %f\n", platvel[0], platvel[1], platvel[2]); + + contact[i].surface.mode |= dContactMotion1 | dContactMotion2 | dContactMotionN | dContactFDir1; + contact[i].surface.mode |= dContactSoftERP; + contact[i].surface.soft_erp = 0.9; + + const dReal *normal = contact[i].geom.normal; + dVector3 fdir1, fdir2; + dPlaneSpace(normal, fdir1, fdir2); + + glm_vec3_copy(contact[i].fdir1, fdir1); + + dReal inv = movingPlatform == 1 ? -1 : 1; + + contact[i].surface.motion1 = dDOT(platvel, fdir1); + contact[i].surface.motion2 = inv * dDOT(platvel, fdir2); + contact[i].surface.motionN = -fabs(dDOT(platvel, normal)); //This makes no physical sense but makes objects not bounce on moving platforms going up + } + } + + int ghost = 0; + + if(numc) { + int triggerType = activate_pair(g1, g2); + + if(e1 != ENT_ID_INVALID) { + if(game_getcomponent(e1, physics)->dynamics & CPHYSICS_GHOST) { + ghost = 1; + } + } + + if(e2 != ENT_ID_INVALID) { + if(game_getcomponent(e2, physics)->dynamics & CPHYSICS_GHOST) { + ghost = 1; + } + } + + float friction = 1; + + if(e1 != ENT_ID_INVALID) { + struct CPhysics *c = game_getcomponent(e1, physics); + + friction *= c->friction; + + vec4 q; + if(b1) { + memcpy(q, dBodyGetQuaternion(b1), sizeof(q)); + } else { + dGeomGetQuaternion(c->geom, q); + } + { + float temp = q[0]; + q[0] = q[1]; + q[1] = q[2]; + q[2] = q[3]; + q[3] = temp; + } + + vec3 n = {0, 1, 0}; + glm_quat_rotatev(q, n, n); + + if(!ghost) for(int i = 0; i < numc; i++) { + if(glm_vec3_dot(contact[i].geom.normal, n) >= 0.7) { + struct CMovement *m = game_getcomponent(e1, movement); + if(m) { + if(m->holding != ENT_ID_INVALID && m->holding == e2) { + ghost = 1; + } + + m->canJump = 1; + break; + } + } + } + + if(c->trigger != TRIGGER_INVALID) { + Game.triggers[c->trigger - 1](c->trigger, e1, e2, triggerType); + } + } + + if(e2 != ENT_ID_INVALID) { + struct CPhysics *c = game_getcomponent(e2, physics); + + friction *= c->friction; + + vec4 q; + if(b2) { + memcpy(q, dBodyGetQuaternion(b2), sizeof(q)); + } else { + dGeomGetQuaternion(c->geom, q); + } + { + float temp = q[0]; + q[0] = q[1]; + q[1] = q[2]; + q[2] = q[3]; + q[3] = temp; + } + + vec3 n = {0, -1, 0}; + glm_quat_rotatev(q, n, n); + + if(!ghost) for(int i = 0; i < numc; i++) { + if(glm_vec3_dot(contact[i].geom.normal, n) >= 0.7) { + struct CMovement *m = game_getcomponent(e2, movement); + if(m) { + if(m->holding != ENT_ID_INVALID && m->holding == e1) { + ghost = 1; + } + + m->canJump = 1; + break; + } + } + } + + if(c->trigger != TRIGGER_INVALID) { + Game.triggers[c->trigger - 1](c->trigger, e2, e1, triggerType); + } + } + + for(int i = 0; i < numc; i++) { + contact[i].surface.mu = friction; + } + } + + if(!ghost) for(int i = 0; i < numc; i++) { + dJointID c = dJointCreateContact(Game.phys, Game.contactgroup, contact + i); + dJointAttach(c, dGeomGetBody(g1), dGeomGetBody(g2)); + } +} + +struct RaycastCtx { + struct LocalRay *rays; + size_t count; +}; +static void raycast_handler(void *data, dGeomID g1, dGeomID g2) { + struct RaycastCtx *ctx = data; + + if(dGeomGetClass(g1) != dRayClass && dGeomGetClass(g2) != dRayClass) { + return; + } + + dContact contact[1]; + memset(contact, 0, sizeof(contact)); + + int numc = dCollide(g1, g2, 1, &contact[0].geom, sizeof(dContact)); + + uint16_t e1 = (uintptr_t) dGeomGetData(g1); + uint16_t e2 = (uintptr_t) dGeomGetData(g2); + + if(numc) { + + if(dGeomGetClass(g1) == dRayClass) { + struct LocalRay *r = &ctx->rays[(uintptr_t) dGeomGetData(g1)]; + if(r->ignore != e2 && contact->geom.depth < r->depth) { + struct CPhysics *asdf = game_getcomponent(e2, physics); + if(!asdf || !(asdf->dynamics & CPHYSICS_GHOST)) { + glm_vec3_copy(contact[0].geom.pos, r->out); + r->hit = e2; + r->depth = contact->geom.depth; + } + } + return; + } else if(dGeomGetClass(g2) == dRayClass) { + struct LocalRay *r = &ctx->rays[(uintptr_t) dGeomGetData(g2)]; + if(r->ignore != e1 && contact->geom.depth < r->depth) { + struct CPhysics *asdf = game_getcomponent(e1, physics); + if(!asdf || !(asdf->dynamics & CPHYSICS_GHOST)) { + glm_vec3_copy(contact[0].geom.pos, r->out); + r->hit = e1; + r->depth = contact->geom.depth; + } + } + return; + } + } +} +void game_raycast(struct LocalRay *rays, size_t count) { + dGeomID rayGeoms[count]; + + for(int i = 0; i < count; i++) { + const float len = rays[i].maxlen; + + glm_vec3_copy(rays[i].pos, rays[i].out); + glm_vec3_muladds(rays[i].dir, len, rays[i].out); + + rayGeoms[i] = dCreateRay(Game.space, len); + + dGeomSetData(rayGeoms[i], (void*) (uintptr_t) i); + + dGeomSetCategoryBits(rayGeoms[i], CATEGORY_RAY); + dGeomSetCollideBits(rayGeoms[i], CATEGORY_STATIC | CATEGORY_ENTITY); + + dGeomRaySet(rayGeoms[i], rays[i].pos[0], rays[i].pos[1], rays[i].pos[2], rays[i].dir[0], rays[i].dir[1], rays[i].dir[2]); + + // Broken. We manually find closest hit with contact depths. + //dGeomRaySetClosestHit(rayGeoms[i], 1); + + rays[i].hit = ENT_ID_INVALID; + rays[i].depth = HUGE_VALF; + } + + dSpaceCollide(Game.space, &(struct RaycastCtx) { + .rays = rays, + .count = count, + }, raycast_handler); + + for(int i = 0; i < count; i++) { + dGeomDestroy(rayGeoms[i]); + } +} + +void game_update() { + for(size_t i = 0; i < Game.entities.playerctrlCount; i++) { + struct CPlayerCtrl *cc = &Game.entities.playerctrl[i]; + + struct CMovement *cm = game_getcomponent(cc->entity, movement); + + struct CPhysics *cp = game_getcomponent(cc->entity, physics); + + if(cm && cp) { + vec3 shift = {0, 0, 0}; + + if(cc->keys & (1 << k4_control_get_id_by_name("forward"))) shift[2] -= 1; + if(cc->keys & (1 << k4_control_get_id_by_name("back"))) shift[2] += 1; + if(cc->keys & (1 << k4_control_get_id_by_name("left"))) shift[0] -= 1; + if(cc->keys & (1 << k4_control_get_id_by_name("right"))) shift[0] += 1; + glm_vec3_rotate(shift, cc->yaw, (vec3) {0, 1, 0}); + + if(Game.isAuthority || Game.reconciliate) { + glm_vec3_copy(shift, cm->dir); + } + cm->pointing = cc->yaw; + cm->jump = !!(cc->keys & (1 << k4_control_get_id_by_name("jump"))); + + if(cm->holding == ENT_ID_INVALID && (cc->keys & (1 << k4_control_get_id_by_name("grab")))) { + vec3 d = {0, 0, -1}; + glm_vec3_rotate(d, cc->pitch, (vec3) {1, 0, 0}); + glm_vec3_rotate(d, cc->yaw, (vec3) {0, 1, 0}); + + glm_vec3_copy(dGeomGetPosition(cp->geom), cc->holdray.pos); + glm_vec3_copy(d, cc->holdray.dir); + cc->holdray.ignore = cc->entity; + + cc->holdray.maxlen = 3; + + game_raycast(&cc->holdray, 1); + } else if(!(cc->keys & (1 << k4_control_get_id_by_name("grab")))) { + cm->holding = ENT_ID_INVALID; + } + } + } + + for(size_t i = 0; i < Game.entities.movementCount; i++) { + struct CPhysics *cp = game_getcomponent(Game.entities.movement[i].entity, physics); + if(cp && cp->geom) { + dBodyID bid = dGeomGetBody(cp->geom); + if(Game.entities.movement[i].canJump) { + dBodySetLinearVel(bid, 0, 0, 0); + } + dBodySetGravityMode(bid, !Game.entities.movement[i].canJump); + } + } + + size_t ci = 0, mi = 0; + for(size_t i = 0; i < Game.entities.physicsCount; i++) { + if(Game.entities.physics[i].geom == NULL) { + /* Create */ + + dMass mass; + dMassSetZero(&mass); + + switch(Game.entities.physics[i].type) { + default: + + if(!Game.entities.physics[i].trimesh.cache) { + Game.entities.physics[i].trimesh.cache = resman_ref(RESMAN_PHYSICS, Game.entities.physics[i].trimesh.name); + } + + Game.entities.physics[i].geom = dCreateTriMesh(Game.space, Game.entities.physics[i].trimesh.cache->trid, NULL, NULL, NULL); + + dMassSetTrimesh(&mass, 1, Game.entities.physics[i].geom); + + break; + case CPHYSICS_BOX: + Game.entities.physics[i].geom = dCreateBox(Game.space, + Game.entities.physics[i].box.w, + Game.entities.physics[i].box.h, + Game.entities.physics[i].box.l); + + dMassSetBoxTotal(&mass, Game.entities.physics[i].mass, + Game.entities.physics[i].box.w, + Game.entities.physics[i].box.h, + Game.entities.physics[i].box.l); + + break; + case CPHYSICS_CAPSULE: + Game.entities.physics[i].geom = dCreateCapsule(Game.space, + Game.entities.physics[i].capsule.radius, + Game.entities.physics[i].capsule.length); + + dMassSetCapsuleTotal(&mass, Game.entities.physics[i].mass, 2, Game.entities.physics[i].capsule.radius, Game.entities.physics[i].capsule.length); + + break; + case CPHYSICS_SPHERE: + Game.entities.physics[i].geom = dCreateSphere(Game.space, + Game.entities.physics[i].sphere.radius); + + dMassSetSphereTotal(&mass, Game.entities.physics[i].mass, Game.entities.physics[i].sphere.radius); + + break; + } + + dGeomSetCategoryBits(Game.entities.physics[i].geom, CATEGORY_ENTITY); + dGeomSetCollideBits(Game.entities.physics[i].geom, Game.entities.physics[i].collide); + dGeomSetData(Game.entities.physics[i].geom, (void*) Game.entities.physics[i].entity); + + if((Game.entities.physics[i].dynamics & ~CPHYSICS_GHOST) != CPHYSICS_STATIC) { + dBodyID body = dBodyCreate(Game.phys); + + if((Game.entities.physics[i].dynamics & ~CPHYSICS_GHOST) == CPHYSICS_KINEMATIC) { + dBodySetKinematic(body); + } else { + dBodySetMass(body, &mass); + } + + dGeomSetBody(Game.entities.physics[i].geom, body); + + if(Game.entities.physics[i].type == CPHYSICS_CAPSULE) { + dBodySetMaxAngularSpeed(body, 0); + + // Rotate to Y-up + dQuaternion q; + dQFromAxisAndAngle(q, 1, 0, 0, M_PI * 0.5); + dGeomSetOffsetQuaternion(Game.entities.physics[i].geom, q); + } + } + + dGeomSetPosition(Game.entities.physics[i].geom, + Game.entities.physics[i].start[0], + Game.entities.physics[i].start[1], + Game.entities.physics[i].start[2]); + + dGeomSetQuaternion(Game.entities.physics[i].geom, (dQuaternion) { + Game.entities.physics[i].rot[3], + Game.entities.physics[i].rot[0], + Game.entities.physics[i].rot[1], + Game.entities.physics[i].rot[2] + }); + + if((Game.entities.physics[i].dynamics & ~CPHYSICS_GHOST) == CPHYSICS_DYNAMIC) { + dBodySetLinearVel(dGeomGetBody(Game.entities.physics[i].geom), + Game.entities.physics[i].vel[0], + Game.entities.physics[i].vel[1], + Game.entities.physics[i].vel[2]); + } + } + + dGeomID gid = Game.entities.physics[i].geom; + dBodyID bid = dGeomGetBody(gid); + + // Find corresponding movement component + while(mi < Game.entities.movementCount && Game.entities.movement[mi].entity < Game.entities.physics[i].entity) { + mi++; + } + + if(mi < Game.entities.movementCount && Game.entities.movement[mi].entity == Game.entities.physics[i].entity) { + if(Game.entities.movement[mi].holding != ENT_ID_INVALID) { + struct CPhysics *hp = game_getcomponent(Game.entities.movement[mi].holding, physics); + const float *p = dGeomGetPosition(gid); + dGeomSetPosition(hp->geom, p[0] - sinf(Game.entities.movement[mi].pointing) * 1.4, p[1], p[2] - cosf(Game.entities.movement[mi].pointing) * 1.4); + dBodyID bid = dGeomGetBody(hp->geom); + if(bid) { + dBodySetLinearVel(bid, 0, 0, 0); + } + } + + vec3 wishvel; + glm_vec3_scale(Game.entities.movement[mi].dir, Game.entities.physics[i].speed, wishvel); + +#ifdef RETARDED_MOVEMENT + dBodySetLinearVel(bid, wishvel[0], dBodyGetLinearVel(bid)[1], wishvel[2]); +#else + int inAir = !Game.entities.movement[mi].canJump; + + float factor = (inAir ? 8 : 20) * (GAME_TPS / 25); + + if(inAir) { + if(glm_vec3_norm(wishvel) > 3) { + glm_vec3_scale_as(wishvel, 3, wishvel); + } + } + + float currentspeed = glm_vec3_dot(wishvel, dBodyGetLinearVel(bid)); + float addspeed = glm_vec3_norm(wishvel) - currentspeed; + if(addspeed > 0) { + dMass massiveness; + dBodyGetMass(bid, &massiveness); + + vec3 accel; + glm_vec3_scale_as(wishvel, addspeed, accel); + + vec3 force; + glm_vec3_scale(accel, massiveness.mass * factor, force); + + dBodyAddForce(bid, force[0], force[1], force[2]); + } +#endif + + dQuaternion q; + dQFromAxisAndAngle(q, 0, 1, 0, Game.entities.movement[mi].pointing + M_PI); + dBodySetQuaternion(bid, q); + + if(Game.entities.movement[mi].jump && (0||Game.entities.movement[mi].canJump)) { + Game.entities.movement[mi].canJump = 0; + + dVector3 force; + dWorldImpulseToForce(Game.phys, 1.f / GAME_TPS, 0, 5, 0, force); + + if(bid) { + dBodyAddForce(bid, force[0], force[1], force[2]); + } + } + } + } + + for(size_t i = 0; i < Game.entities.movementCount; i++) { + Game.entities.movement[i].canJump = 0; + } + + dSpaceCollide(Game.space, 0, &contact_callback); + + tick_pairs(); + + dWorldSetQuickStepNumIterations(Game.phys, 60); + dWorldSetQuickStepW(Game.phys, 1); + dWorldQuickStep(Game.phys, 1.0f / GAME_TPS); + + dJointGroupEmpty(Game.contactgroup); + + for(size_t i = 0; i < Game.entities.playerctrlCount; i++) { + struct CPlayerCtrl *cc = &Game.entities.playerctrl[i]; + struct CMovement *cm = game_getcomponent(cc->entity, movement); + + if(cc->holdray.hit != ENT_ID_INVALID && (cc->keys & (1 << k4_control_get_id_by_name("grab"))) && cm->holding == ENT_ID_INVALID) { + dGeomID hd = game_getcomponent(cc->holdray.hit, physics)->geom; + dBodyID hb = dGeomGetBody(hd); + if(hb && !dBodyIsKinematic(hb)) { + cm->holding = cc->holdray.hit; + } + } + } + + for(size_t ci = 0; ci < Game.entities.renderCount; ci++) { + struct CPhysics *cp = game_getcomponent(Game.entities.render[ci].entity, physics); + + if(!Game.entities.render[ci].cache && strlen(Game.entities.render[ci].mdl)) { + struct k3Mdl *srccache = resman_ref(RESMAN_MODEL, Game.entities.render[ci].mdl); + Game.entities.render[ci].cache = k3MdlCopySubs(srccache); + } + + size_t boneCount = Game.entities.render[ci].cache ? k3MdlGetBoneCount(Game.entities.render[ci].cache) : 0; + if(boneCount) { + struct CBoned *cb = game_getcomponent(Game.entities.render[ci].entity, boned); + + if(!cb) { + cb = game_ensurecomponent(Game.entities.render[ci].entity, boned); + } + + if(cb->size < boneCount) { + size_t start; + + if(cb->bones) { + start = cb->size; + + struct k3AnimationBone *nu = _mm_malloc(sizeof(*cb->bones) * boneCount, 16); + memcpy(nu, cb->bones, sizeof(*cb->bones) * cb->size); + struct k3AnimationBone *ol = cb->bones; + cb->bones = nu; + _mm_free(ol); + } else { + start = 0; + + cb->bones = _mm_malloc(sizeof(*cb->bones) * boneCount, 16); + } + + cb->size = boneCount; + + for(size_t asdf = start; asdf < boneCount; asdf++) { + cb->bones[asdf].rotation[3] = cb->bones[asdf].translation[3] = 1; + } + } + + if(cb->anim.id) { + if(!cb->anim.cache.base) { + memset(&cb->anim.cache, 0, sizeof(cb->anim.cache)); + cb->anim.cache.base = k3MdlGetAnim(Game.entities.render[ci].cache, cb->anim.id); + cb->anim.cache.loop = true; + + k3AnimatorSet(&cb->anim.cache, 0); + } else { + float spd = 1.f; + + if(cb->anim.standard && cb->anim.id != 1 && cp && cp->geom) { + dBodyID bid = dGeomGetBody(cp->geom); + if(bid) { + spd = glm_vec3_norm(dBodyGetLinearVel(bid)) * 0.3; + } + } + + k3AnimatorStep(&cb->anim.cache, spd / GAME_TPS); + } + + for(size_t m = 0; m < boneCount; m++) { + vec3 scaleignore; + mat4 rot; + glm_decompose(cb->anim.cache.inter[m], cb->bones[m].translation, rot, scaleignore); + glm_mat4_quat(cb->anim.cache.inter[m], cb->bones[m].rotation); + } + } + } + + dGeomID gid = cp->geom; + + if(!gid) continue; + + dBodyID bid = dGeomGetBody(gid); + + if(bid) { + const float *q = dBodyGetQuaternion(bid); + + Game.entities.render[ci].rot[0] = q[1]; + Game.entities.render[ci].rot[1] = q[2]; + Game.entities.render[ci].rot[2] = q[3]; + Game.entities.render[ci].rot[3] = q[0]; + } else { + dQuaternion q; + dGeomGetQuaternion(gid, q); + + Game.entities.render[ci].rot[0] = q[1]; + Game.entities.render[ci].rot[1] = q[2]; + Game.entities.render[ci].rot[2] = q[3]; + Game.entities.render[ci].rot[3] = q[0]; + } + + const float *src = bid ? dBodyGetPosition(bid) : dGeomGetPosition(gid); + Game.entities.render[ci].pos[0] = src[0]; + Game.entities.render[ci].pos[1] = src[1]; + Game.entities.render[ci].pos[2] = src[2]; + Game.entities.render[ci].pos[3] = 1; + } + + for(size_t cm = 0; cm < Game.entities.movementCount; cm++) { + struct CBoned *cb = game_getcomponent(Game.entities.movement[cm].entity, boned); + if(cb && cb->anim.standard) { + struct CPhysics *cp = game_getcomponent(Game.entities.movement[cm].entity, physics); + if(cp && cp->geom) { + dBodyID bid = dGeomGetBody(cp->geom); + if(bid) { + uint16_t newID = glm_vec3_norm(dBodyGetLinearVel(bid)) > 1 ? 2 : 1; + + if(cb->anim.id != newID) { + cb->anim.id = newID; + cb->anim.cache.base = NULL; + } + } + } + } + } + + for(size_t i = 0; i < Game.conveyorCount; i++) { + struct Conveyor *conveyor = Game.conveyors[i]; + + struct CPhysics *cp = conveyor->entity == ENT_ID_INVALID ? NULL : game_getcomponent(conveyor->entity, physics); + + dGeomID gid = cp ? cp->geom : NULL; + + conveyor->effectivelyActiveLast = conveyor->effectivelyActive; + + if(conveyor->type == CONVEYOR_TYPE_LOOP) { + if(!conveyor->active) { + conveyor->effectivelyActive = 0; + continue; + } + + conveyor->effectivelyActive = 1; + + // Teleport to first point + if(conveyor->position >= conveyor->pointCount - 1) { + conveyor->position -= conveyor->pointCount - 1; + } + + size_t currentPoint = floorf(conveyor->position); + size_t nextPoint = currentPoint + 1; + float alpha = fmodf(conveyor->position, 1.f); + + if(gid) { + vec3 lerped; + glm_vec3_lerp(conveyor->points[currentPoint], conveyor->points[nextPoint], alpha, lerped); + dGeomSetPosition(gid, lerped[0], lerped[1], lerped[2]); + + dBodyID bid = dGeomGetBody(gid); + if(bid) { + vec3 dif; + glm_vec3_sub(conveyor->points[nextPoint], conveyor->points[currentPoint], dif); + glm_vec3_scale_as(dif, conveyor->speed, dif); + dBodySetLinearVel(bid, dif[0], dif[1], dif[2]); // doesn't affect movement, but necessary for proper collision response + } + } + + conveyor->position += conveyor->speed / glm_vec3_distance(conveyor->points[currentPoint], conveyor->points[nextPoint]) / GAME_TPS; + } else if(conveyor->type == CONVEYOR_TYPE_BINARY) { + int stopped = 0; + + if(conveyor->active > 0 && conveyor->position >= conveyor->pointCount - 1) { + conveyor->position = conveyor->pointCount - 1; + stopped = 1; + } else if(conveyor->active <= 0 && conveyor->position <= 0) { + conveyor->position = 0; + stopped = 1; + } + + conveyor->effectivelyActive = !stopped; + + size_t currentPoint, nextPoint; + if(!stopped) { + currentPoint = (size_t) floorf(conveyor->position) % conveyor->pointCount; + nextPoint = (currentPoint + 1) % conveyor->pointCount; + float alpha = fmodf(conveyor->position, 1.f); + + if(gid) { + vec3 lerped; + glm_vec3_lerp(conveyor->points[currentPoint], conveyor->points[nextPoint], alpha, lerped); + dGeomSetPosition(gid, lerped[0], lerped[1], lerped[2]); + } + + float offset = conveyor->speed / glm_vec3_distance(conveyor->points[currentPoint], conveyor->points[nextPoint]) / GAME_TPS; + + if(conveyor->active > 0) { + conveyor->position += offset; + } else { + conveyor->position -= offset; + } + } + + if(gid) { + dBodyID bid = dGeomGetBody(gid); + if(bid) { + if(stopped) { + dBodySetLinearVel(bid, 0, 0, 0); + } else { + vec3 dif; + glm_vec3_sub(conveyor->points[nextPoint], conveyor->points[currentPoint], dif); + glm_vec3_scale_as(dif, conveyor->speed * (conveyor->active <= 0 ? -1 : 1), dif); + //printf("set %f %f %f\n", dif[0], dif[1], dif[2]); + dBodySetLinearVel(bid, dif[0], dif[1], dif[2]); // doesn't affect movement, but necessary for proper collision response + } + } + } + } + + if(conveyor->trigger != TRIGGER_INVALID) { + if(conveyor->effectivelyActive && !conveyor->effectivelyActiveLast) { + Game.triggers[conveyor->trigger - 1](conveyor->trigger, ENT_ID_INVALID, ENT_ID_INVALID, 0); + } else if(conveyor->effectivelyActive && conveyor->effectivelyActiveLast) { + Game.triggers[conveyor->trigger - 1](conveyor->trigger, ENT_ID_INVALID, ENT_ID_INVALID, 1); + } else if(!conveyor->effectivelyActive && conveyor->effectivelyActiveLast) { + Game.triggers[conveyor->trigger - 1](conveyor->trigger, ENT_ID_INVALID, ENT_ID_INVALID, 2); + } + } + } + + Game.frame++; +} + +void game_setphys(struct TrimeshData *phys) { + if(Game.statikRes) { + resman_unref_ptr(RESMAN_PHYSICS, Game.statikRes); + } + if(Game.statik) { + dGeomDestroy(Game.statik); + } + + Game.statikRes = phys; + Game.statik = dCreateTriMesh(Game.space, phys->trid, NULL, NULL, NULL); + + dGeomSetCategoryBits(Game.statik, CATEGORY_STATIC); + dGeomSetCollideBits(Game.statik, 0); + + dGeomSetData(Game.statik, (void*) ENT_ID_INVALID); +} + +void game_synccphysics() { + for(size_t i = 0; i < Game.entities.physicsCount; i++) { + if(Game.entities.physics[i].geom) { + glm_vec3_copy(dGeomGetPosition(Game.entities.physics[i].geom), Game.entities.physics[i].start); + } + } +} + +void game_cleanup() { + // XXX: Go over ALL component types! + + memset(Game.entities.freeIDs, 0, sizeof(Game.entities.freeIDs)); + + for(size_t i = 0; i < Game.entities.physicsCount; i++) { + if(Game.entities.physics[i].type == CPHYSICS_TRIMESH) { + resman_unref_ptr(RESMAN_PHYSICS, Game.entities.physics[i].trimesh.cache); + } + dGeomID gid = Game.entities.physics[i].geom; + if(gid) { + dBodyID bid = dGeomGetBody(gid); + if(bid) { + dBodyDestroy(bid); + } + dGeomDestroy(gid); + } + } + Game.entities.physicsCount = 0; + + for(size_t i = 0; i < Game.entities.renderCount; i++) { + if(Game.entities.render[i].cache) { + resman_unref(RESMAN_MODEL, Game.entities.render[i].mdl); + } + } + Game.entities.renderCount = 0; + + for(size_t i = 0; i < Game.entities.bonedCount; i++) { + free(Game.entities.boned[i].bones); + } + Game.entities.bonedCount = 0; + + Game.entities.movementCount = 0; + Game.entities.playerctrlCount = 0; + + Game.entityCount = 0; + + for(size_t i = 0; i < Game.conveyorCount; i++) { + free(Game.conveyors[i]->points); + free(Game.conveyors[i]); + } + free(Game.conveyors); + Game.conveyors = NULL; + Game.conveyorCount = 0; + + free(Game.triggers); + Game.triggers = NULL; + Game.triggerCount = 0; + + Game.spectated = ENT_ID_INVALID; + Game.controlled = ENT_ID_INVALID; + + free(activeCollisions); + activeCollisions = NULL; + activeCollisionCount = 0; + activeCollisionCapacity = 0; + + if(Game.phys) { + dWorldDestroy(Game.phys); + } + + Game.phys = dWorldCreate(); + dWorldSetGravity(Game.phys, 0, -15, 0); + + dWorldSetCFM(Game.phys, 0.0001); + dWorldSetERP(Game.phys, 0.5); + + Game.space = dHashSpaceCreate(NULL); + + Game.contactgroup = dJointGroupCreate(0); +} diff --git a/src/game.h b/src/game.h new file mode 100644 index 0000000..409565c --- /dev/null +++ b/src/game.h @@ -0,0 +1,254 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include"k3.h" + +#define GAME_TPS 50 + +#define CATEGORY_STATIC 1 +#define CATEGORY_RAY 2 +#define CATEGORY_ENTITY 4 + +#define TRIGGER_INVALID 0 + +#define MODELNAME_LENGTH 12 + +struct CRender { + uint16_t entity; + char mdl[MODELNAME_LENGTH]; + + struct k3Mdl *cache; + + vec4 pos; + versor rot; + + vec4 posLast; + versor rotLast; +}; + +struct TrimeshData { + void *vdata; + void *idata; + dTriMeshDataID trid; +}; + +#define CPHYSICS_TRIMESH 0 +#define CPHYSICS_CAPSULE 1 +#define CPHYSICS_BOX 2 +#define CPHYSICS_SPHERE 3 +#define CPHYSICS_STATIC 0 +#define CPHYSICS_KINEMATIC 1 +#define CPHYSICS_DYNAMIC 2 +#define CPHYSICS_GHOST 128 +struct CPhysics { + uint16_t entity; + dGeomID geom; + uint16_t trigger; + + uint8_t type; + uint8_t dynamics; + union { + struct { + char name[MODELNAME_LENGTH]; + struct TrimeshData *cache; + } trimesh; + struct { + float length; + float radius; + } capsule; + struct { + float w; + float h; + float l; + } box; + struct { + float radius; + } sphere; + }; + + vec3 start; + vec3 vel; + vec4 rot; + + float speed; + + float mass; + float friction; + + uint32_t collide; +}; + +struct CMovement { + uint16_t entity; + vec3 dir; + float pointing; + char jump, canJump; + uint16_t holding; +}; + +struct LocalRay { + vec3 pos; + vec3 dir; + uint16_t ignore; + + vec3 out; + uint16_t hit; + float depth; + + float maxlen; +}; + +struct CPlayerCtrl { + uint16_t entity; + float yaw; + float pitch; + uint32_t keys; + + struct LocalRay holdray; +}; + +struct CBoned { + uint16_t entity; + + size_t size; + struct k3AnimationBone *bones; + + struct { + uint16_t id; + struct k3Animator cache; + bool standard; + } anim; +}; + +#define CONVEYOR_TYPE_LOOP 0 +#define CONVEYOR_TYPE_BINARY 1 +struct Conveyor { + uint16_t entity; + int16_t active; + uint8_t type; + float speed; + float position; + size_t pointCount; + vec3 *points; + + uint16_t trigger; + + uint8_t effectivelyActive; + uint8_t effectivelyActiveLast; +}; + +#define TRIGGER_EV_IN 0 +#define TRIGGER_EV_CONTINUOUS 1 +#define TRIGGER_EV_OUT 2 +typedef int(*TriggerFunc)(size_t id, uint16_t ethis, uint16_t ethat, uint8_t event); + +#define MAX_ENTS 128 +extern struct Game { + size_t entityCount; + struct { + struct CRender render[MAX_ENTS]; + size_t renderCount; + + struct CPhysics physics[MAX_ENTS]; + size_t physicsCount; + + struct CMovement movement[MAX_ENTS]; + size_t movementCount; + + struct CPlayerCtrl playerctrl[MAX_ENTS]; + size_t playerctrlCount; + + struct CBoned boned[MAX_ENTS]; + size_t bonedCount; + + uint64_t freeIDs[(MAX_ENTS + 63) / 64]; + } entities; + + int isMultiplayer; + int isAuthority; + int reconciliate; + + size_t frame; + +#define MAX_CONVEYORS 4096 + size_t conveyorCount; + struct Conveyor **conveyors; + +#define MAX_TRIGGERS 4096 + size_t triggerCount; + TriggerFunc *triggers; + + dWorldID phys; + dSpaceID space; + dJointGroupID contactgroup; + + struct TrimeshData *statikRes; + dGeomID statik; + + uint16_t spectated; + uint16_t controlled; +} Game; + +void game_init(); + +void game_raycast(struct LocalRay *rays, size_t count); +void game_update(); + +void game_setphys(struct TrimeshData*); + +#define ENT_ID_INVALID 65535 +static inline size_t game_nextid() { + for(size_t i = 0; i < (MAX_ENTS + 63) / 64; i++) { + for(uint8_t b = 0; b < 64; b++) { + if((Game.entities.freeIDs[i] & (1ULL << b)) == 0) { + return i * 8 + b; + } + } + } + return ENT_ID_INVALID; +} + +static inline void game_claimentid(size_t i) { + Game.entities.freeIDs[i / 64] |= 1 << (i % 64); +} + +static inline int game_componentcomparator(const void *a, const void *b) { + return *(const uint16_t*) a - *(const uint16_t*) b; +} + +#define game_addcomponent(a, c) game_addcomponent_((uint8_t*) (Game.entities.a), (uint8_t*) (c), sizeof(*(Game.entities.a)), &(Game.entities.a##Count)) +static inline void game_addcomponent_(uint8_t *array, uint8_t *component, size_t componentSize, size_t *componentCount) { + memcpy(&array[*componentCount * componentSize], component, componentSize); + + (*componentCount)++; + + qsort(array, *componentCount, componentSize, game_componentcomparator); +} + +#define game_getcomponent(eid, arr) ((typeof(&Game.entities.arr[0]))game_getcomponent_((eid), (Game.entities.arr), sizeof(*(Game.entities.arr)), (Game.entities.arr##Count))) +static inline void *game_getcomponent_(uint16_t eid, void *array, size_t componentSize, size_t componentCount) { + return bsearch(&eid, array, componentCount, componentSize, game_componentcomparator); +} + +#define game_ensurecomponent(eid, arr) ((typeof(&Game.entities.arr[0]))game_ensurecomponent_((eid), (Game.entities.arr), sizeof(*(Game.entities.arr)), &(Game.entities.arr##Count))) +static inline void *game_ensurecomponent_(uint16_t eid, void *array, size_t componentSize, size_t *componentCount) { + void *ptr = game_getcomponent_(eid, array, componentSize, *componentCount); + if(!ptr) { + void *data = alloca(componentSize); + memset(data, 0, componentSize); + *(uint16_t*) data = eid; + game_addcomponent_(array, data, componentSize, componentCount); + ptr = game_getcomponent_(eid, array, componentSize, *componentCount); + } + return ptr; +} + +// An artifact of using a third-party physics engine +void game_synccphysics(); + +void game_cleanup(); diff --git a/src/gl.h b/src/gl.h new file mode 100644 index 0000000..8adf6b0 --- /dev/null +++ b/src/gl.h @@ -0,0 +1,10961 @@ +/** + * Loader generated by glad 2.0.8 on Sun Nov 17 08:36:10 2024 + * + * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 + * + * Generator: C/C++ + * Specification: gl + * Extensions: 31 + * + * APIs: + * - gl:compatibility=4.6 + * + * Options: + * - ALIAS = False + * - DEBUG = False + * - HEADER_ONLY = True + * - LOADER = False + * - MX = False + * - ON_DEMAND = False + * + * Commandline: + * --api='gl:compatibility=4.6' --extensions='GL_ARB_compatibility,GL_ARB_debug_output,GL_ARB_fragment_program,GL_ARB_fragment_shader,GL_ARB_framebuffer_sRGB,GL_ARB_shader_image_load_store,GL_ARB_shader_image_size,GL_ARB_shader_objects,GL_ARB_shader_storage_buffer_object,GL_ARB_shading_language_100,GL_ARB_texture_float,GL_ARB_texture_rg,GL_ARB_texture_rgb10_a2ui,GL_ARB_vertex_buffer_object,GL_ARB_vertex_program,GL_ARB_vertex_shader,GL_ARB_vertex_type_2_10_10_10_rev,GL_EXT_direct_state_access,GL_EXT_framebuffer_blit,GL_EXT_framebuffer_object,GL_EXT_framebuffer_sRGB,GL_EXT_geometry_shader4,GL_EXT_gpu_shader4,GL_EXT_shader_image_load_store,GL_EXT_texture_array,GL_EXT_texture_compression_s3tc,GL_EXT_texture_integer,GL_EXT_texture_sRGB,GL_EXT_transform_feedback,GL_INTEL_conservative_rasterization,GL_NV_conservative_raster' c --header-only + * + * Online: + * http://glad.sh/#api=gl%3Acompatibility%3D4.6&extensions=GL_ARB_compatibility%2CGL_ARB_debug_output%2CGL_ARB_fragment_program%2CGL_ARB_fragment_shader%2CGL_ARB_framebuffer_sRGB%2CGL_ARB_shader_image_load_store%2CGL_ARB_shader_image_size%2CGL_ARB_shader_objects%2CGL_ARB_shader_storage_buffer_object%2CGL_ARB_shading_language_100%2CGL_ARB_texture_float%2CGL_ARB_texture_rg%2CGL_ARB_texture_rgb10_a2ui%2CGL_ARB_vertex_buffer_object%2CGL_ARB_vertex_program%2CGL_ARB_vertex_shader%2CGL_ARB_vertex_type_2_10_10_10_rev%2CGL_EXT_direct_state_access%2CGL_EXT_framebuffer_blit%2CGL_EXT_framebuffer_object%2CGL_EXT_framebuffer_sRGB%2CGL_EXT_geometry_shader4%2CGL_EXT_gpu_shader4%2CGL_EXT_shader_image_load_store%2CGL_EXT_texture_array%2CGL_EXT_texture_compression_s3tc%2CGL_EXT_texture_integer%2CGL_EXT_texture_sRGB%2CGL_EXT_transform_feedback%2CGL_INTEL_conservative_rasterization%2CGL_NV_conservative_raster&generator=c&options=HEADER_ONLY + * + */ + +#ifndef GLAD_GL_H_ +#define GLAD_GL_H_ + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#endif +#ifdef __gl_h_ + #error OpenGL (gl.h) header already included (API: gl), remove previous include! +#endif +#define __gl_h_ 1 +#ifdef __gl3_h_ + #error OpenGL (gl3.h) header already included (API: gl), remove previous include! +#endif +#define __gl3_h_ 1 +#ifdef __glext_h_ + #error OpenGL (glext.h) header already included (API: gl), remove previous include! +#endif +#define __glext_h_ 1 +#ifdef __gl3ext_h_ + #error OpenGL (gl3ext.h) header already included (API: gl), remove previous include! +#endif +#define __gl3ext_h_ 1 +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#define GLAD_GL +#define GLAD_OPTION_GL_HEADER_ONLY + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef GLAD_PLATFORM_H_ +#define GLAD_PLATFORM_H_ + +#ifndef GLAD_PLATFORM_WIN32 + #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__) + #define GLAD_PLATFORM_WIN32 1 + #else + #define GLAD_PLATFORM_WIN32 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_APPLE + #ifdef __APPLE__ + #define GLAD_PLATFORM_APPLE 1 + #else + #define GLAD_PLATFORM_APPLE 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_EMSCRIPTEN + #ifdef __EMSCRIPTEN__ + #define GLAD_PLATFORM_EMSCRIPTEN 1 + #else + #define GLAD_PLATFORM_EMSCRIPTEN 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_UWP + #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY) + #ifdef __has_include + #if __has_include() + #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1 + #endif + #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_ + #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1 + #endif + #endif + + #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY + #include + #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) + #define GLAD_PLATFORM_UWP 1 + #endif + #endif + + #ifndef GLAD_PLATFORM_UWP + #define GLAD_PLATFORM_UWP 0 + #endif +#endif + +#ifdef __GNUC__ + #define GLAD_GNUC_EXTENSION __extension__ +#else + #define GLAD_GNUC_EXTENSION +#endif + +#define GLAD_UNUSED(x) (void)(x) + +#ifndef GLAD_API_CALL + #if defined(GLAD_API_CALL_EXPORT) + #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__) + #if defined(GLAD_API_CALL_EXPORT_BUILD) + #if defined(__GNUC__) + #define GLAD_API_CALL __attribute__ ((dllexport)) extern + #else + #define GLAD_API_CALL __declspec(dllexport) extern + #endif + #else + #if defined(__GNUC__) + #define GLAD_API_CALL __attribute__ ((dllimport)) extern + #else + #define GLAD_API_CALL __declspec(dllimport) extern + #endif + #endif + #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD) + #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern + #else + #define GLAD_API_CALL extern + #endif + #else + #define GLAD_API_CALL extern + #endif +#endif + +#ifdef APIENTRY + #define GLAD_API_PTR APIENTRY +#elif GLAD_PLATFORM_WIN32 + #define GLAD_API_PTR __stdcall +#else + #define GLAD_API_PTR +#endif + +#ifndef GLAPI +#define GLAPI GLAD_API_CALL +#endif + +#ifndef GLAPIENTRY +#define GLAPIENTRY GLAD_API_PTR +#endif + +#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor) +#define GLAD_VERSION_MAJOR(version) (version / 10000) +#define GLAD_VERSION_MINOR(version) (version % 10000) + +#define GLAD_GENERATOR_VERSION "2.0.8" + +typedef void (*GLADapiproc)(void); + +typedef GLADapiproc (*GLADloadfunc)(const char *name); +typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name); + +typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...); +typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...); + +#endif /* GLAD_PLATFORM_H_ */ + +#define GL_2D 0x0600 +#define GL_2_BYTES 0x1407 +#define GL_3D 0x0601 +#define GL_3D_COLOR 0x0602 +#define GL_3D_COLOR_TEXTURE 0x0603 +#define GL_3_BYTES 0x1408 +#define GL_4D_COLOR_TEXTURE 0x0604 +#define GL_4_BYTES 0x1409 +#define GL_ACCUM 0x0100 +#define GL_ACCUM_ALPHA_BITS 0x0D5B +#define GL_ACCUM_BLUE_BITS 0x0D5A +#define GL_ACCUM_BUFFER_BIT 0x00000200 +#define GL_ACCUM_CLEAR_VALUE 0x0B80 +#define GL_ACCUM_GREEN_BITS 0x0D59 +#define GL_ACCUM_RED_BITS 0x0D58 +#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_ACTIVE_PROGRAM 0x8259 +#define GL_ACTIVE_RESOURCES 0x92F5 +#define GL_ACTIVE_SUBROUTINES 0x8DE5 +#define GL_ACTIVE_SUBROUTINE_MAX_LENGTH 0x8E48 +#define GL_ACTIVE_SUBROUTINE_UNIFORMS 0x8DE6 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_LOCATIONS 0x8E47 +#define GL_ACTIVE_SUBROUTINE_UNIFORM_MAX_LENGTH 0x8E49 +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_VARIABLES 0x9305 +#define GL_ADD 0x0104 +#define GL_ADD_SIGNED 0x8574 +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALL_ATTRIB_BITS 0xFFFFFFFF +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF +#define GL_ALL_BARRIER_BITS_EXT 0xFFFFFFFF +#define GL_ALL_SHADER_BITS 0xFFFFFFFF +#define GL_ALPHA 0x1906 +#define GL_ALPHA12 0x803D +#define GL_ALPHA16 0x803E +#define GL_ALPHA16F_ARB 0x881C +#define GL_ALPHA16I_EXT 0x8D8A +#define GL_ALPHA16UI_EXT 0x8D78 +#define GL_ALPHA32F_ARB 0x8816 +#define GL_ALPHA32I_EXT 0x8D84 +#define GL_ALPHA32UI_EXT 0x8D72 +#define GL_ALPHA4 0x803B +#define GL_ALPHA8 0x803C +#define GL_ALPHA8I_EXT 0x8D90 +#define GL_ALPHA8UI_EXT 0x8D7E +#define GL_ALPHA_BIAS 0x0D1D +#define GL_ALPHA_BITS 0x0D55 +#define GL_ALPHA_INTEGER 0x8D97 +#define GL_ALPHA_INTEGER_EXT 0x8D97 +#define GL_ALPHA_SCALE 0x0D1C +#define GL_ALPHA_TEST 0x0BC0 +#define GL_ALPHA_TEST_FUNC 0x0BC1 +#define GL_ALPHA_TEST_REF 0x0BC2 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_ALWAYS 0x0207 +#define GL_AMBIENT 0x1200 +#define GL_AMBIENT_AND_DIFFUSE 0x1602 +#define GL_AND 0x1501 +#define GL_AND_INVERTED 0x1504 +#define GL_AND_REVERSE 0x1502 +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ARRAY_BUFFER_ARB 0x8892 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 +#define GL_ARRAY_SIZE 0x92FB +#define GL_ARRAY_STRIDE 0x92FE +#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000 +#define GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000 +#define GL_ATOMIC_COUNTER_BUFFER 0x92C0 +#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5 +#define GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6 +#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1 +#define GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4 +#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9 +#define GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7 +#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3 +#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ATTRIB_STACK_DEPTH 0x0BB0 +#define GL_AUTO_GENERATE_MIPMAP 0x8295 +#define GL_AUTO_NORMAL 0x0D80 +#define GL_AUX0 0x0409 +#define GL_AUX1 0x040A +#define GL_AUX2 0x040B +#define GL_AUX3 0x040C +#define GL_AUX_BUFFERS 0x0C00 +#define GL_BACK 0x0405 +#define GL_BACK_LEFT 0x0402 +#define GL_BACK_RIGHT 0x0403 +#define GL_BGR 0x80E0 +#define GL_BGRA 0x80E1 +#define GL_BGRA_INTEGER 0x8D9B +#define GL_BGRA_INTEGER_EXT 0x8D9B +#define GL_BGR_INTEGER 0x8D9A +#define GL_BGR_INTEGER_EXT 0x8D9A +#define GL_BITMAP 0x1A00 +#define GL_BITMAP_TOKEN 0x0704 +#define GL_BLEND 0x0BE2 +#define GL_BLEND_COLOR 0x8005 +#define GL_BLEND_DST 0x0BE0 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_SRC 0x0BE1 +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLOCK_INDEX 0x92FD +#define GL_BLUE 0x1905 +#define GL_BLUE_BIAS 0x0D1B +#define GL_BLUE_BITS 0x0D54 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_BLUE_INTEGER_EXT 0x8D96 +#define GL_BLUE_SCALE 0x0D1A +#define GL_BOOL 0x8B56 +#define GL_BOOL_ARB 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC2_ARB 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC3_ARB 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_BOOL_VEC4_ARB 0x8B59 +#define GL_BUFFER 0x82E0 +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_ACCESS_ARB 0x88BB +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_BINDING 0x9302 +#define GL_BUFFER_DATA_SIZE 0x9303 +#define GL_BUFFER_IMMUTABLE_STORAGE 0x821F +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAPPED_ARB 0x88BC +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_BUFFER_MAP_POINTER_ARB 0x88BD +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_SIZE_ARB 0x8764 +#define GL_BUFFER_STORAGE_FLAGS 0x8220 +#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200 +#define GL_BUFFER_UPDATE_BARRIER_BIT_EXT 0x00000200 +#define GL_BUFFER_USAGE 0x8765 +#define GL_BUFFER_USAGE_ARB 0x8765 +#define GL_BUFFER_VARIABLE 0x92E5 +#define GL_BYTE 0x1400 +#define GL_C3F_V3F 0x2A24 +#define GL_C4F_N3F_V3F 0x2A26 +#define GL_C4UB_V2F 0x2A22 +#define GL_C4UB_V3F 0x2A23 +#define GL_CAVEAT_SUPPORT 0x82B8 +#define GL_CCW 0x0901 +#define GL_CLAMP 0x2900 +#define GL_CLAMP_FRAGMENT_COLOR 0x891B +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_CLAMP_VERTEX_COLOR 0x891A +#define GL_CLEAR 0x1500 +#define GL_CLEAR_BUFFER 0x82B4 +#define GL_CLEAR_TEXTURE 0x9365 +#define GL_CLIENT_ACTIVE_TEXTURE 0x84E1 +#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF +#define GL_CLIENT_ATTRIB_STACK_DEPTH 0x0BB1 +#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT 0x00004000 +#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001 +#define GL_CLIENT_STORAGE_BIT 0x0200 +#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002 +#define GL_CLIPPING_INPUT_PRIMITIVES 0x82F6 +#define GL_CLIPPING_OUTPUT_PRIMITIVES 0x82F7 +#define GL_CLIP_DEPTH_MODE 0x935D +#define GL_CLIP_DISTANCE0 0x3000 +#define GL_CLIP_DISTANCE1 0x3001 +#define GL_CLIP_DISTANCE2 0x3002 +#define GL_CLIP_DISTANCE3 0x3003 +#define GL_CLIP_DISTANCE4 0x3004 +#define GL_CLIP_DISTANCE5 0x3005 +#define GL_CLIP_DISTANCE6 0x3006 +#define GL_CLIP_DISTANCE7 0x3007 +#define GL_CLIP_ORIGIN 0x935C +#define GL_CLIP_PLANE0 0x3000 +#define GL_CLIP_PLANE1 0x3001 +#define GL_CLIP_PLANE2 0x3002 +#define GL_CLIP_PLANE3 0x3003 +#define GL_CLIP_PLANE4 0x3004 +#define GL_CLIP_PLANE5 0x3005 +#define GL_COEFF 0x0A00 +#define GL_COLOR 0x1800 +#define GL_COLOR_ARRAY 0x8076 +#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898 +#define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 +#define GL_COLOR_ARRAY_POINTER 0x8090 +#define GL_COLOR_ARRAY_SIZE 0x8081 +#define GL_COLOR_ARRAY_STRIDE 0x8083 +#define GL_COLOR_ARRAY_TYPE 0x8082 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT13_EXT 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT20 0x8CF4 +#define GL_COLOR_ATTACHMENT21 0x8CF5 +#define GL_COLOR_ATTACHMENT22 0x8CF6 +#define GL_COLOR_ATTACHMENT23 0x8CF7 +#define GL_COLOR_ATTACHMENT24 0x8CF8 +#define GL_COLOR_ATTACHMENT25 0x8CF9 +#define GL_COLOR_ATTACHMENT26 0x8CFA +#define GL_COLOR_ATTACHMENT27 0x8CFB +#define GL_COLOR_ATTACHMENT28 0x8CFC +#define GL_COLOR_ATTACHMENT29 0x8CFD +#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF +#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_COMPONENTS 0x8283 +#define GL_COLOR_ENCODING 0x8296 +#define GL_COLOR_INDEX 0x1900 +#define GL_COLOR_INDEXES 0x1603 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_COLOR_MATERIAL 0x0B57 +#define GL_COLOR_MATERIAL_FACE 0x0B55 +#define GL_COLOR_MATERIAL_PARAMETER 0x0B56 +#define GL_COLOR_RENDERABLE 0x8286 +#define GL_COLOR_SUM 0x8458 +#define GL_COLOR_SUM_ARB 0x8458 +#define GL_COLOR_TABLE 0x80D0 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_COMBINE 0x8570 +#define GL_COMBINE_ALPHA 0x8572 +#define GL_COMBINE_RGB 0x8571 +#define GL_COMMAND_BARRIER_BIT 0x00000040 +#define GL_COMMAND_BARRIER_BIT_EXT 0x00000040 +#define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_COMPARE_R_TO_TEXTURE 0x884E +#define GL_COMPATIBLE_SUBROUTINES 0x8E4B +#define GL_COMPILE 0x1300 +#define GL_COMPILE_AND_EXECUTE 0x1301 +#define GL_COMPILE_STATUS 0x8B81 +#define GL_COMPRESSED_ALPHA 0x84E9 +#define GL_COMPRESSED_INTENSITY 0x84EC +#define GL_COMPRESSED_LUMINANCE 0x84EA +#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_RG 0x8226 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_RGBA_BPTC_UNORM 0x8E8C +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 +#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 +#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT 0x8E8E +#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT 0x8E8F +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define GL_COMPRESSED_SLUMINANCE 0x8C4A +#define GL_COMPRESSED_SLUMINANCE_ALPHA 0x8C4B +#define GL_COMPRESSED_SLUMINANCE_ALPHA_EXT 0x8C4B +#define GL_COMPRESSED_SLUMINANCE_EXT 0x8C4A +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM 0x8E8D +#define GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49 +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F +#define GL_COMPRESSED_SRGB_EXT 0x8C48 +#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_COMPUTE_SHADER 0x91B9 +#define GL_COMPUTE_SHADER_BIT 0x00000020 +#define GL_COMPUTE_SHADER_INVOCATIONS 0x82F5 +#define GL_COMPUTE_SUBROUTINE 0x92ED +#define GL_COMPUTE_SUBROUTINE_UNIFORM 0x92F3 +#define GL_COMPUTE_TEXTURE 0x82A0 +#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267 +#define GL_CONDITION_SATISFIED 0x911C +#define GL_CONSERVATIVE_RASTERIZATION_INTEL 0x83FE +#define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346 +#define GL_CONSTANT 0x8576 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_CONSTANT_ATTENUATION 0x1207 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define GL_CONTEXT_CORE_PROFILE_BIT 0x00000001 +#define GL_CONTEXT_FLAGS 0x821E +#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 +#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT 0x00000001 +#define GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008 +#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004 +#define GL_CONTEXT_LOST 0x0507 +#define GL_CONTEXT_PROFILE_MASK 0x9126 +#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB +#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC +#define GL_CONVOLUTION_1D 0x8010 +#define GL_CONVOLUTION_2D 0x8011 +#define GL_COORD_REPLACE 0x8862 +#define GL_COPY 0x1503 +#define GL_COPY_INVERTED 0x150C +#define GL_COPY_PIXEL_TOKEN 0x0706 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_READ_BUFFER_BINDING 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_CURRENT_BIT 0x00000001 +#define GL_CURRENT_COLOR 0x0B00 +#define GL_CURRENT_FOG_COORD 0x8453 +#define GL_CURRENT_FOG_COORDINATE 0x8453 +#define GL_CURRENT_INDEX 0x0B01 +#define GL_CURRENT_MATRIX_ARB 0x8641 +#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 +#define GL_CURRENT_NORMAL 0x0B02 +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_CURRENT_QUERY 0x8865 +#define GL_CURRENT_RASTER_COLOR 0x0B04 +#define GL_CURRENT_RASTER_DISTANCE 0x0B09 +#define GL_CURRENT_RASTER_INDEX 0x0B05 +#define GL_CURRENT_RASTER_POSITION 0x0B07 +#define GL_CURRENT_RASTER_POSITION_VALID 0x0B08 +#define GL_CURRENT_RASTER_SECONDARY_COLOR 0x845F +#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06 +#define GL_CURRENT_SECONDARY_COLOR 0x8459 +#define GL_CURRENT_TEXTURE_COORDS 0x0B03 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626 +#define GL_CW 0x0900 +#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 +#define GL_DEBUG_CALLBACK_FUNCTION_ARB 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 +#define GL_DEBUG_CALLBACK_USER_PARAM_ARB 0x8245 +#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D +#define GL_DEBUG_LOGGED_MESSAGES 0x9145 +#define GL_DEBUG_LOGGED_MESSAGES_ARB 0x9145 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_ARB 0x8243 +#define GL_DEBUG_OUTPUT 0x92E0 +#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 +#define GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB 0x8242 +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#define GL_DEBUG_SEVERITY_HIGH_ARB 0x9146 +#define GL_DEBUG_SEVERITY_LOW 0x9148 +#define GL_DEBUG_SEVERITY_LOW_ARB 0x9148 +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#define GL_DEBUG_SEVERITY_MEDIUM_ARB 0x9147 +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#define GL_DEBUG_SOURCE_API 0x8246 +#define GL_DEBUG_SOURCE_API_ARB 0x8246 +#define GL_DEBUG_SOURCE_APPLICATION 0x824A +#define GL_DEBUG_SOURCE_APPLICATION_ARB 0x824A +#define GL_DEBUG_SOURCE_OTHER 0x824B +#define GL_DEBUG_SOURCE_OTHER_ARB 0x824B +#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 +#define GL_DEBUG_SOURCE_SHADER_COMPILER_ARB 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 +#define GL_DEBUG_SOURCE_THIRD_PARTY_ARB 0x8249 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB 0x8247 +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB 0x824D +#define GL_DEBUG_TYPE_ERROR 0x824C +#define GL_DEBUG_TYPE_ERROR_ARB 0x824C +#define GL_DEBUG_TYPE_MARKER 0x8268 +#define GL_DEBUG_TYPE_OTHER 0x8251 +#define GL_DEBUG_TYPE_OTHER_ARB 0x8251 +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#define GL_DEBUG_TYPE_PERFORMANCE_ARB 0x8250 +#define GL_DEBUG_TYPE_POP_GROUP 0x826A +#define GL_DEBUG_TYPE_PORTABILITY 0x824F +#define GL_DEBUG_TYPE_PORTABILITY_ARB 0x824F +#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB 0x824E +#define GL_DECAL 0x2101 +#define GL_DECR 0x1E03 +#define GL_DECR_WRAP 0x8508 +#define GL_DELETE_STATUS 0x8B80 +#define GL_DEPTH 0x1801 +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_DEPTH_ATTACHMENT_EXT 0x8D00 +#define GL_DEPTH_BIAS 0x0D1F +#define GL_DEPTH_BITS 0x0D56 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_DEPTH_CLAMP 0x864F +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32 0x81A7 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH_COMPONENTS 0x8284 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_RENDERABLE 0x8287 +#define GL_DEPTH_SCALE 0x0D1E +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_TEXTURE_MODE 0x884B +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DIFFUSE 0x1201 +#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE +#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF +#define GL_DISPLAY_LIST 0x82E7 +#define GL_DITHER 0x0BD0 +#define GL_DOMAIN 0x0A02 +#define GL_DONT_CARE 0x1100 +#define GL_DOT3_RGB 0x86AE +#define GL_DOT3_RGBA 0x86AF +#define GL_DOUBLE 0x140A +#define GL_DOUBLEBUFFER 0x0C32 +#define GL_DOUBLE_MAT2 0x8F46 +#define GL_DOUBLE_MAT2x3 0x8F49 +#define GL_DOUBLE_MAT2x4 0x8F4A +#define GL_DOUBLE_MAT3 0x8F47 +#define GL_DOUBLE_MAT3x2 0x8F4B +#define GL_DOUBLE_MAT3x4 0x8F4C +#define GL_DOUBLE_MAT4 0x8F48 +#define GL_DOUBLE_MAT4x2 0x8F4D +#define GL_DOUBLE_MAT4x3 0x8F4E +#define GL_DOUBLE_VEC2 0x8FFC +#define GL_DOUBLE_VEC3 0x8FFD +#define GL_DOUBLE_VEC4 0x8FFE +#define GL_DRAW_BUFFER 0x0C01 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9 +#define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 +#define GL_DRAW_PIXEL_TOKEN 0x0705 +#define GL_DST_ALPHA 0x0304 +#define GL_DST_COLOR 0x0306 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_DYNAMIC_COPY_ARB 0x88EA +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_DRAW_ARB 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_READ_ARB 0x88E9 +#define GL_DYNAMIC_STORAGE_BIT 0x0100 +#define GL_EDGE_FLAG 0x0B43 +#define GL_EDGE_FLAG_ARRAY 0x8079 +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B +#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B +#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093 +#define GL_EDGE_FLAG_ARRAY_STRIDE 0x808C +#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002 +#define GL_ELEMENT_ARRAY_BARRIER_BIT_EXT 0x00000002 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 +#define GL_EMISSION 0x1600 +#define GL_ENABLE_BIT 0x00002000 +#define GL_EQUAL 0x0202 +#define GL_EQUIV 0x1509 +#define GL_EVAL_BIT 0x00010000 +#define GL_EXP 0x0800 +#define GL_EXP2 0x0801 +#define GL_EXTENSIONS 0x1F03 +#define GL_EYE_LINEAR 0x2400 +#define GL_EYE_PLANE 0x2502 +#define GL_FALSE 0 +#define GL_FASTEST 0x1101 +#define GL_FEEDBACK 0x1C01 +#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0 +#define GL_FEEDBACK_BUFFER_SIZE 0x0DF1 +#define GL_FEEDBACK_BUFFER_TYPE 0x0DF2 +#define GL_FILL 0x1B02 +#define GL_FILTER 0x829A +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_FIXED 0x140C +#define GL_FIXED_ONLY 0x891D +#define GL_FLAT 0x1D00 +#define GL_FLOAT 0x1406 +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT2_ARB 0x8B5A +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT3_ARB 0x8B5B +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4 0x8B5C +#define GL_FLOAT_MAT4_ARB 0x8B5C +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC2_ARB 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC3_ARB 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_FLOAT_VEC4_ARB 0x8B52 +#define GL_FOG 0x0B60 +#define GL_FOG_BIT 0x00000080 +#define GL_FOG_COLOR 0x0B66 +#define GL_FOG_COORD 0x8451 +#define GL_FOG_COORDINATE 0x8451 +#define GL_FOG_COORDINATE_ARRAY 0x8457 +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D +#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D +#define GL_FOG_COORDINATE_ARRAY_POINTER 0x8456 +#define GL_FOG_COORDINATE_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORDINATE_ARRAY_TYPE 0x8454 +#define GL_FOG_COORDINATE_SOURCE 0x8450 +#define GL_FOG_COORD_ARRAY 0x8457 +#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D +#define GL_FOG_COORD_ARRAY_POINTER 0x8456 +#define GL_FOG_COORD_ARRAY_STRIDE 0x8455 +#define GL_FOG_COORD_ARRAY_TYPE 0x8454 +#define GL_FOG_COORD_SRC 0x8450 +#define GL_FOG_DENSITY 0x0B62 +#define GL_FOG_END 0x0B64 +#define GL_FOG_HINT 0x0C54 +#define GL_FOG_INDEX 0x0B61 +#define GL_FOG_MODE 0x0B65 +#define GL_FOG_START 0x0B63 +#define GL_FRACTIONAL_EVEN 0x8E7C +#define GL_FRACTIONAL_ODD 0x8E7B +#define GL_FRAGMENT_DEPTH 0x8452 +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D +#define GL_FRAGMENT_PROGRAM_ARB 0x8804 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_FRAGMENT_SHADER_ARB 0x8B30 +#define GL_FRAGMENT_SHADER_BIT 0x00000002 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_ARB 0x8B8B +#define GL_FRAGMENT_SHADER_INVOCATIONS 0x82F4 +#define GL_FRAGMENT_SUBROUTINE 0x92EC +#define GL_FRAGMENT_SUBROUTINE_UNIFORM 0x92F2 +#define GL_FRAGMENT_TEXTURE 0x829F +#define GL_FRAMEBUFFER 0x8D40 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 +#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400 +#define GL_FRAMEBUFFER_BARRIER_BIT_EXT 0x00000400 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 +#define GL_FRAMEBUFFER_BLEND 0x828B +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314 +#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311 +#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312 +#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313 +#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 +#define GL_FRAMEBUFFER_EXT 0x8D40 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC +#define GL_FRAMEBUFFER_RENDERABLE 0x8289 +#define GL_FRAMEBUFFER_RENDERABLE_LAYERED 0x828A +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD +#define GL_FRONT 0x0404 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_FRONT_FACE 0x0B46 +#define GL_FRONT_LEFT 0x0400 +#define GL_FRONT_RIGHT 0x0401 +#define GL_FULL_SUPPORT 0x82B7 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_FUNC_SUBTRACT 0x800A +#define GL_GENERATE_MIPMAP 0x8191 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_GEOMETRY_SHADER_BIT 0x00000004 +#define GL_GEOMETRY_SHADER_EXT 0x8DD9 +#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED 0x82F3 +#define GL_GEOMETRY_SUBROUTINE 0x92EB +#define GL_GEOMETRY_SUBROUTINE_UNIFORM 0x92F1 +#define GL_GEOMETRY_TEXTURE 0x829E +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA +#define GL_GEQUAL 0x0206 +#define GL_GET_TEXTURE_IMAGE_FORMAT 0x8291 +#define GL_GET_TEXTURE_IMAGE_TYPE 0x8292 +#define GL_GREATER 0x0204 +#define GL_GREEN 0x1904 +#define GL_GREEN_BIAS 0x0D19 +#define GL_GREEN_BITS 0x0D53 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_GREEN_INTEGER_EXT 0x8D95 +#define GL_GREEN_SCALE 0x0D18 +#define GL_GUILTY_CONTEXT_RESET 0x8253 +#define GL_HALF_FLOAT 0x140B +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_HIGH_INT 0x8DF5 +#define GL_HINT_BIT 0x00008000 +#define GL_HISTOGRAM 0x8024 +#define GL_IMAGE_1D 0x904C +#define GL_IMAGE_1D_ARRAY 0x9052 +#define GL_IMAGE_1D_ARRAY_EXT 0x9052 +#define GL_IMAGE_1D_EXT 0x904C +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_IMAGE_2D_ARRAY_EXT 0x9053 +#define GL_IMAGE_2D_EXT 0x904D +#define GL_IMAGE_2D_MULTISAMPLE 0x9055 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY 0x9056 +#define GL_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9056 +#define GL_IMAGE_2D_MULTISAMPLE_EXT 0x9055 +#define GL_IMAGE_2D_RECT 0x904F +#define GL_IMAGE_2D_RECT_EXT 0x904F +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_3D_EXT 0x904E +#define GL_IMAGE_BINDING_ACCESS 0x8F3E +#define GL_IMAGE_BINDING_ACCESS_EXT 0x8F3E +#define GL_IMAGE_BINDING_FORMAT 0x906E +#define GL_IMAGE_BINDING_FORMAT_EXT 0x906E +#define GL_IMAGE_BINDING_LAYER 0x8F3D +#define GL_IMAGE_BINDING_LAYERED 0x8F3C +#define GL_IMAGE_BINDING_LAYERED_EXT 0x8F3C +#define GL_IMAGE_BINDING_LAYER_EXT 0x8F3D +#define GL_IMAGE_BINDING_LEVEL 0x8F3B +#define GL_IMAGE_BINDING_LEVEL_EXT 0x8F3B +#define GL_IMAGE_BINDING_NAME 0x8F3A +#define GL_IMAGE_BINDING_NAME_EXT 0x8F3A +#define GL_IMAGE_BUFFER 0x9051 +#define GL_IMAGE_BUFFER_EXT 0x9051 +#define GL_IMAGE_CLASS_10_10_10_2 0x82C3 +#define GL_IMAGE_CLASS_11_11_10 0x82C2 +#define GL_IMAGE_CLASS_1_X_16 0x82BE +#define GL_IMAGE_CLASS_1_X_32 0x82BB +#define GL_IMAGE_CLASS_1_X_8 0x82C1 +#define GL_IMAGE_CLASS_2_X_16 0x82BD +#define GL_IMAGE_CLASS_2_X_32 0x82BA +#define GL_IMAGE_CLASS_2_X_8 0x82C0 +#define GL_IMAGE_CLASS_4_X_16 0x82BC +#define GL_IMAGE_CLASS_4_X_32 0x82B9 +#define GL_IMAGE_CLASS_4_X_8 0x82BF +#define GL_IMAGE_COMPATIBILITY_CLASS 0x82A8 +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_CUBE_EXT 0x9050 +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8 +#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7 +#define GL_IMAGE_PIXEL_FORMAT 0x82A9 +#define GL_IMAGE_PIXEL_TYPE 0x82AA +#define GL_IMAGE_TEXEL_SIZE 0x82A7 +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_INCR 0x1E02 +#define GL_INCR_WRAP 0x8507 +#define GL_INDEX 0x8222 +#define GL_INDEX_ARRAY 0x8077 +#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899 +#define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 +#define GL_INDEX_ARRAY_POINTER 0x8091 +#define GL_INDEX_ARRAY_STRIDE 0x8086 +#define GL_INDEX_ARRAY_TYPE 0x8085 +#define GL_INDEX_BITS 0x0D51 +#define GL_INDEX_CLEAR_VALUE 0x0C20 +#define GL_INDEX_LOGIC_OP 0x0BF1 +#define GL_INDEX_MODE 0x0C30 +#define GL_INDEX_OFFSET 0x0D13 +#define GL_INDEX_SHIFT 0x0D12 +#define GL_INDEX_WRITEMASK 0x0C21 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_INNOCENT_CONTEXT_RESET 0x8254 +#define GL_INT 0x1404 +#define GL_INTENSITY 0x8049 +#define GL_INTENSITY12 0x804C +#define GL_INTENSITY16 0x804D +#define GL_INTENSITY16F_ARB 0x881D +#define GL_INTENSITY16I_EXT 0x8D8B +#define GL_INTENSITY16UI_EXT 0x8D79 +#define GL_INTENSITY32F_ARB 0x8817 +#define GL_INTENSITY32I_EXT 0x8D85 +#define GL_INTENSITY32UI_EXT 0x8D73 +#define GL_INTENSITY4 0x804A +#define GL_INTENSITY8 0x804B +#define GL_INTENSITY8I_EXT 0x8D91 +#define GL_INTENSITY8UI_EXT 0x8D7F +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_INTERLEAVED_ATTRIBS_EXT 0x8C8C +#define GL_INTERNALFORMAT_ALPHA_SIZE 0x8274 +#define GL_INTERNALFORMAT_ALPHA_TYPE 0x827B +#define GL_INTERNALFORMAT_BLUE_SIZE 0x8273 +#define GL_INTERNALFORMAT_BLUE_TYPE 0x827A +#define GL_INTERNALFORMAT_DEPTH_SIZE 0x8275 +#define GL_INTERNALFORMAT_DEPTH_TYPE 0x827C +#define GL_INTERNALFORMAT_GREEN_SIZE 0x8272 +#define GL_INTERNALFORMAT_GREEN_TYPE 0x8279 +#define GL_INTERNALFORMAT_PREFERRED 0x8270 +#define GL_INTERNALFORMAT_RED_SIZE 0x8271 +#define GL_INTERNALFORMAT_RED_TYPE 0x8278 +#define GL_INTERNALFORMAT_SHARED_SIZE 0x8277 +#define GL_INTERNALFORMAT_STENCIL_SIZE 0x8276 +#define GL_INTERNALFORMAT_STENCIL_TYPE 0x827D +#define GL_INTERNALFORMAT_SUPPORTED 0x826F +#define GL_INTERPOLATE 0x8575 +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_INT_IMAGE_1D 0x9057 +#define GL_INT_IMAGE_1D_ARRAY 0x905D +#define GL_INT_IMAGE_1D_ARRAY_EXT 0x905D +#define GL_INT_IMAGE_1D_EXT 0x9057 +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_INT_IMAGE_2D_ARRAY_EXT 0x905E +#define GL_INT_IMAGE_2D_EXT 0x9058 +#define GL_INT_IMAGE_2D_MULTISAMPLE 0x9060 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x9061 +#define GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x9061 +#define GL_INT_IMAGE_2D_MULTISAMPLE_EXT 0x9060 +#define GL_INT_IMAGE_2D_RECT 0x905A +#define GL_INT_IMAGE_2D_RECT_EXT 0x905A +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_3D_EXT 0x9059 +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_INT_IMAGE_BUFFER_EXT 0x905C +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_CUBE_EXT 0x905B +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_1D_ARRAY_EXT 0x8DCE +#define GL_INT_SAMPLER_1D_EXT 0x8DC9 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_INT_SAMPLER_2D_ARRAY_EXT 0x8DCF +#define GL_INT_SAMPLER_2D_EXT 0x8DCA +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_INT_SAMPLER_2D_RECT 0x8DCD +#define GL_INT_SAMPLER_2D_RECT_EXT 0x8DCD +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_3D_EXT 0x8DCB +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_CUBE_EXT 0x8DCC +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC2_ARB 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC3_ARB 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_INT_VEC4_ARB 0x8B55 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 +#define GL_INVALID_INDEX 0xFFFFFFFF +#define GL_INVALID_OPERATION 0x0502 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVERT 0x150A +#define GL_ISOLINES 0x8E7A +#define GL_IS_PER_PATCH 0x92E7 +#define GL_IS_ROW_MAJOR 0x9300 +#define GL_KEEP 0x1E00 +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_LAYER_PROVOKING_VERTEX 0x825E +#define GL_LEFT 0x0406 +#define GL_LEQUAL 0x0203 +#define GL_LESS 0x0201 +#define GL_LIGHT0 0x4000 +#define GL_LIGHT1 0x4001 +#define GL_LIGHT2 0x4002 +#define GL_LIGHT3 0x4003 +#define GL_LIGHT4 0x4004 +#define GL_LIGHT5 0x4005 +#define GL_LIGHT6 0x4006 +#define GL_LIGHT7 0x4007 +#define GL_LIGHTING 0x0B50 +#define GL_LIGHTING_BIT 0x00000040 +#define GL_LIGHT_MODEL_AMBIENT 0x0B53 +#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8 +#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51 +#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52 +#define GL_LINE 0x1B01 +#define GL_LINEAR 0x2601 +#define GL_LINEAR_ATTENUATION 0x1208 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_LINES 0x0001 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINES_ADJACENCY_EXT 0x000A +#define GL_LINE_BIT 0x00000004 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_RESET_TOKEN 0x0707 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_LINE_STIPPLE 0x0B24 +#define GL_LINE_STIPPLE_PATTERN 0x0B25 +#define GL_LINE_STIPPLE_REPEAT 0x0B26 +#define GL_LINE_STRIP 0x0003 +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B +#define GL_LINE_TOKEN 0x0702 +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINK_STATUS 0x8B82 +#define GL_LIST_BASE 0x0B32 +#define GL_LIST_BIT 0x00020000 +#define GL_LIST_INDEX 0x0B33 +#define GL_LIST_MODE 0x0B30 +#define GL_LOAD 0x0101 +#define GL_LOCATION 0x930E +#define GL_LOCATION_COMPONENT 0x934A +#define GL_LOCATION_INDEX 0x930F +#define GL_LOGIC_OP 0x0BF1 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_LOSE_CONTEXT_ON_RESET 0x8252 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_LOW_FLOAT 0x8DF0 +#define GL_LOW_INT 0x8DF3 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE12 0x8041 +#define GL_LUMINANCE12_ALPHA12 0x8047 +#define GL_LUMINANCE12_ALPHA4 0x8046 +#define GL_LUMINANCE16 0x8042 +#define GL_LUMINANCE16F_ARB 0x881E +#define GL_LUMINANCE16I_EXT 0x8D8C +#define GL_LUMINANCE16UI_EXT 0x8D7A +#define GL_LUMINANCE16_ALPHA16 0x8048 +#define GL_LUMINANCE32F_ARB 0x8818 +#define GL_LUMINANCE32I_EXT 0x8D86 +#define GL_LUMINANCE32UI_EXT 0x8D74 +#define GL_LUMINANCE4 0x803F +#define GL_LUMINANCE4_ALPHA4 0x8043 +#define GL_LUMINANCE6_ALPHA2 0x8044 +#define GL_LUMINANCE8 0x8040 +#define GL_LUMINANCE8I_EXT 0x8D92 +#define GL_LUMINANCE8UI_EXT 0x8D80 +#define GL_LUMINANCE8_ALPHA8 0x8045 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_LUMINANCE_ALPHA16F_ARB 0x881F +#define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D +#define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B +#define GL_LUMINANCE_ALPHA32F_ARB 0x8819 +#define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 +#define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 +#define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 +#define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 +#define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D +#define GL_LUMINANCE_INTEGER_EXT 0x8D9C +#define GL_MAJOR_VERSION 0x821B +#define GL_MANUAL_GENERATE_MIPMAP 0x8294 +#define GL_MAP1_COLOR_4 0x0D90 +#define GL_MAP1_GRID_DOMAIN 0x0DD0 +#define GL_MAP1_GRID_SEGMENTS 0x0DD1 +#define GL_MAP1_INDEX 0x0D91 +#define GL_MAP1_NORMAL 0x0D92 +#define GL_MAP1_TEXTURE_COORD_1 0x0D93 +#define GL_MAP1_TEXTURE_COORD_2 0x0D94 +#define GL_MAP1_TEXTURE_COORD_3 0x0D95 +#define GL_MAP1_TEXTURE_COORD_4 0x0D96 +#define GL_MAP1_VERTEX_3 0x0D97 +#define GL_MAP1_VERTEX_4 0x0D98 +#define GL_MAP2_COLOR_4 0x0DB0 +#define GL_MAP2_GRID_DOMAIN 0x0DD2 +#define GL_MAP2_GRID_SEGMENTS 0x0DD3 +#define GL_MAP2_INDEX 0x0DB1 +#define GL_MAP2_NORMAL 0x0DB2 +#define GL_MAP2_TEXTURE_COORD_1 0x0DB3 +#define GL_MAP2_TEXTURE_COORD_2 0x0DB4 +#define GL_MAP2_TEXTURE_COORD_3 0x0DB5 +#define GL_MAP2_TEXTURE_COORD_4 0x0DB6 +#define GL_MAP2_VERTEX_3 0x0DB7 +#define GL_MAP2_VERTEX_4 0x0DB8 +#define GL_MAP_COHERENT_BIT 0x0080 +#define GL_MAP_COLOR 0x0D10 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_PERSISTENT_BIT 0x0040 +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_STENCIL 0x0D11 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MATRIX0_ARB 0x88C0 +#define GL_MATRIX10_ARB 0x88CA +#define GL_MATRIX11_ARB 0x88CB +#define GL_MATRIX12_ARB 0x88CC +#define GL_MATRIX13_ARB 0x88CD +#define GL_MATRIX14_ARB 0x88CE +#define GL_MATRIX15_ARB 0x88CF +#define GL_MATRIX16_ARB 0x88D0 +#define GL_MATRIX17_ARB 0x88D1 +#define GL_MATRIX18_ARB 0x88D2 +#define GL_MATRIX19_ARB 0x88D3 +#define GL_MATRIX1_ARB 0x88C1 +#define GL_MATRIX20_ARB 0x88D4 +#define GL_MATRIX21_ARB 0x88D5 +#define GL_MATRIX22_ARB 0x88D6 +#define GL_MATRIX23_ARB 0x88D7 +#define GL_MATRIX24_ARB 0x88D8 +#define GL_MATRIX25_ARB 0x88D9 +#define GL_MATRIX26_ARB 0x88DA +#define GL_MATRIX27_ARB 0x88DB +#define GL_MATRIX28_ARB 0x88DC +#define GL_MATRIX29_ARB 0x88DD +#define GL_MATRIX2_ARB 0x88C2 +#define GL_MATRIX30_ARB 0x88DE +#define GL_MATRIX31_ARB 0x88DF +#define GL_MATRIX3_ARB 0x88C3 +#define GL_MATRIX4_ARB 0x88C4 +#define GL_MATRIX5_ARB 0x88C5 +#define GL_MATRIX6_ARB 0x88C6 +#define GL_MATRIX7_ARB 0x88C7 +#define GL_MATRIX8_ARB 0x88C8 +#define GL_MATRIX9_ARB 0x88C9 +#define GL_MATRIX_MODE 0x0BA0 +#define GL_MATRIX_STRIDE 0x92FF +#define GL_MAX 0x8008 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF +#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC +#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8 +#define GL_MAX_ATTRIB_STACK_DEPTH 0x0D35 +#define GL_MAX_CLIENT_ATTRIB_STACK_DEPTH 0x0D3B +#define GL_MAX_CLIP_DISTANCES 0x0D32 +#define GL_MAX_CLIP_PLANES 0x0D32 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7 +#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1 +#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA +#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266 +#define GL_MAX_COMBINED_DIMENSIONS 0x8282 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39 +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39 +#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39 +#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC +#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E +#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265 +#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264 +#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD +#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB +#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262 +#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC +#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB +#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263 +#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE +#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB +#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_MAX_CULL_DISTANCES 0x82F9 +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C +#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 +#define GL_MAX_DEBUG_LOGGED_MESSAGES_ARB 0x9144 +#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 +#define GL_MAX_DEBUG_MESSAGE_LENGTH_ARB 0x9143 +#define GL_MAX_DEPTH 0x8280 +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_MAX_DUAL_SOURCE_DRAW_BUFFERS 0x88FC +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_MAX_EVAL_ORDER 0x0D30 +#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6 +#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0 +#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C +#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316 +#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317 +#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318 +#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF +#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF +#define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD +#define GL_MAX_HEIGHT 0x827F +#define GL_MAX_IMAGE_SAMPLES 0x906D +#define GL_MAX_IMAGE_SAMPLES_EXT 0x906D +#define GL_MAX_IMAGE_UNITS 0x8F38 +#define GL_MAX_IMAGE_UNITS_EXT 0x8F38 +#define GL_MAX_INTEGER_SAMPLES 0x9110 +#define GL_MAX_LABEL_LENGTH 0x82E8 +#define GL_MAX_LAYERS 0x8281 +#define GL_MAX_LIGHTS 0x0D31 +#define GL_MAX_LIST_NESTING 0x0B31 +#define GL_MAX_MODELVIEW_STACK_DEPTH 0x0D36 +#define GL_MAX_NAME_LENGTH 0x92F6 +#define GL_MAX_NAME_STACK_DEPTH 0x0D37 +#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7 +#define GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8 +#define GL_MAX_PATCH_VERTICES 0x8E7D +#define GL_MAX_PIXEL_MAP_TABLE 0x0D34 +#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 +#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B +#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD +#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 +#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 +#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 +#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F +#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E +#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 +#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E +#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF +#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 +#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB +#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 +#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810 +#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F +#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9 +#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_PROGRAM_TEXEL_OFFSET_EXT 0x8905 +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D +#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C +#define GL_MAX_PROJECTION_STACK_DEPTH 0x0D38 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE +#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD +#define GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV 0x9349 +#define GL_MAX_SUBROUTINES 0x8DE7 +#define GL_MAX_SUBROUTINE_UNIFORM_LOCATIONS 0x8DE8 +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3 +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD +#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB +#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C +#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83 +#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8 +#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81 +#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85 +#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89 +#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4 +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE +#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC +#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D +#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86 +#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9 +#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82 +#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A +#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80 +#define GL_MAX_TESS_GEN_LEVEL 0x8E7E +#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84 +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_MAX_TEXTURE_COORDS 0x8871 +#define GL_MAX_TEXTURE_COORDS_ARB 0x8871 +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_TEXTURE_STACK_DEPTH 0x0D39 +#define GL_MAX_TEXTURE_UNITS 0x84E2 +#define GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80 +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_LOCATIONS 0x826E +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VARYING_FLOATS_ARB 0x8B4B +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2 +#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869 +#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA +#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9 +#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5 +#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6 +#define GL_MAX_VERTEX_STREAMS 0x8E71 +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB 0x8B4C +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB 0x8B4A +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE +#define GL_MAX_VIEWPORTS 0x825B +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MAX_WIDTH 0x827E +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_MIN 0x8007 +#define GL_MINMAX 0x802E +#define GL_MINOR_VERSION 0x821C +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B +#define GL_MIN_MAP_BUFFER_ALIGNMENT 0x90BC +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MIN_PROGRAM_TEXEL_OFFSET_EXT 0x8904 +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 +#define GL_MIPMAP 0x8293 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_MIRROR_CLAMP_TO_EDGE 0x8743 +#define GL_MODELVIEW 0x1700 +#define GL_MODELVIEW_MATRIX 0x0BA6 +#define GL_MODELVIEW_STACK_DEPTH 0x0BA3 +#define GL_MODULATE 0x2100 +#define GL_MULT 0x0103 +#define GL_MULTISAMPLE 0x809D +#define GL_MULTISAMPLE_BIT 0x20000000 +#define GL_N3F_V3F 0x2A25 +#define GL_NAME_LENGTH 0x92F9 +#define GL_NAME_STACK_DEPTH 0x0D70 +#define GL_NAND 0x150E +#define GL_NEAREST 0x2600 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_NEGATIVE_ONE_TO_ONE 0x935E +#define GL_NEVER 0x0200 +#define GL_NICEST 0x1102 +#define GL_NONE 0 +#define GL_NOOP 0x1505 +#define GL_NOR 0x1508 +#define GL_NORMALIZE 0x0BA1 +#define GL_NORMAL_ARRAY 0x8075 +#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897 +#define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 +#define GL_NORMAL_ARRAY_POINTER 0x808F +#define GL_NORMAL_ARRAY_STRIDE 0x807F +#define GL_NORMAL_ARRAY_TYPE 0x807E +#define GL_NORMAL_MAP 0x8511 +#define GL_NOTEQUAL 0x0205 +#define GL_NO_ERROR 0 +#define GL_NO_RESET_NOTIFICATION 0x8261 +#define GL_NUM_ACTIVE_VARIABLES 0x9304 +#define GL_NUM_COMPATIBLE_SUBROUTINES 0x8E4A +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_NUM_EXTENSIONS 0x821D +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_NUM_SHADING_LANGUAGE_VERSIONS 0x82E9 +#define GL_NUM_SPIR_V_EXTENSIONS 0x9554 +#define GL_OBJECT_ACTIVE_ATTRIBUTES_ARB 0x8B89 +#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A +#define GL_OBJECT_ACTIVE_UNIFORMS_ARB 0x8B86 +#define GL_OBJECT_ACTIVE_UNIFORM_MAX_LENGTH_ARB 0x8B87 +#define GL_OBJECT_ATTACHED_OBJECTS_ARB 0x8B85 +#define GL_OBJECT_COMPILE_STATUS_ARB 0x8B81 +#define GL_OBJECT_DELETE_STATUS_ARB 0x8B80 +#define GL_OBJECT_INFO_LOG_LENGTH_ARB 0x8B84 +#define GL_OBJECT_LINEAR 0x2401 +#define GL_OBJECT_LINK_STATUS_ARB 0x8B82 +#define GL_OBJECT_PLANE 0x2501 +#define GL_OBJECT_SHADER_SOURCE_LENGTH_ARB 0x8B88 +#define GL_OBJECT_SUBTYPE_ARB 0x8B4F +#define GL_OBJECT_TYPE 0x9112 +#define GL_OBJECT_TYPE_ARB 0x8B4E +#define GL_OBJECT_VALIDATE_STATUS_ARB 0x8B83 +#define GL_OFFSET 0x92FC +#define GL_ONE 1 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_ONE_MINUS_SRC1_ALPHA 0x88FB +#define GL_ONE_MINUS_SRC1_COLOR 0x88FA +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_OPERAND0_ALPHA 0x8598 +#define GL_OPERAND0_RGB 0x8590 +#define GL_OPERAND1_ALPHA 0x8599 +#define GL_OPERAND1_RGB 0x8591 +#define GL_OPERAND2_ALPHA 0x859A +#define GL_OPERAND2_RGB 0x8592 +#define GL_OR 0x1507 +#define GL_ORDER 0x0A01 +#define GL_OR_INVERTED 0x150D +#define GL_OR_REVERSE 0x150B +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_PACK_COMPRESSED_BLOCK_DEPTH 0x912D +#define GL_PACK_COMPRESSED_BLOCK_HEIGHT 0x912C +#define GL_PACK_COMPRESSED_BLOCK_SIZE 0x912E +#define GL_PACK_COMPRESSED_BLOCK_WIDTH 0x912B +#define GL_PACK_IMAGE_HEIGHT 0x806C +#define GL_PACK_LSB_FIRST 0x0D01 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_IMAGES 0x806B +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SWAP_BYTES 0x0D00 +#define GL_PARAMETER_BUFFER 0x80EE +#define GL_PARAMETER_BUFFER_BINDING 0x80EF +#define GL_PASS_THROUGH_TOKEN 0x0700 +#define GL_PATCHES 0x000E +#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73 +#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 +#define GL_PATCH_VERTICES 0x8E72 +#define GL_PERSPECTIVE_CORRECTION_HINT 0x0C50 +#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080 +#define GL_PIXEL_BUFFER_BARRIER_BIT_EXT 0x00000080 +#define GL_PIXEL_MAP_A_TO_A 0x0C79 +#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9 +#define GL_PIXEL_MAP_B_TO_B 0x0C78 +#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8 +#define GL_PIXEL_MAP_G_TO_G 0x0C77 +#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7 +#define GL_PIXEL_MAP_I_TO_A 0x0C75 +#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5 +#define GL_PIXEL_MAP_I_TO_B 0x0C74 +#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4 +#define GL_PIXEL_MAP_I_TO_G 0x0C73 +#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3 +#define GL_PIXEL_MAP_I_TO_I 0x0C70 +#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0 +#define GL_PIXEL_MAP_I_TO_R 0x0C72 +#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2 +#define GL_PIXEL_MAP_R_TO_R 0x0C76 +#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6 +#define GL_PIXEL_MAP_S_TO_S 0x0C71 +#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1 +#define GL_PIXEL_MODE_BIT 0x00000020 +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_POINT 0x1B00 +#define GL_POINTS 0x0000 +#define GL_POINT_BIT 0x00000002 +#define GL_POINT_DISTANCE_ATTENUATION 0x8129 +#define GL_POINT_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_POINT_SIZE_MAX 0x8127 +#define GL_POINT_SIZE_MIN 0x8126 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SMOOTH 0x0B10 +#define GL_POINT_SMOOTH_HINT 0x0C51 +#define GL_POINT_SPRITE 0x8861 +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_POINT_TOKEN 0x0701 +#define GL_POLYGON 0x0009 +#define GL_POLYGON_BIT 0x00000008 +#define GL_POLYGON_MODE 0x0B40 +#define GL_POLYGON_OFFSET_CLAMP 0x8E1B +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_LINE 0x2A02 +#define GL_POLYGON_OFFSET_POINT 0x2A01 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_SMOOTH 0x0B41 +#define GL_POLYGON_SMOOTH_HINT 0x0C53 +#define GL_POLYGON_STIPPLE 0x0B42 +#define GL_POLYGON_STIPPLE_BIT 0x00000010 +#define GL_POLYGON_TOKEN 0x0703 +#define GL_POSITION 0x1203 +#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2 +#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1 +#define GL_PREVIOUS 0x8578 +#define GL_PRIMARY_COLOR 0x8577 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 +#define GL_PRIMITIVES_SUBMITTED 0x82EF +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221 +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_PROGRAM 0x82E2 +#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 +#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805 +#define GL_PROGRAM_ATTRIBS_ARB 0x88AC +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINDING_ARB 0x8677 +#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B +#define GL_PROGRAM_ERROR_STRING_ARB 0x8874 +#define GL_PROGRAM_FORMAT_ARB 0x8876 +#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875 +#define GL_PROGRAM_INPUT 0x92E3 +#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0 +#define GL_PROGRAM_LENGTH_ARB 0x8627 +#define GL_PROGRAM_MATRIX_EXT 0x8E2D +#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F +#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 +#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808 +#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE +#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 +#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA +#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 +#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A +#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809 +#define GL_PROGRAM_OBJECT_ARB 0x8B40 +#define GL_PROGRAM_OUTPUT 0x92E4 +#define GL_PROGRAM_PARAMETERS_ARB 0x88A8 +#define GL_PROGRAM_PIPELINE 0x82E4 +#define GL_PROGRAM_PIPELINE_BINDING 0x825A +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_PROGRAM_POINT_SIZE_EXT 0x8642 +#define GL_PROGRAM_SEPARABLE 0x8258 +#define GL_PROGRAM_STRING_ARB 0x8628 +#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4 +#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807 +#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806 +#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 +#define GL_PROJECTION 0x1701 +#define GL_PROJECTION_MATRIX 0x0BA7 +#define GL_PROJECTION_STACK_DEPTH 0x0BA4 +#define GL_PROVOKING_VERTEX 0x8E4F +#define GL_PROXY_COLOR_TABLE 0x80D3 +#define GL_PROXY_HISTOGRAM 0x8025 +#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5 +#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4 +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_PROXY_TEXTURE_1D_ARRAY_EXT 0x8C19 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_PROXY_TEXTURE_2D_ARRAY 0x8C1B +#define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_PROXY_TEXTURE_3D 0x8070 +#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B +#define GL_PROXY_TEXTURE_CUBE_MAP_ARRAY 0x900B +#define GL_PROXY_TEXTURE_RECTANGLE 0x84F7 +#define GL_Q 0x2003 +#define GL_QUADRATIC_ATTENUATION 0x1209 +#define GL_QUADS 0x0007 +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_QUAD_STRIP 0x0008 +#define GL_QUERY 0x82E3 +#define GL_QUERY_BUFFER 0x9192 +#define GL_QUERY_BUFFER_BARRIER_BIT 0x00008000 +#define GL_QUERY_BUFFER_BINDING 0x9193 +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#define GL_QUERY_BY_REGION_NO_WAIT_INVERTED 0x8E1A +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_BY_REGION_WAIT_INVERTED 0x8E19 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_NO_WAIT_INVERTED 0x8E18 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_QUERY_RESULT_NO_WAIT 0x9194 +#define GL_QUERY_TARGET 0x82EA +#define GL_QUERY_WAIT 0x8E13 +#define GL_QUERY_WAIT_INVERTED 0x8E17 +#define GL_R 0x2002 +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_R16 0x822A +#define GL_R16F 0x822D +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R16_SNORM 0x8F98 +#define GL_R32F 0x822E +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_R3_G3_B2 0x2A10 +#define GL_R8 0x8229 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R8_SNORM 0x8F94 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_RASTERIZER_DISCARD_EXT 0x8C89 +#define GL_READ_BUFFER 0x0C02 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA +#define GL_READ_FRAMEBUFFER_EXT 0x8CA8 +#define GL_READ_ONLY 0x88B8 +#define GL_READ_ONLY_ARB 0x88B8 +#define GL_READ_PIXELS 0x828C +#define GL_READ_PIXELS_FORMAT 0x828D +#define GL_READ_PIXELS_TYPE 0x828E +#define GL_READ_WRITE 0x88BA +#define GL_READ_WRITE_ARB 0x88BA +#define GL_RED 0x1903 +#define GL_RED_BIAS 0x0D15 +#define GL_RED_BITS 0x0D52 +#define GL_RED_INTEGER 0x8D94 +#define GL_RED_INTEGER_EXT 0x8D94 +#define GL_RED_SCALE 0x0D14 +#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B +#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A +#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309 +#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307 +#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308 +#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306 +#define GL_REFLECTION_MAP 0x8512 +#define GL_RENDER 0x1C00 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 +#define GL_RENDERBUFFER_EXT 0x8D41 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 +#define GL_RENDERER 0x1F01 +#define GL_RENDER_MODE 0x0C40 +#define GL_REPEAT 0x2901 +#define GL_REPLACE 0x1E01 +#define GL_RESCALE_NORMAL 0x803A +#define GL_RESET_NOTIFICATION_STRATEGY 0x8256 +#define GL_RETURN 0x0102 +#define GL_RG 0x8227 +#define GL_RG16 0x822C +#define GL_RG16F 0x822F +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG16_SNORM 0x8F99 +#define GL_RG32F 0x8230 +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_RG8 0x822B +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB 0x1907 +#define GL_RGB10 0x8052 +#define GL_RGB10_A2 0x8059 +#define GL_RGB10_A2UI 0x906F +#define GL_RGB12 0x8053 +#define GL_RGB16 0x8054 +#define GL_RGB16F 0x881B +#define GL_RGB16F_ARB 0x881B +#define GL_RGB16I 0x8D89 +#define GL_RGB16I_EXT 0x8D89 +#define GL_RGB16UI 0x8D77 +#define GL_RGB16UI_EXT 0x8D77 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGB32F 0x8815 +#define GL_RGB32F_ARB 0x8815 +#define GL_RGB32I 0x8D83 +#define GL_RGB32I_EXT 0x8D83 +#define GL_RGB32UI 0x8D71 +#define GL_RGB32UI_EXT 0x8D71 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB565 0x8D62 +#define GL_RGB5_A1 0x8057 +#define GL_RGB8 0x8051 +#define GL_RGB8I 0x8D8F +#define GL_RGB8I_EXT 0x8D8F +#define GL_RGB8UI 0x8D7D +#define GL_RGB8UI_EXT 0x8D7D +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGB9_E5 0x8C3D +#define GL_RGBA 0x1908 +#define GL_RGBA12 0x805A +#define GL_RGBA16 0x805B +#define GL_RGBA16F 0x881A +#define GL_RGBA16F_ARB 0x881A +#define GL_RGBA16I 0x8D88 +#define GL_RGBA16I_EXT 0x8D88 +#define GL_RGBA16UI 0x8D76 +#define GL_RGBA16UI_EXT 0x8D76 +#define GL_RGBA16_SNORM 0x8F9B +#define GL_RGBA2 0x8055 +#define GL_RGBA32F 0x8814 +#define GL_RGBA32F_ARB 0x8814 +#define GL_RGBA32I 0x8D82 +#define GL_RGBA32I_EXT 0x8D82 +#define GL_RGBA32UI 0x8D70 +#define GL_RGBA32UI_EXT 0x8D70 +#define GL_RGBA4 0x8056 +#define GL_RGBA8 0x8058 +#define GL_RGBA8I 0x8D8E +#define GL_RGBA8I_EXT 0x8D8E +#define GL_RGBA8UI 0x8D7C +#define GL_RGBA8UI_EXT 0x8D7C +#define GL_RGBA8_SNORM 0x8F97 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_RGBA_INTEGER_EXT 0x8D99 +#define GL_RGBA_INTEGER_MODE_EXT 0x8D9E +#define GL_RGBA_MODE 0x0C31 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGB_INTEGER_EXT 0x8D98 +#define GL_RGB_SCALE 0x8573 +#define GL_RG_INTEGER 0x8228 +#define GL_RIGHT 0x0407 +#define GL_S 0x2000 +#define GL_SAMPLER 0x82E6 +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_1D_ARB 0x8B5D +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_1D_ARRAY_EXT 0x8DC0 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_1D_ARRAY_SHADOW_EXT 0x8DC3 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_1D_SHADOW_ARB 0x8B61 +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_2D_ARB 0x8B5E +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_SAMPLER_2D_RECT 0x8B63 +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#define GL_SAMPLER_2D_RECT_SHADOW 0x8B64 +#define GL_SAMPLER_2D_RECT_SHADOW_ARB 0x8B64 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_SAMPLER_2D_SHADOW_ARB 0x8B62 +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_3D_ARB 0x8B5F +#define GL_SAMPLER_BINDING 0x8919 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_SAMPLER_BUFFER_EXT 0x8DC2 +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_CUBE_ARB 0x8B60 +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_SAMPLER_CUBE_SHADOW_EXT 0x8DC5 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLES_PASSED 0x8914 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_ALPHA_TO_ONE 0x809F +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_SHADING 0x8C36 +#define GL_SCISSOR_BIT 0x00080000 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_SECONDARY_COLOR_ARRAY 0x845E +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C +#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C +#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D +#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A +#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C +#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B +#define GL_SELECT 0x1C02 +#define GL_SELECTION_BUFFER_POINTER 0x0DF3 +#define GL_SELECTION_BUFFER_SIZE 0x0DF4 +#define GL_SEPARABLE_2D 0x8012 +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_SEPARATE_ATTRIBS_EXT 0x8C8D +#define GL_SEPARATE_SPECULAR_COLOR 0x81FA +#define GL_SET 0x150F +#define GL_SHADER 0x82E1 +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_SHADER_BINARY_FORMAT_SPIR_V 0x9551 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT_EXT 0x00000020 +#define GL_SHADER_IMAGE_ATOMIC 0x82A6 +#define GL_SHADER_IMAGE_LOAD 0x82A4 +#define GL_SHADER_IMAGE_STORE 0x82A5 +#define GL_SHADER_OBJECT_ARB 0x8B48 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000 +#define GL_SHADER_STORAGE_BLOCK 0x92E6 +#define GL_SHADER_STORAGE_BUFFER 0x90D2 +#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3 +#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF +#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5 +#define GL_SHADER_STORAGE_BUFFER_START 0x90D4 +#define GL_SHADER_TYPE 0x8B4F +#define GL_SHADE_MODEL 0x0B54 +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_SHADING_LANGUAGE_VERSION_ARB 0x8B8C +#define GL_SHININESS 0x1601 +#define GL_SHORT 0x1402 +#define GL_SIGNALED 0x9119 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_TEST 0x82AC +#define GL_SIMULTANEOUS_TEXTURE_AND_DEPTH_WRITE 0x82AE +#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_TEST 0x82AD +#define GL_SIMULTANEOUS_TEXTURE_AND_STENCIL_WRITE 0x82AF +#define GL_SINGLE_COLOR 0x81F9 +#define GL_SLUMINANCE 0x8C46 +#define GL_SLUMINANCE8 0x8C47 +#define GL_SLUMINANCE8_ALPHA8 0x8C45 +#define GL_SLUMINANCE8_ALPHA8_EXT 0x8C45 +#define GL_SLUMINANCE8_EXT 0x8C47 +#define GL_SLUMINANCE_ALPHA 0x8C44 +#define GL_SLUMINANCE_ALPHA_EXT 0x8C44 +#define GL_SLUMINANCE_EXT 0x8C46 +#define GL_SMOOTH 0x1D01 +#define GL_SMOOTH_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_SMOOTH_LINE_WIDTH_RANGE 0x0B22 +#define GL_SMOOTH_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_SMOOTH_POINT_SIZE_RANGE 0x0B12 +#define GL_SOURCE0_ALPHA 0x8588 +#define GL_SOURCE0_RGB 0x8580 +#define GL_SOURCE1_ALPHA 0x8589 +#define GL_SOURCE1_RGB 0x8581 +#define GL_SOURCE2_ALPHA 0x858A +#define GL_SOURCE2_RGB 0x8582 +#define GL_SPECULAR 0x1202 +#define GL_SPHERE_MAP 0x2402 +#define GL_SPIR_V_BINARY 0x9552 +#define GL_SPIR_V_EXTENSIONS 0x9553 +#define GL_SPOT_CUTOFF 0x1206 +#define GL_SPOT_DIRECTION 0x1204 +#define GL_SPOT_EXPONENT 0x1205 +#define GL_SRC0_ALPHA 0x8588 +#define GL_SRC0_RGB 0x8580 +#define GL_SRC1_ALPHA 0x8589 +#define GL_SRC1_COLOR 0x88F9 +#define GL_SRC1_RGB 0x8581 +#define GL_SRC2_ALPHA 0x858A +#define GL_SRC2_RGB 0x8582 +#define GL_SRC_ALPHA 0x0302 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_SRC_COLOR 0x0300 +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_SRGB8_ALPHA8_EXT 0x8C43 +#define GL_SRGB8_EXT 0x8C41 +#define GL_SRGB_ALPHA 0x8C42 +#define GL_SRGB_ALPHA_EXT 0x8C42 +#define GL_SRGB_EXT 0x8C40 +#define GL_SRGB_READ 0x8297 +#define GL_SRGB_WRITE 0x8298 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_STATIC_COPY 0x88E6 +#define GL_STATIC_COPY_ARB 0x88E6 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_DRAW_ARB 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_READ_ARB 0x88E5 +#define GL_STENCIL 0x1802 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_STENCIL_ATTACHMENT_EXT 0x8D20 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_STENCIL_BITS 0x0D57 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_COMPONENTS 0x8285 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_INDEX 0x1901 +#define GL_STENCIL_INDEX1 0x8D46 +#define GL_STENCIL_INDEX16 0x8D49 +#define GL_STENCIL_INDEX16_EXT 0x8D49 +#define GL_STENCIL_INDEX1_EXT 0x8D46 +#define GL_STENCIL_INDEX4 0x8D47 +#define GL_STENCIL_INDEX4_EXT 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_INDEX8_EXT 0x8D48 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_RENDERABLE 0x8288 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STEREO 0x0C33 +#define GL_STREAM_COPY 0x88E2 +#define GL_STREAM_COPY_ARB 0x88E2 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_DRAW_ARB 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_READ_ARB 0x88E1 +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV 0x9347 +#define GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV 0x9348 +#define GL_SUBTRACT 0x84E7 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_SYNC_STATUS 0x9114 +#define GL_T 0x2001 +#define GL_T2F_C3F_V3F 0x2A2A +#define GL_T2F_C4F_N3F_V3F 0x2A2C +#define GL_T2F_C4UB_V3F 0x2A29 +#define GL_T2F_N3F_V3F 0x2A2B +#define GL_T2F_V3F 0x2A27 +#define GL_T4F_C4F_N3F_V4F 0x2A2D +#define GL_T4F_V4F 0x2A28 +#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75 +#define GL_TESS_CONTROL_SHADER 0x8E88 +#define GL_TESS_CONTROL_SHADER_BIT 0x00000008 +#define GL_TESS_CONTROL_SHADER_PATCHES 0x82F1 +#define GL_TESS_CONTROL_SUBROUTINE 0x92E9 +#define GL_TESS_CONTROL_SUBROUTINE_UNIFORM 0x92EF +#define GL_TESS_CONTROL_TEXTURE 0x829C +#define GL_TESS_EVALUATION_SHADER 0x8E87 +#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010 +#define GL_TESS_EVALUATION_SHADER_INVOCATIONS 0x82F2 +#define GL_TESS_EVALUATION_SUBROUTINE 0x92EA +#define GL_TESS_EVALUATION_SUBROUTINE_UNIFORM 0x92F0 +#define GL_TESS_EVALUATION_TEXTURE 0x829D +#define GL_TESS_GEN_MODE 0x8E76 +#define GL_TESS_GEN_POINT_MODE 0x8E79 +#define GL_TESS_GEN_SPACING 0x8E77 +#define GL_TESS_GEN_VERTEX_ORDER 0x8E78 +#define GL_TEXTURE 0x1702 +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE_1D 0x0DE0 +#define GL_TEXTURE_1D_ARRAY 0x8C18 +#define GL_TEXTURE_1D_ARRAY_EXT 0x8C18 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_ALPHA_TYPE_ARB 0x8C13 +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_1D_ARRAY_EXT 0x8C1C +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A +#define GL_TEXTURE_BINDING_RECTANGLE 0x84F6 +#define GL_TEXTURE_BIT 0x00040000 +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_BLUE_TYPE_ARB 0x8C12 +#define GL_TEXTURE_BORDER 0x1005 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_TEXTURE_BUFFER_BINDING 0x8C2A +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_BUFFER_OFFSET 0x919D +#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F +#define GL_TEXTURE_BUFFER_SIZE 0x919E +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPONENTS 0x1003 +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_TEXTURE_COMPRESSED_BLOCK_HEIGHT 0x82B2 +#define GL_TEXTURE_COMPRESSED_BLOCK_SIZE 0x82B3 +#define GL_TEXTURE_COMPRESSED_BLOCK_WIDTH 0x82B1 +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_COORD_ARRAY 0x8078 +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A +#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A +#define GL_TEXTURE_COORD_ARRAY_POINTER 0x8092 +#define GL_TEXTURE_COORD_ARRAY_SIZE 0x8088 +#define GL_TEXTURE_COORD_ARRAY_STRIDE 0x808A +#define GL_TEXTURE_COORD_ARRAY_TYPE 0x8089 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_SEAMLESS 0x884F +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_TEXTURE_DEPTH_TYPE_ARB 0x8C16 +#define GL_TEXTURE_ENV 0x2300 +#define GL_TEXTURE_ENV_COLOR 0x2201 +#define GL_TEXTURE_ENV_MODE 0x2200 +#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008 +#define GL_TEXTURE_FETCH_BARRIER_BIT_EXT 0x00000008 +#define GL_TEXTURE_FILTER_CONTROL 0x8500 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_TEXTURE_GATHER 0x82A2 +#define GL_TEXTURE_GATHER_SHADOW 0x82A3 +#define GL_TEXTURE_GEN_MODE 0x2500 +#define GL_TEXTURE_GEN_Q 0x0C63 +#define GL_TEXTURE_GEN_R 0x0C62 +#define GL_TEXTURE_GEN_S 0x0C60 +#define GL_TEXTURE_GEN_T 0x0C61 +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_GREEN_TYPE_ARB 0x8C11 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_IMAGE_FORMAT 0x828F +#define GL_TEXTURE_IMAGE_TYPE 0x8290 +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF +#define GL_TEXTURE_INTENSITY_SIZE 0x8061 +#define GL_TEXTURE_INTENSITY_TYPE 0x8C15 +#define GL_TEXTURE_INTENSITY_TYPE_ARB 0x8C15 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_TEXTURE_LUMINANCE_SIZE 0x8060 +#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14 +#define GL_TEXTURE_LUMINANCE_TYPE_ARB 0x8C14 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MATRIX 0x0BA8 +#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_PRIORITY 0x8066 +#define GL_TEXTURE_RECTANGLE 0x84F5 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_RED_TYPE_ARB 0x8C10 +#define GL_TEXTURE_RESIDENT 0x8067 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_SHADOW 0x82A1 +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TEXTURE_STACK_DEPTH 0x0BA5 +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46 +#define GL_TEXTURE_TARGET 0x1006 +#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100 +#define GL_TEXTURE_UPDATE_BARRIER_BIT_EXT 0x00000100 +#define GL_TEXTURE_VIEW 0x82B5 +#define GL_TEXTURE_VIEW_MIN_LAYER 0x82DD +#define GL_TEXTURE_VIEW_MIN_LEVEL 0x82DB +#define GL_TEXTURE_VIEW_NUM_LAYERS 0x82DE +#define GL_TEXTURE_VIEW_NUM_LEVELS 0x82DC +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF +#define GL_TIMESTAMP 0x8E28 +#define GL_TIME_ELAPSED 0x88BF +#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C +#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D +#define GL_TRANSFORM_BIT 0x00001000 +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT_EXT 0x00000800 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT 0x8C8F +#define GL_TRANSFORM_FEEDBACK_BUFFER_EXT 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_INDEX 0x934B +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE_EXT 0x8C7F +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT 0x8C85 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START_EXT 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE 0x934C +#define GL_TRANSFORM_FEEDBACK_OVERFLOW 0x82EC +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT 0x8C88 +#define GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW 0x82ED +#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_VARYINGS_EXT 0x8C83 +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT 0x8C76 +#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6 +#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 +#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3 +#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E +#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4 +#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLES_ADJACENCY_EXT 0x000C +#define GL_TRIANGLE_FAN 0x0006 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D +#define GL_TRUE 1 +#define GL_TYPE 0x92FA +#define GL_UNDEFINED_VERTEX 0x8260 +#define GL_UNIFORM 0x92E1 +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA +#define GL_UNIFORM_BARRIER_BIT 0x00000004 +#define GL_UNIFORM_BARRIER_BIT_EXT 0x00000004 +#define GL_UNIFORM_BLOCK 0x92E2 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNKNOWN_CONTEXT_RESET 0x8255 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_UNPACK_COMPRESSED_BLOCK_DEPTH 0x9129 +#define GL_UNPACK_COMPRESSED_BLOCK_HEIGHT 0x9128 +#define GL_UNPACK_COMPRESSED_BLOCK_SIZE 0x912A +#define GL_UNPACK_COMPRESSED_BLOCK_WIDTH 0x9127 +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_UNPACK_LSB_FIRST 0x0CF1 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SWAP_BYTES 0x0CF0 +#define GL_UNSIGNALED 0x9118 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362 +#define GL_UNSIGNED_BYTE_3_3_2 0x8032 +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_UNSIGNED_INT_10_10_10_2 0x8036 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_UNSIGNED_INT_8_8_8_8 0x8035 +#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367 +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB +#define GL_UNSIGNED_INT_IMAGE_1D 0x9062 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY 0x9068 +#define GL_UNSIGNED_INT_IMAGE_1D_ARRAY_EXT 0x9068 +#define GL_UNSIGNED_INT_IMAGE_1D_EXT 0x9062 +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY_EXT 0x9069 +#define GL_UNSIGNED_INT_IMAGE_2D_EXT 0x9063 +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY 0x906C +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY_EXT 0x906C +#define GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_EXT 0x906B +#define GL_UNSIGNED_INT_IMAGE_2D_RECT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_2D_RECT_EXT 0x9065 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_3D_EXT 0x9064 +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_CUBE_EXT 0x9066 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A +#define GL_UNSIGNED_INT_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY_EXT 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_1D_EXT 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY_EXT 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_2D_EXT 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT 0x8DD5 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_3D_EXT 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_CUBE_EXT 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC2_EXT 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC3_EXT 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_UNSIGNED_INT_VEC4_EXT 0x8DC8 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_UNSIGNED_NORMALIZED_ARB 0x8C17 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364 +#define GL_UPPER_LEFT 0x8CA2 +#define GL_V2F 0x2A20 +#define GL_V3F 0x2A21 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_VENDOR 0x1F00 +#define GL_VERSION 0x1F02 +#define GL_VERTEX_ARRAY 0x8074 +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896 +#define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 +#define GL_VERTEX_ARRAY_POINTER 0x808E +#define GL_VERTEX_ARRAY_SIZE 0x807A +#define GL_VERTEX_ARRAY_STRIDE 0x807C +#define GL_VERTEX_ARRAY_TYPE 0x807B +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT_EXT 0x00000001 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER_EXT 0x88FD +#define GL_VERTEX_ATTRIB_ARRAY_LONG 0x874E +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 +#define GL_VERTEX_ATTRIB_BINDING 0x82D4 +#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5 +#define GL_VERTEX_BINDING_BUFFER 0x8F4F +#define GL_VERTEX_BINDING_DIVISOR 0x82D6 +#define GL_VERTEX_BINDING_OFFSET 0x82D7 +#define GL_VERTEX_BINDING_STRIDE 0x82D8 +#define GL_VERTEX_PROGRAM_ARB 0x8620 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 +#define GL_VERTEX_PROGRAM_TWO_SIDE 0x8643 +#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_VERTEX_SHADER_ARB 0x8B31 +#define GL_VERTEX_SHADER_BIT 0x00000001 +#define GL_VERTEX_SHADER_INVOCATIONS 0x82F0 +#define GL_VERTEX_SUBROUTINE 0x92E8 +#define GL_VERTEX_SUBROUTINE_UNIFORM 0x92EE +#define GL_VERTEX_TEXTURE 0x829B +#define GL_VERTICES_SUBMITTED 0x82EE +#define GL_VIEWPORT 0x0BA2 +#define GL_VIEWPORT_BIT 0x00000800 +#define GL_VIEWPORT_BOUNDS_RANGE 0x825D +#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F +#define GL_VIEWPORT_SUBPIXEL_BITS 0x825C +#define GL_VIEW_CLASS_128_BITS 0x82C4 +#define GL_VIEW_CLASS_16_BITS 0x82CA +#define GL_VIEW_CLASS_24_BITS 0x82C9 +#define GL_VIEW_CLASS_32_BITS 0x82C8 +#define GL_VIEW_CLASS_48_BITS 0x82C7 +#define GL_VIEW_CLASS_64_BITS 0x82C6 +#define GL_VIEW_CLASS_8_BITS 0x82CB +#define GL_VIEW_CLASS_96_BITS 0x82C5 +#define GL_VIEW_CLASS_BPTC_FLOAT 0x82D3 +#define GL_VIEW_CLASS_BPTC_UNORM 0x82D2 +#define GL_VIEW_CLASS_RGTC1_RED 0x82D0 +#define GL_VIEW_CLASS_RGTC2_RG 0x82D1 +#define GL_VIEW_CLASS_S3TC_DXT1_RGB 0x82CC +#define GL_VIEW_CLASS_S3TC_DXT1_RGBA 0x82CD +#define GL_VIEW_CLASS_S3TC_DXT3_RGBA 0x82CE +#define GL_VIEW_CLASS_S3TC_DXT5_RGBA 0x82CF +#define GL_VIEW_COMPATIBILITY_CLASS 0x82B6 +#define GL_WAIT_FAILED 0x911D +#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E +#define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E +#define GL_WRITE_ONLY 0x88B9 +#define GL_WRITE_ONLY_ARB 0x88B9 +#define GL_XOR 0x1506 +#define GL_ZERO 0 +#define GL_ZERO_TO_ONE 0x935F +#define GL_ZOOM_X 0x0D16 +#define GL_ZOOM_Y 0x0D17 + + +#ifndef __khrplatform_h_ +#define __khrplatform_h_ + +/* +** Copyright (c) 2008-2018 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE 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 OR COPYRIGHT HOLDERS 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 +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Khronos platform-specific types and definitions. + * + * The master copy of khrplatform.h is maintained in the Khronos EGL + * Registry repository at https://github.com/KhronosGroup/EGL-Registry + * The last semantic modification to khrplatform.h was at commit ID: + * 67a3e0864c2d75ea5287b9f3d2eb74a745936692 + * + * Adopters may modify this file to suit their platform. Adopters are + * encouraged to submit platform specific modifications to the Khronos + * group so that they can be included in future versions of this file. + * Please submit changes by filing pull requests or issues on + * the EGL Registry repository linked above. + * + * + * See the Implementer's Guidelines for information about where this file + * should be located on your system and for more details of its use: + * http://www.khronos.org/registry/implementers_guide.pdf + * + * This file should be included as + * #include + * by Khronos client API header files that use its types and defines. + * + * The types in khrplatform.h should only be used to define API-specific types. + * + * Types defined in khrplatform.h: + * khronos_int8_t signed 8 bit + * khronos_uint8_t unsigned 8 bit + * khronos_int16_t signed 16 bit + * khronos_uint16_t unsigned 16 bit + * khronos_int32_t signed 32 bit + * khronos_uint32_t unsigned 32 bit + * khronos_int64_t signed 64 bit + * khronos_uint64_t unsigned 64 bit + * khronos_intptr_t signed same number of bits as a pointer + * khronos_uintptr_t unsigned same number of bits as a pointer + * khronos_ssize_t signed size + * khronos_usize_t unsigned size + * khronos_float_t signed 32 bit floating point + * khronos_time_ns_t unsigned 64 bit time in nanoseconds + * khronos_utime_nanoseconds_t unsigned time interval or absolute time in + * nanoseconds + * khronos_stime_nanoseconds_t signed time interval in nanoseconds + * khronos_boolean_enum_t enumerated boolean type. This should + * only be used as a base type when a client API's boolean type is + * an enum. Client APIs which use an integer or other type for + * booleans cannot use this as the base type for their boolean. + * + * Tokens defined in khrplatform.h: + * + * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. + * + * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. + * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. + * + * Calling convention macros defined in this file: + * KHRONOS_APICALL + * KHRONOS_GLAD_API_PTR + * KHRONOS_APIATTRIBUTES + * + * These may be used in function prototypes as: + * + * KHRONOS_APICALL void KHRONOS_GLAD_API_PTR funcname( + * int arg1, + * int arg2) KHRONOS_APIATTRIBUTES; + */ + +#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) +# define KHRONOS_STATIC 1 +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APICALL + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +#if defined(KHRONOS_STATIC) + /* If the preprocessor constant KHRONOS_STATIC is defined, make the + * header compatible with static linking. */ +# define KHRONOS_APICALL +#elif defined(_WIN32) +# define KHRONOS_APICALL __declspec(dllimport) +#elif defined (__SYMBIAN32__) +# define KHRONOS_APICALL IMPORT_C +#elif defined(__ANDROID__) +# define KHRONOS_APICALL __attribute__((visibility("default"))) +#else +# define KHRONOS_APICALL +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_GLAD_API_PTR + *------------------------------------------------------------------------- + * This follows the return type of the function and precedes the function + * name in the function prototype. + */ +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) + /* Win32 but not WinCE */ +# define KHRONOS_GLAD_API_PTR __stdcall +#else +# define KHRONOS_GLAD_API_PTR +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIATTRIBUTES + *------------------------------------------------------------------------- + * This follows the closing parenthesis of the function prototype arguments. + */ +#if defined (__ARMCC_2__) +#define KHRONOS_APIATTRIBUTES __softfp +#else +#define KHRONOS_APIATTRIBUTES +#endif + +/*------------------------------------------------------------------------- + * basic type definitions + *-----------------------------------------------------------------------*/ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) + + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 +/* + * To support platform where unsigned long cannot be used interchangeably with + * inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t. + * Ideally, we could just use (u)intptr_t everywhere, but this could result in + * ABI breakage if khronos_uintptr_t is changed from unsigned long to + * unsigned long long or similar (this results in different C++ name mangling). + * To avoid changes for existing platforms, we restrict usage of intptr_t to + * platforms where the size of a pointer is larger than the size of long. + */ +#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__) +#if __SIZEOF_POINTER__ > __SIZEOF_LONG__ +#define KHRONOS_USE_INTPTR_T +#endif +#endif + +#elif defined(__VMS ) || defined(__sgi) + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) + +/* + * Win32 + */ +typedef __int32 khronos_int32_t; +typedef unsigned __int32 khronos_uint32_t; +typedef __int64 khronos_int64_t; +typedef unsigned __int64 khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__sun__) || defined(__digital__) + +/* + * Sun or Digital + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#if defined(__arch64__) || defined(_LP64) +typedef long int khronos_int64_t; +typedef unsigned long int khronos_uint64_t; +#else +typedef long long int khronos_int64_t; +typedef unsigned long long int khronos_uint64_t; +#endif /* __arch64__ */ +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif 0 + +/* + * Hypothetical platform with no float or int64 support + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#define KHRONOS_SUPPORT_INT64 0 +#define KHRONOS_SUPPORT_FLOAT 0 + +#else + +/* + * Generic fallback + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#endif + + +/* + * Types that are (so far) the same on all platforms + */ +typedef signed char khronos_int8_t; +typedef unsigned char khronos_uint8_t; +typedef signed short int khronos_int16_t; +typedef unsigned short int khronos_uint16_t; + +/* + * Types that differ between LLP64 and LP64 architectures - in LLP64, + * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears + * to be the only LLP64 architecture in current use. + */ +#ifdef KHRONOS_USE_INTPTR_T +typedef intptr_t khronos_intptr_t; +typedef uintptr_t khronos_uintptr_t; +#elif defined(_WIN64) +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +#endif + +#if defined(_WIN64) +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; +#endif + +#if KHRONOS_SUPPORT_FLOAT +/* + * Float type + */ +typedef float khronos_float_t; +#endif + +#if KHRONOS_SUPPORT_INT64 +/* Time types + * + * These types can be used to represent a time interval in nanoseconds or + * an absolute Unadjusted System Time. Unadjusted System Time is the number + * of nanoseconds since some arbitrary system event (e.g. since the last + * time the system booted). The Unadjusted System Time is an unsigned + * 64 bit value that wraps back to 0 every 584 years. Time intervals + * may be either signed or unsigned. + */ +typedef khronos_uint64_t khronos_utime_nanoseconds_t; +typedef khronos_int64_t khronos_stime_nanoseconds_t; +#endif + +/* + * Dummy value used to pad enum types to 32 bits. + */ +#ifndef KHRONOS_MAX_ENUM +#define KHRONOS_MAX_ENUM 0x7FFFFFFF +#endif + +/* + * Enumerated boolean type + * + * Values other than zero should be considered to be true. Therefore + * comparisons should not be made against KHRONOS_TRUE. + */ +typedef enum { + KHRONOS_FALSE = 0, + KHRONOS_TRUE = 1, + KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM +} khronos_boolean_enum_t; + +#endif /* __khrplatform_h_ */ +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef khronos_int8_t GLbyte; +typedef khronos_uint8_t GLubyte; +typedef khronos_int16_t GLshort; +typedef khronos_uint16_t GLushort; +typedef int GLint; +typedef unsigned int GLuint; +typedef khronos_int32_t GLclampx; +typedef int GLsizei; +typedef khronos_float_t GLfloat; +typedef khronos_float_t GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef void *GLeglClientBufferEXT; +typedef void *GLeglImageOES; +typedef char GLchar; +typedef char GLcharARB; +#ifdef __APPLE__ +typedef void *GLhandleARB; +#else +typedef unsigned int GLhandleARB; +#endif +typedef khronos_uint16_t GLhalf; +typedef khronos_uint16_t GLhalfARB; +typedef khronos_int32_t GLfixed; +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_intptr_t GLintptr; +#else +typedef khronos_intptr_t GLintptr; +#endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_intptr_t GLintptrARB; +#else +typedef khronos_intptr_t GLintptrARB; +#endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_ssize_t GLsizeiptr; +#else +typedef khronos_ssize_t GLsizeiptr; +#endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_ssize_t GLsizeiptrARB; +#else +typedef khronos_ssize_t GLsizeiptrARB; +#endif +typedef khronos_int64_t GLint64; +typedef khronos_int64_t GLint64EXT; +typedef khronos_uint64_t GLuint64; +typedef khronos_uint64_t GLuint64EXT; +typedef struct __GLsync *GLsync; +struct _cl_context; +struct _cl_event; +typedef void (GLAD_API_PTR *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (GLAD_API_PTR *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (GLAD_API_PTR *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (GLAD_API_PTR *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam); +typedef unsigned short GLhalfNV; +typedef GLintptr GLvdpauSurfaceNV; +typedef void (GLAD_API_PTR *GLVULKANPROCNV)(void); + + +#define GL_VERSION_1_0 1 +GLAD_API_CALL int GLAD_GL_VERSION_1_0; +#define GL_VERSION_1_1 1 +GLAD_API_CALL int GLAD_GL_VERSION_1_1; +#define GL_VERSION_1_2 1 +GLAD_API_CALL int GLAD_GL_VERSION_1_2; +#define GL_VERSION_1_3 1 +GLAD_API_CALL int GLAD_GL_VERSION_1_3; +#define GL_VERSION_1_4 1 +GLAD_API_CALL int GLAD_GL_VERSION_1_4; +#define GL_VERSION_1_5 1 +GLAD_API_CALL int GLAD_GL_VERSION_1_5; +#define GL_VERSION_2_0 1 +GLAD_API_CALL int GLAD_GL_VERSION_2_0; +#define GL_VERSION_2_1 1 +GLAD_API_CALL int GLAD_GL_VERSION_2_1; +#define GL_VERSION_3_0 1 +GLAD_API_CALL int GLAD_GL_VERSION_3_0; +#define GL_VERSION_3_1 1 +GLAD_API_CALL int GLAD_GL_VERSION_3_1; +#define GL_VERSION_3_2 1 +GLAD_API_CALL int GLAD_GL_VERSION_3_2; +#define GL_VERSION_3_3 1 +GLAD_API_CALL int GLAD_GL_VERSION_3_3; +#define GL_VERSION_4_0 1 +GLAD_API_CALL int GLAD_GL_VERSION_4_0; +#define GL_VERSION_4_1 1 +GLAD_API_CALL int GLAD_GL_VERSION_4_1; +#define GL_VERSION_4_2 1 +GLAD_API_CALL int GLAD_GL_VERSION_4_2; +#define GL_VERSION_4_3 1 +GLAD_API_CALL int GLAD_GL_VERSION_4_3; +#define GL_VERSION_4_4 1 +GLAD_API_CALL int GLAD_GL_VERSION_4_4; +#define GL_VERSION_4_5 1 +GLAD_API_CALL int GLAD_GL_VERSION_4_5; +#define GL_VERSION_4_6 1 +GLAD_API_CALL int GLAD_GL_VERSION_4_6; +#define GL_ARB_compatibility 1 +GLAD_API_CALL int GLAD_GL_ARB_compatibility; +#define GL_ARB_debug_output 1 +GLAD_API_CALL int GLAD_GL_ARB_debug_output; +#define GL_ARB_fragment_program 1 +GLAD_API_CALL int GLAD_GL_ARB_fragment_program; +#define GL_ARB_fragment_shader 1 +GLAD_API_CALL int GLAD_GL_ARB_fragment_shader; +#define GL_ARB_framebuffer_sRGB 1 +GLAD_API_CALL int GLAD_GL_ARB_framebuffer_sRGB; +#define GL_ARB_shader_image_load_store 1 +GLAD_API_CALL int GLAD_GL_ARB_shader_image_load_store; +#define GL_ARB_shader_image_size 1 +GLAD_API_CALL int GLAD_GL_ARB_shader_image_size; +#define GL_ARB_shader_objects 1 +GLAD_API_CALL int GLAD_GL_ARB_shader_objects; +#define GL_ARB_shader_storage_buffer_object 1 +GLAD_API_CALL int GLAD_GL_ARB_shader_storage_buffer_object; +#define GL_ARB_shading_language_100 1 +GLAD_API_CALL int GLAD_GL_ARB_shading_language_100; +#define GL_ARB_texture_float 1 +GLAD_API_CALL int GLAD_GL_ARB_texture_float; +#define GL_ARB_texture_rg 1 +GLAD_API_CALL int GLAD_GL_ARB_texture_rg; +#define GL_ARB_texture_rgb10_a2ui 1 +GLAD_API_CALL int GLAD_GL_ARB_texture_rgb10_a2ui; +#define GL_ARB_vertex_buffer_object 1 +GLAD_API_CALL int GLAD_GL_ARB_vertex_buffer_object; +#define GL_ARB_vertex_program 1 +GLAD_API_CALL int GLAD_GL_ARB_vertex_program; +#define GL_ARB_vertex_shader 1 +GLAD_API_CALL int GLAD_GL_ARB_vertex_shader; +#define GL_ARB_vertex_type_2_10_10_10_rev 1 +GLAD_API_CALL int GLAD_GL_ARB_vertex_type_2_10_10_10_rev; +#define GL_EXT_direct_state_access 1 +GLAD_API_CALL int GLAD_GL_EXT_direct_state_access; +#define GL_EXT_framebuffer_blit 1 +GLAD_API_CALL int GLAD_GL_EXT_framebuffer_blit; +#define GL_EXT_framebuffer_object 1 +GLAD_API_CALL int GLAD_GL_EXT_framebuffer_object; +#define GL_EXT_framebuffer_sRGB 1 +GLAD_API_CALL int GLAD_GL_EXT_framebuffer_sRGB; +#define GL_EXT_geometry_shader4 1 +GLAD_API_CALL int GLAD_GL_EXT_geometry_shader4; +#define GL_EXT_gpu_shader4 1 +GLAD_API_CALL int GLAD_GL_EXT_gpu_shader4; +#define GL_EXT_shader_image_load_store 1 +GLAD_API_CALL int GLAD_GL_EXT_shader_image_load_store; +#define GL_EXT_texture_array 1 +GLAD_API_CALL int GLAD_GL_EXT_texture_array; +#define GL_EXT_texture_compression_s3tc 1 +GLAD_API_CALL int GLAD_GL_EXT_texture_compression_s3tc; +#define GL_EXT_texture_integer 1 +GLAD_API_CALL int GLAD_GL_EXT_texture_integer; +#define GL_EXT_texture_sRGB 1 +GLAD_API_CALL int GLAD_GL_EXT_texture_sRGB; +#define GL_EXT_transform_feedback 1 +GLAD_API_CALL int GLAD_GL_EXT_transform_feedback; +#define GL_INTEL_conservative_rasterization 1 +GLAD_API_CALL int GLAD_GL_INTEL_conservative_rasterization; +#define GL_NV_conservative_raster 1 +GLAD_API_CALL int GLAD_GL_NV_conservative_raster; + + +typedef void (GLAD_API_PTR *PFNGLACCUMPROC)(GLenum op, GLfloat value); +typedef void (GLAD_API_PTR *PFNGLACTIVESHADERPROGRAMPROC)(GLuint pipeline, GLuint program); +typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum texture); +typedef void (GLAD_API_PTR *PFNGLALPHAFUNCPROC)(GLenum func, GLfloat ref); +typedef GLboolean (GLAD_API_PTR *PFNGLARETEXTURESRESIDENTPROC)(GLsizei n, const GLuint * textures, GLboolean * residences); +typedef void (GLAD_API_PTR *PFNGLARRAYELEMENTPROC)(GLint i); +typedef void (GLAD_API_PTR *PFNGLATTACHOBJECTARBPROC)(GLhandleARB containerObj, GLhandleARB obj); +typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader); +typedef void (GLAD_API_PTR *PFNGLBEGINPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLBEGINCONDITIONALRENDERPROC)(GLuint id, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLBEGINQUERYPROC)(GLenum target, GLuint id); +typedef void (GLAD_API_PTR *PFNGLBEGINQUERYINDEXEDPROC)(GLenum target, GLuint index, GLuint id); +typedef void (GLAD_API_PTR *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode); +typedef void (GLAD_API_PTR *PFNGLBEGINTRANSFORMFEEDBACKEXTPROC)(GLenum primitiveMode); +typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONARBPROC)(GLhandleARB programObj, GLuint index, const GLcharARB * name); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERARBPROC)(GLenum target, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASEEXTPROC)(GLenum target, GLuint index, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFEROFFSETEXTPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGEEXTPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERSBASEPROC)(GLenum target, GLuint first, GLsizei count, const GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERSRANGEPROC)(GLenum target, GLuint first, GLsizei count, const GLuint * buffers, const GLintptr * offsets, const GLsizeiptr * sizes); +typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONPROC)(GLuint program, GLuint color, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONEXTPROC)(GLuint program, GLuint color, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONINDEXEDPROC)(GLuint program, GLuint colorNumber, GLuint index, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer); +typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFEREXTPROC)(GLenum target, GLuint framebuffer); +typedef void (GLAD_API_PTR *PFNGLBINDIMAGETEXTUREPROC)(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +typedef void (GLAD_API_PTR *PFNGLBINDIMAGETEXTUREEXTPROC)(GLuint index, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLint format); +typedef void (GLAD_API_PTR *PFNGLBINDIMAGETEXTURESPROC)(GLuint first, GLsizei count, const GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLBINDMULTITEXTUREEXTPROC)(GLenum texunit, GLenum target, GLuint texture); +typedef void (GLAD_API_PTR *PFNGLBINDPROGRAMARBPROC)(GLenum target, GLuint program); +typedef void (GLAD_API_PTR *PFNGLBINDPROGRAMPIPELINEPROC)(GLuint pipeline); +typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFEREXTPROC)(GLenum target, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLBINDSAMPLERPROC)(GLuint unit, GLuint sampler); +typedef void (GLAD_API_PTR *PFNGLBINDSAMPLERSPROC)(GLuint first, GLsizei count, const GLuint * samplers); +typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture); +typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREUNITPROC)(GLuint unit, GLuint texture); +typedef void (GLAD_API_PTR *PFNGLBINDTEXTURESPROC)(GLuint first, GLsizei count, const GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLBINDTRANSFORMFEEDBACKPROC)(GLenum target, GLuint id); +typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYPROC)(GLuint array); +typedef void (GLAD_API_PTR *PFNGLBINDVERTEXBUFFERPROC)(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (GLAD_API_PTR *PFNGLBINDVERTEXBUFFERSPROC)(GLuint first, GLsizei count, const GLuint * buffers, const GLintptr * offsets, const GLsizei * strides); +typedef void (GLAD_API_PTR *PFNGLBITMAPPROC)(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte * bitmap); +typedef void (GLAD_API_PTR *PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEIPROC)(GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONIPROC)(GLuint buf, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEIPROC)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCIPROC)(GLuint buf, GLenum src, GLenum dst); +typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFERPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFEREXTPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (GLAD_API_PTR *PFNGLBLITNAMEDFRAMEBUFFERPROC)(GLuint readFramebuffer, GLuint drawFramebuffer, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (GLAD_API_PTR *PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void * data, GLenum usage); +typedef void (GLAD_API_PTR *PFNGLBUFFERDATAARBPROC)(GLenum target, GLsizeiptrARB size, const void * data, GLenum usage); +typedef void (GLAD_API_PTR *PFNGLBUFFERSTORAGEPROC)(GLenum target, GLsizeiptr size, const void * data, GLbitfield flags); +typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data); +typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAARBPROC)(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const void * data); +typedef void (GLAD_API_PTR *PFNGLCALLLISTPROC)(GLuint list); +typedef void (GLAD_API_PTR *PFNGLCALLLISTSPROC)(GLsizei n, GLenum type, const void * lists); +typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target); +typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)(GLenum target); +typedef GLenum (GLAD_API_PTR *PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC)(GLuint framebuffer, GLenum target); +typedef GLenum (GLAD_API_PTR *PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC)(GLuint framebuffer, GLenum target); +typedef void (GLAD_API_PTR *PFNGLCLAMPCOLORPROC)(GLenum target, GLenum clamp); +typedef void (GLAD_API_PTR *PFNGLCLEARPROC)(GLbitfield mask); +typedef void (GLAD_API_PTR *PFNGLCLEARACCUMPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERDATAPROC)(GLenum target, GLenum internalformat, GLenum format, GLenum type, const void * data); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERSUBDATAPROC)(GLenum target, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void * data); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFIPROC)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFVPROC)(GLenum buffer, GLint drawbuffer, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERIVPROC)(GLenum buffer, GLint drawbuffer, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERUIVPROC)(GLenum buffer, GLint drawbuffer, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GLAD_API_PTR *PFNGLCLEARCOLORIIEXTPROC)(GLint red, GLint green, GLint blue, GLint alpha); +typedef void (GLAD_API_PTR *PFNGLCLEARCOLORIUIEXTPROC)(GLuint red, GLuint green, GLuint blue, GLuint alpha); +typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHPROC)(GLdouble depth); +typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHFPROC)(GLfloat d); +typedef void (GLAD_API_PTR *PFNGLCLEARINDEXPROC)(GLfloat c); +typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDBUFFERDATAPROC)(GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void * data); +typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDBUFFERDATAEXTPROC)(GLuint buffer, GLenum internalformat, GLenum format, GLenum type, const void * data); +typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDBUFFERSUBDATAPROC)(GLuint buffer, GLenum internalformat, GLintptr offset, GLsizeiptr size, GLenum format, GLenum type, const void * data); +typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC)(GLuint buffer, GLenum internalformat, GLsizeiptr offset, GLsizeiptr size, GLenum format, GLenum type, const void * data); +typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDFRAMEBUFFERFIPROC)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDFRAMEBUFFERFVPROC)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDFRAMEBUFFERIVPROC)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC)(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint s); +typedef void (GLAD_API_PTR *PFNGLCLEARTEXIMAGEPROC)(GLuint texture, GLint level, GLenum format, GLenum type, const void * data); +typedef void (GLAD_API_PTR *PFNGLCLEARTEXSUBIMAGEPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * data); +typedef void (GLAD_API_PTR *PFNGLCLIENTACTIVETEXTUREPROC)(GLenum texture); +typedef void (GLAD_API_PTR *PFNGLCLIENTATTRIBDEFAULTEXTPROC)(GLbitfield mask); +typedef GLenum (GLAD_API_PTR *PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GLAD_API_PTR *PFNGLCLIPCONTROLPROC)(GLenum origin, GLenum depth); +typedef void (GLAD_API_PTR *PFNGLCLIPPLANEPROC)(GLenum plane, const GLdouble * equation); +typedef void (GLAD_API_PTR *PFNGLCOLOR3BPROC)(GLbyte red, GLbyte green, GLbyte blue); +typedef void (GLAD_API_PTR *PFNGLCOLOR3BVPROC)(const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR3DPROC)(GLdouble red, GLdouble green, GLdouble blue); +typedef void (GLAD_API_PTR *PFNGLCOLOR3DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR3FPROC)(GLfloat red, GLfloat green, GLfloat blue); +typedef void (GLAD_API_PTR *PFNGLCOLOR3FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR3IPROC)(GLint red, GLint green, GLint blue); +typedef void (GLAD_API_PTR *PFNGLCOLOR3IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR3SPROC)(GLshort red, GLshort green, GLshort blue); +typedef void (GLAD_API_PTR *PFNGLCOLOR3SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR3UBPROC)(GLubyte red, GLubyte green, GLubyte blue); +typedef void (GLAD_API_PTR *PFNGLCOLOR3UBVPROC)(const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR3UIPROC)(GLuint red, GLuint green, GLuint blue); +typedef void (GLAD_API_PTR *PFNGLCOLOR3UIVPROC)(const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR3USPROC)(GLushort red, GLushort green, GLushort blue); +typedef void (GLAD_API_PTR *PFNGLCOLOR3USVPROC)(const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR4BPROC)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha); +typedef void (GLAD_API_PTR *PFNGLCOLOR4BVPROC)(const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR4DPROC)(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha); +typedef void (GLAD_API_PTR *PFNGLCOLOR4DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR4FPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GLAD_API_PTR *PFNGLCOLOR4FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR4IPROC)(GLint red, GLint green, GLint blue, GLint alpha); +typedef void (GLAD_API_PTR *PFNGLCOLOR4IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR4SPROC)(GLshort red, GLshort green, GLshort blue, GLshort alpha); +typedef void (GLAD_API_PTR *PFNGLCOLOR4SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR4UBPROC)(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha); +typedef void (GLAD_API_PTR *PFNGLCOLOR4UBVPROC)(const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR4UIPROC)(GLuint red, GLuint green, GLuint blue, GLuint alpha); +typedef void (GLAD_API_PTR *PFNGLCOLOR4UIVPROC)(const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLCOLOR4USPROC)(GLushort red, GLushort green, GLushort blue, GLushort alpha); +typedef void (GLAD_API_PTR *PFNGLCOLOR4USVPROC)(const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +typedef void (GLAD_API_PTR *PFNGLCOLORMASKIPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef void (GLAD_API_PTR *PFNGLCOLORMATERIALPROC)(GLenum face, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLCOLORP3UIPROC)(GLenum type, GLuint color); +typedef void (GLAD_API_PTR *PFNGLCOLORP3UIVPROC)(GLenum type, const GLuint * color); +typedef void (GLAD_API_PTR *PFNGLCOLORP4UIPROC)(GLenum type, GLuint color); +typedef void (GLAD_API_PTR *PFNGLCOLORP4UIVPROC)(GLenum type, const GLuint * color); +typedef void (GLAD_API_PTR *PFNGLCOLORPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERPROC)(GLuint shader); +typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERARBPROC)(GLhandleARB shaderObj); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC)(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * bits); +typedef void (GLAD_API_PTR *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLCOPYIMAGESUBDATAPROC)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +typedef void (GLAD_API_PTR *PFNGLCOPYMULTITEXIMAGE1DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYMULTITEXIMAGE2DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAD_API_PTR *PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYNAMEDBUFFERSUBDATAPROC)(GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLCOPYPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE1DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTUREIMAGE1DEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTUREIMAGE2DEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURESUBIMAGE1DPROC)(GLuint texture, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURESUBIMAGE2DPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURESUBIMAGE3DPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCREATEBUFFERSPROC)(GLsizei n, GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLCREATEFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers); +typedef GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void); +typedef GLhandleARB (GLAD_API_PTR *PFNGLCREATEPROGRAMOBJECTARBPROC)(void); +typedef void (GLAD_API_PTR *PFNGLCREATEPROGRAMPIPELINESPROC)(GLsizei n, GLuint * pipelines); +typedef void (GLAD_API_PTR *PFNGLCREATEQUERIESPROC)(GLenum target, GLsizei n, GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLCREATERENDERBUFFERSPROC)(GLsizei n, GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLCREATESAMPLERSPROC)(GLsizei n, GLuint * samplers); +typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum type); +typedef GLhandleARB (GLAD_API_PTR *PFNGLCREATESHADEROBJECTARBPROC)(GLenum shaderType); +typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROGRAMVPROC)(GLenum type, GLsizei count, const GLchar *const* strings); +typedef void (GLAD_API_PTR *PFNGLCREATETEXTURESPROC)(GLenum target, GLsizei n, GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLCREATETRANSFORMFEEDBACKSPROC)(GLsizei n, GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLCREATEVERTEXARRAYSPROC)(GLsizei n, GLuint * arrays); +typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECALLBACKPROC)(GLDEBUGPROC callback, const void * userParam); +typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECALLBACKARBPROC)(GLDEBUGPROCARB callback, const void * userParam); +typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECONTROLPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled); +typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECONTROLARBPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled); +typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGEINSERTPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf); +typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGEINSERTARBPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf); +typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSARBPROC)(GLsizei n, const GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint * framebuffers); +typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSEXTPROC)(GLsizei n, const GLuint * framebuffers); +typedef void (GLAD_API_PTR *PFNGLDELETELISTSPROC)(GLuint list, GLsizei range); +typedef void (GLAD_API_PTR *PFNGLDELETEOBJECTARBPROC)(GLhandleARB obj); +typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPIPELINESPROC)(GLsizei n, const GLuint * pipelines); +typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMSARBPROC)(GLsizei n, const GLuint * programs); +typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESPROC)(GLsizei n, const GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSEXTPROC)(GLsizei n, const GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLDELETESAMPLERSPROC)(GLsizei count, const GLuint * samplers); +typedef void (GLAD_API_PTR *PFNGLDELETESHADERPROC)(GLuint shader); +typedef void (GLAD_API_PTR *PFNGLDELETESYNCPROC)(GLsync sync); +typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLDELETETRANSFORMFEEDBACKSPROC)(GLsizei n, const GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLDELETEVERTEXARRAYSPROC)(GLsizei n, const GLuint * arrays); +typedef void (GLAD_API_PTR *PFNGLDEPTHFUNCPROC)(GLenum func); +typedef void (GLAD_API_PTR *PFNGLDEPTHMASKPROC)(GLboolean flag); +typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEPROC)(GLdouble n, GLdouble f); +typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEARRAYVPROC)(GLuint first, GLsizei count, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEINDEXEDPROC)(GLuint index, GLdouble n, GLdouble f); +typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEFPROC)(GLfloat n, GLfloat f); +typedef void (GLAD_API_PTR *PFNGLDETACHOBJECTARBPROC)(GLhandleARB containerObj, GLhandleARB attachedObj); +typedef void (GLAD_API_PTR *PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader); +typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum cap); +typedef void (GLAD_API_PTR *PFNGLDISABLECLIENTSTATEPROC)(GLenum array); +typedef void (GLAD_API_PTR *PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC)(GLenum array, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLECLIENTSTATEIEXTPROC)(GLenum array, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEINDEXEDEXTPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXARRAYATTRIBPROC)(GLuint vaobj, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC)(GLuint vaobj, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXARRAYEXTPROC)(GLuint vaobj, GLenum array); +typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEIPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISPATCHCOMPUTEPROC)(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +typedef void (GLAD_API_PTR *PFNGLDISPATCHCOMPUTEINDIRECTPROC)(GLintptr indirect); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINDIRECTPROC)(GLenum mode, const void * indirect); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); +typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERPROC)(GLenum buf); +typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum * bufs); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINDIRECTPROC)(GLenum mode, GLenum type, const void * indirect); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLuint baseinstance); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); +typedef void (GLAD_API_PTR *PFNGLDRAWPIXELSPROC)(GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices); +typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex); +typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKPROC)(GLenum mode, GLuint id); +typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC)(GLenum mode, GLuint id, GLsizei instancecount); +typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC)(GLenum mode, GLuint id, GLuint stream); +typedef void (GLAD_API_PTR *PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC)(GLenum mode, GLuint id, GLuint stream, GLsizei instancecount); +typedef void (GLAD_API_PTR *PFNGLEDGEFLAGPROC)(GLboolean flag); +typedef void (GLAD_API_PTR *PFNGLEDGEFLAGPOINTERPROC)(GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLEDGEFLAGVPROC)(const GLboolean * flag); +typedef void (GLAD_API_PTR *PFNGLENABLEPROC)(GLenum cap); +typedef void (GLAD_API_PTR *PFNGLENABLECLIENTSTATEPROC)(GLenum array); +typedef void (GLAD_API_PTR *PFNGLENABLECLIENTSTATEINDEXEDEXTPROC)(GLenum array, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLECLIENTSTATEIEXTPROC)(GLenum array, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEINDEXEDEXTPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXARRAYATTRIBPROC)(GLuint vaobj, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXARRAYATTRIBEXTPROC)(GLuint vaobj, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXARRAYEXTPROC)(GLuint vaobj, GLenum array); +typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYARBPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEIPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENDPROC)(void); +typedef void (GLAD_API_PTR *PFNGLENDCONDITIONALRENDERPROC)(void); +typedef void (GLAD_API_PTR *PFNGLENDLISTPROC)(void); +typedef void (GLAD_API_PTR *PFNGLENDQUERYPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLENDQUERYINDEXEDPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKPROC)(void); +typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKEXTPROC)(void); +typedef void (GLAD_API_PTR *PFNGLEVALCOORD1DPROC)(GLdouble u); +typedef void (GLAD_API_PTR *PFNGLEVALCOORD1DVPROC)(const GLdouble * u); +typedef void (GLAD_API_PTR *PFNGLEVALCOORD1FPROC)(GLfloat u); +typedef void (GLAD_API_PTR *PFNGLEVALCOORD1FVPROC)(const GLfloat * u); +typedef void (GLAD_API_PTR *PFNGLEVALCOORD2DPROC)(GLdouble u, GLdouble v); +typedef void (GLAD_API_PTR *PFNGLEVALCOORD2DVPROC)(const GLdouble * u); +typedef void (GLAD_API_PTR *PFNGLEVALCOORD2FPROC)(GLfloat u, GLfloat v); +typedef void (GLAD_API_PTR *PFNGLEVALCOORD2FVPROC)(const GLfloat * u); +typedef void (GLAD_API_PTR *PFNGLEVALMESH1PROC)(GLenum mode, GLint i1, GLint i2); +typedef void (GLAD_API_PTR *PFNGLEVALMESH2PROC)(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2); +typedef void (GLAD_API_PTR *PFNGLEVALPOINT1PROC)(GLint i); +typedef void (GLAD_API_PTR *PFNGLEVALPOINT2PROC)(GLint i, GLint j); +typedef void (GLAD_API_PTR *PFNGLFEEDBACKBUFFERPROC)(GLsizei size, GLenum type, GLfloat * buffer); +typedef GLsync (GLAD_API_PTR *PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags); +typedef void (GLAD_API_PTR *PFNGLFINISHPROC)(void); +typedef void (GLAD_API_PTR *PFNGLFLUSHPROC)(void); +typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length); +typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC)(GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC)(GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (GLAD_API_PTR *PFNGLFOGCOORDPOINTERPROC)(GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLFOGCOORDDPROC)(GLdouble coord); +typedef void (GLAD_API_PTR *PFNGLFOGCOORDDVPROC)(const GLdouble * coord); +typedef void (GLAD_API_PTR *PFNGLFOGCOORDFPROC)(GLfloat coord); +typedef void (GLAD_API_PTR *PFNGLFOGCOORDFVPROC)(const GLfloat * coord); +typedef void (GLAD_API_PTR *PFNGLFOGFPROC)(GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLFOGFVPROC)(GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLFOGIPROC)(GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLFOGIVPROC)(GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC)(GLuint framebuffer, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC)(GLuint framebuffer, GLsizei n, const GLenum * bufs); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERPARAMETERIPROC)(GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERREADBUFFEREXTPROC)(GLuint framebuffer, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLFRUSTUMPROC)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei n, GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLGENBUFFERSARBPROC)(GLsizei n, GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers); +typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSEXTPROC)(GLsizei n, GLuint * framebuffers); +typedef GLuint (GLAD_API_PTR *PFNGLGENLISTSPROC)(GLsizei range); +typedef void (GLAD_API_PTR *PFNGLGENPROGRAMPIPELINESPROC)(GLsizei n, GLuint * pipelines); +typedef void (GLAD_API_PTR *PFNGLGENPROGRAMSARBPROC)(GLsizei n, GLuint * programs); +typedef void (GLAD_API_PTR *PFNGLGENQUERIESPROC)(GLsizei n, GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSEXTPROC)(GLsizei n, GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLGENSAMPLERSPROC)(GLsizei count, GLuint * samplers); +typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei n, GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLGENTRANSFORMFEEDBACKSPROC)(GLsizei n, GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint * arrays); +typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPEXTPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLGENERATEMULTITEXMIPMAPEXTPROC)(GLenum texunit, GLenum target); +typedef void (GLAD_API_PTR *PFNGLGENERATETEXTUREMIPMAPPROC)(GLuint texture); +typedef void (GLAD_API_PTR *PFNGLGENERATETEXTUREMIPMAPEXTPROC)(GLuint texture, GLenum target); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC)(GLuint program, GLuint bufferIndex, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBARBPROC)(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVESUBROUTINENAMEPROC)(GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC)(GLuint program, GLenum shadertype, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC)(GLuint program, GLenum shadertype, GLuint index, GLenum pname, GLint * values); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMARBPROC)(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei * length, GLint * size, GLenum * type, GLcharARB * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMNAMEPROC)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETATTACHEDOBJECTSARBPROC)(GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj); +typedef void (GLAD_API_PTR *PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders); +typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar * name); +typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONARBPROC)(GLhandleARB programObj, const GLcharARB * name); +typedef void (GLAD_API_PTR *PFNGLGETBOOLEANINDEXEDVEXTPROC)(GLenum target, GLuint index, GLboolean * data); +typedef void (GLAD_API_PTR *PFNGLGETBOOLEANI_VPROC)(GLenum target, GLuint index, GLboolean * data); +typedef void (GLAD_API_PTR *PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean * data); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum target, GLenum pname, GLint64 * params); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVARBPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, void ** params); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVARBPROC)(GLenum target, GLenum pname, void ** params); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, void * data); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERSUBDATAARBPROC)(GLenum target, GLintptrARB offset, GLsizeiptrARB size, void * data); +typedef void (GLAD_API_PTR *PFNGLGETCLIPPLANEPROC)(GLenum plane, GLdouble * equation); +typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC)(GLenum texunit, GLenum target, GLint lod, void * img); +typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level, void * img); +typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC)(GLuint texture, GLint level, GLsizei bufSize, void * pixels); +typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC)(GLuint texture, GLenum target, GLint lod, void * img); +typedef void (GLAD_API_PTR *PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void * pixels); +typedef GLuint (GLAD_API_PTR *PFNGLGETDEBUGMESSAGELOGPROC)(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog); +typedef GLuint (GLAD_API_PTR *PFNGLGETDEBUGMESSAGELOGARBPROC)(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog); +typedef void (GLAD_API_PTR *PFNGLGETDOUBLEINDEXEDVEXTPROC)(GLenum target, GLuint index, GLdouble * data); +typedef void (GLAD_API_PTR *PFNGLGETDOUBLEI_VPROC)(GLenum target, GLuint index, GLdouble * data); +typedef void (GLAD_API_PTR *PFNGLGETDOUBLEI_VEXTPROC)(GLenum pname, GLuint index, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETDOUBLEVPROC)(GLenum pname, GLdouble * data); +typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void); +typedef void (GLAD_API_PTR *PFNGLGETFLOATINDEXEDVEXTPROC)(GLenum target, GLuint index, GLfloat * data); +typedef void (GLAD_API_PTR *PFNGLGETFLOATI_VPROC)(GLenum target, GLuint index, GLfloat * data); +typedef void (GLAD_API_PTR *PFNGLGETFLOATI_VEXTPROC)(GLenum pname, GLuint index, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETFLOATVPROC)(GLenum pname, GLfloat * data); +typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATAINDEXPROC)(GLuint program, const GLchar * name); +typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATALOCATIONPROC)(GLuint program, const GLchar * name); +typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATALOCATIONEXTPROC)(GLuint program, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC)(GLuint framebuffer, GLenum pname, GLint * params); +typedef GLenum (GLAD_API_PTR *PFNGLGETGRAPHICSRESETSTATUSPROC)(void); +typedef GLhandleARB (GLAD_API_PTR *PFNGLGETHANDLEARBPROC)(GLenum pname); +typedef void (GLAD_API_PTR *PFNGLGETINFOLOGARBPROC)(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETINTEGER64I_VPROC)(GLenum target, GLuint index, GLint64 * data); +typedef void (GLAD_API_PTR *PFNGLGETINTEGER64VPROC)(GLenum pname, GLint64 * data); +typedef void (GLAD_API_PTR *PFNGLGETINTEGERINDEXEDVEXTPROC)(GLenum target, GLuint index, GLint * data); +typedef void (GLAD_API_PTR *PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint * data); +typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum pname, GLint * data); +typedef void (GLAD_API_PTR *PFNGLGETINTERNALFORMATI64VPROC)(GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint64 * params); +typedef void (GLAD_API_PTR *PFNGLGETINTERNALFORMATIVPROC)(GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETLIGHTFVPROC)(GLenum light, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETLIGHTIVPROC)(GLenum light, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMAPDVPROC)(GLenum target, GLenum query, GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLGETMAPFVPROC)(GLenum target, GLenum query, GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLGETMAPIVPROC)(GLenum target, GLenum query, GLint * v); +typedef void (GLAD_API_PTR *PFNGLGETMATERIALFVPROC)(GLenum face, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETMATERIALIVPROC)(GLenum face, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXENVFVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXENVIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXGENDVEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXGENFVEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXGENIVEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXIMAGEEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, void * pixels); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC)(GLenum texunit, GLenum target, GLint level, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXPARAMETERIIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXPARAMETERIUIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXPARAMETERFVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTITEXPARAMETERIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat * val); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERPARAMETERI64VPROC)(GLuint buffer, GLenum pname, GLint64 * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERPARAMETERIVPROC)(GLuint buffer, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC)(GLuint buffer, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERPOINTERVPROC)(GLuint buffer, GLenum pname, void ** params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERPOINTERVEXTPROC)(GLuint buffer, GLenum pname, void ** params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERSUBDATAPROC)(GLuint buffer, GLintptr offset, GLsizeiptr size, void * data); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDBUFFERSUBDATAEXTPROC)(GLuint buffer, GLintptr offset, GLsizeiptr size, void * data); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLuint framebuffer, GLenum attachment, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)(GLuint framebuffer, GLenum attachment, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC)(GLuint framebuffer, GLenum pname, GLint * param); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC)(GLuint framebuffer, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC)(GLuint program, GLenum target, GLuint index, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC)(GLuint program, GLenum target, GLuint index, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC)(GLuint program, GLenum target, GLuint index, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC)(GLuint program, GLenum target, GLuint index, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDPROGRAMSTRINGEXTPROC)(GLuint program, GLenum target, GLenum pname, void * string); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDPROGRAMIVEXTPROC)(GLuint program, GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC)(GLuint renderbuffer, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC)(GLuint renderbuffer, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETOBJECTLABELPROC)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei * length, GLchar * label); +typedef void (GLAD_API_PTR *PFNGLGETOBJECTPARAMETERFVARBPROC)(GLhandleARB obj, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETOBJECTPARAMETERIVARBPROC)(GLhandleARB obj, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETOBJECTPTRLABELPROC)(const void * ptr, GLsizei bufSize, GLsizei * length, GLchar * label); +typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPFVPROC)(GLenum map, GLfloat * values); +typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPUIVPROC)(GLenum map, GLuint * values); +typedef void (GLAD_API_PTR *PFNGLGETPIXELMAPUSVPROC)(GLenum map, GLushort * values); +typedef void (GLAD_API_PTR *PFNGLGETPOINTERINDEXEDVEXTPROC)(GLenum target, GLuint index, void ** data); +typedef void (GLAD_API_PTR *PFNGLGETPOINTERI_VEXTPROC)(GLenum pname, GLuint index, void ** params); +typedef void (GLAD_API_PTR *PFNGLGETPOINTERVPROC)(GLenum pname, void ** params); +typedef void (GLAD_API_PTR *PFNGLGETPOLYGONSTIPPLEPROC)(GLubyte * mask); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMBINARYPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMENVPARAMETERDVARBPROC)(GLenum target, GLuint index, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMENVPARAMETERFVARBPROC)(GLenum target, GLuint index, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINTERFACEIVPROC)(GLuint program, GLenum programInterface, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC)(GLenum target, GLuint index, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC)(GLenum target, GLuint index, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMPIPELINEINFOLOGPROC)(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMPIPELINEIVPROC)(GLuint pipeline, GLenum pname, GLint * params); +typedef GLuint (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCEINDEXPROC)(GLuint program, GLenum programInterface, const GLchar * name); +typedef GLint (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCELOCATIONPROC)(GLuint program, GLenum programInterface, const GLchar * name); +typedef GLint (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC)(GLuint program, GLenum programInterface, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCENAMEPROC)(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCEIVPROC)(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei count, GLsizei * length, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMSTAGEIVPROC)(GLuint program, GLenum shadertype, GLenum pname, GLint * values); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMSTRINGARBPROC)(GLenum target, GLenum pname, void * string); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVARBPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYBUFFEROBJECTI64VPROC)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLGETQUERYBUFFEROBJECTIVPROC)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLGETQUERYBUFFEROBJECTUI64VPROC)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLGETQUERYBUFFEROBJECTUIVPROC)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLGETQUERYINDEXEDIVPROC)(GLenum target, GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTI64VPROC)(GLuint id, GLenum pname, GLint64 * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTIVPROC)(GLuint id, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUI64VPROC)(GLuint id, GLenum pname, GLuint64 * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVPROC)(GLuint id, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETSHADERPRECISIONFORMATPROC)(GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision); +typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source); +typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEARBPROC)(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * source); +typedef void (GLAD_API_PTR *PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint * params); +typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGPROC)(GLenum name); +typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGIPROC)(GLenum name, GLuint index); +typedef GLuint (GLAD_API_PTR *PFNGLGETSUBROUTINEINDEXPROC)(GLuint program, GLenum shadertype, const GLchar * name); +typedef GLint (GLAD_API_PTR *PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC)(GLuint program, GLenum shadertype, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei count, GLsizei * length, GLint * values); +typedef void (GLAD_API_PTR *PFNGLGETTEXENVFVPROC)(GLenum target, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXENVIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXGENDVPROC)(GLenum coord, GLenum pname, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXGENFVPROC)(GLenum coord, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXGENIVPROC)(GLenum coord, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, void * pixels); +typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum target, GLint level, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum target, GLint level, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVEXTPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVEXTPROC)(GLenum target, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREIMAGEPROC)(GLuint texture, GLint level, GLenum format, GLenum type, GLsizei bufSize, void * pixels); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREIMAGEEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, void * pixels); +typedef void (GLAD_API_PTR *PFNGLGETTEXTURELEVELPARAMETERFVPROC)(GLuint texture, GLint level, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTURELEVELPARAMETERIVPROC)(GLuint texture, GLint level, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC)(GLuint texture, GLenum target, GLint level, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERIIVPROC)(GLuint texture, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERIIVEXTPROC)(GLuint texture, GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERIUIVPROC)(GLuint texture, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERIUIVEXTPROC)(GLuint texture, GLenum target, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERFVPROC)(GLuint texture, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERFVEXTPROC)(GLuint texture, GLenum target, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERIVPROC)(GLuint texture, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTUREPARAMETERIVEXTPROC)(GLuint texture, GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXTURESUBIMAGEPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void * pixels); +typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKI64_VPROC)(GLuint xfb, GLenum pname, GLuint index, GLint64 * param); +typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKI_VPROC)(GLuint xfb, GLenum pname, GLuint index, GLint * param); +typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKIVPROC)(GLuint xfb, GLenum pname, GLint * param); +typedef GLuint (GLAD_API_PTR *PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar * uniformBlockName); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMINDICESPROC)(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices); +typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar * name); +typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONARBPROC)(GLhandleARB programObj, const GLcharARB * name); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMSUBROUTINEUIVPROC)(GLenum shadertype, GLint location, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMDVPROC)(GLuint program, GLint location, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVARBPROC)(GLhandleARB programObj, GLint location, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVARBPROC)(GLhandleARB programObj, GLint location, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUIVEXTPROC)(GLuint program, GLint location, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYINDEXED64IVPROC)(GLuint vaobj, GLuint index, GLenum pname, GLint64 * param); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYINDEXEDIVPROC)(GLuint vaobj, GLuint index, GLenum pname, GLint * param); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC)(GLuint vaobj, GLuint index, GLenum pname, GLint * param); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYINTEGERVEXTPROC)(GLuint vaobj, GLenum pname, GLint * param); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC)(GLuint vaobj, GLuint index, GLenum pname, void ** param); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYPOINTERVEXTPROC)(GLuint vaobj, GLenum pname, void ** param); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXARRAYIVPROC)(GLuint vaobj, GLenum pname, GLint * param); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIIVEXTPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIUIVEXTPROC)(GLuint index, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBLDVPROC)(GLuint index, GLenum pname, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void ** pointer); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVARBPROC)(GLuint index, GLenum pname, void ** pointer); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVPROC)(GLuint index, GLenum pname, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVARBPROC)(GLuint index, GLenum pname, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVARBPROC)(GLuint index, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVARBPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNCOLORTABLEPROC)(GLenum target, GLenum format, GLenum type, GLsizei bufSize, void * table); +typedef void (GLAD_API_PTR *PFNGLGETNCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint lod, GLsizei bufSize, void * pixels); +typedef void (GLAD_API_PTR *PFNGLGETNCONVOLUTIONFILTERPROC)(GLenum target, GLenum format, GLenum type, GLsizei bufSize, void * image); +typedef void (GLAD_API_PTR *PFNGLGETNHISTOGRAMPROC)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void * values); +typedef void (GLAD_API_PTR *PFNGLGETNMAPDVPROC)(GLenum target, GLenum query, GLsizei bufSize, GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLGETNMAPFVPROC)(GLenum target, GLenum query, GLsizei bufSize, GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLGETNMAPIVPROC)(GLenum target, GLenum query, GLsizei bufSize, GLint * v); +typedef void (GLAD_API_PTR *PFNGLGETNMINMAXPROC)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void * values); +typedef void (GLAD_API_PTR *PFNGLGETNPIXELMAPFVPROC)(GLenum map, GLsizei bufSize, GLfloat * values); +typedef void (GLAD_API_PTR *PFNGLGETNPIXELMAPUIVPROC)(GLenum map, GLsizei bufSize, GLuint * values); +typedef void (GLAD_API_PTR *PFNGLGETNPIXELMAPUSVPROC)(GLenum map, GLsizei bufSize, GLushort * values); +typedef void (GLAD_API_PTR *PFNGLGETNPOLYGONSTIPPLEPROC)(GLsizei bufSize, GLubyte * pattern); +typedef void (GLAD_API_PTR *PFNGLGETNSEPARABLEFILTERPROC)(GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void * row, GLsizei columnBufSize, void * column, void * span); +typedef void (GLAD_API_PTR *PFNGLGETNTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void * pixels); +typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMDVPROC)(GLuint program, GLint location, GLsizei bufSize, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMFVPROC)(GLuint program, GLint location, GLsizei bufSize, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMIVPROC)(GLuint program, GLint location, GLsizei bufSize, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMUIVPROC)(GLuint program, GLint location, GLsizei bufSize, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum target, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLINDEXMASKPROC)(GLuint mask); +typedef void (GLAD_API_PTR *PFNGLINDEXPOINTERPROC)(GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLINDEXDPROC)(GLdouble c); +typedef void (GLAD_API_PTR *PFNGLINDEXDVPROC)(const GLdouble * c); +typedef void (GLAD_API_PTR *PFNGLINDEXFPROC)(GLfloat c); +typedef void (GLAD_API_PTR *PFNGLINDEXFVPROC)(const GLfloat * c); +typedef void (GLAD_API_PTR *PFNGLINDEXIPROC)(GLint c); +typedef void (GLAD_API_PTR *PFNGLINDEXIVPROC)(const GLint * c); +typedef void (GLAD_API_PTR *PFNGLINDEXSPROC)(GLshort c); +typedef void (GLAD_API_PTR *PFNGLINDEXSVPROC)(const GLshort * c); +typedef void (GLAD_API_PTR *PFNGLINDEXUBPROC)(GLubyte c); +typedef void (GLAD_API_PTR *PFNGLINDEXUBVPROC)(const GLubyte * c); +typedef void (GLAD_API_PTR *PFNGLINITNAMESPROC)(void); +typedef void (GLAD_API_PTR *PFNGLINTERLEAVEDARRAYSPROC)(GLenum format, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLINVALIDATEBUFFERSUBDATAPROC)(GLuint buffer, GLintptr offset, GLsizeiptr length); +typedef void (GLAD_API_PTR *PFNGLINVALIDATEFRAMEBUFFERPROC)(GLenum target, GLsizei numAttachments, const GLenum * attachments); +typedef void (GLAD_API_PTR *PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC)(GLuint framebuffer, GLsizei numAttachments, const GLenum * attachments); +typedef void (GLAD_API_PTR *PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC)(GLuint framebuffer, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLINVALIDATESUBFRAMEBUFFERPROC)(GLenum target, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLINVALIDATETEXIMAGEPROC)(GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLINVALIDATETEXSUBIMAGEPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); +typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint buffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERARBPROC)(GLuint buffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum cap); +typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDINDEXEDEXTPROC)(GLenum target, GLuint index); +typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIPROC)(GLenum target, GLuint index); +typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFEREXTPROC)(GLuint framebuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISLISTPROC)(GLuint list); +typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint program); +typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMARBPROC)(GLuint program); +typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPIPELINEPROC)(GLuint pipeline); +typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYPROC)(GLuint id); +typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFEREXTPROC)(GLuint renderbuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISSAMPLERPROC)(GLuint sampler); +typedef GLboolean (GLAD_API_PTR *PFNGLISSHADERPROC)(GLuint shader); +typedef GLboolean (GLAD_API_PTR *PFNGLISSYNCPROC)(GLsync sync); +typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREPROC)(GLuint texture); +typedef GLboolean (GLAD_API_PTR *PFNGLISTRANSFORMFEEDBACKPROC)(GLuint id); +typedef GLboolean (GLAD_API_PTR *PFNGLISVERTEXARRAYPROC)(GLuint array); +typedef void (GLAD_API_PTR *PFNGLLIGHTMODELFPROC)(GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLLIGHTMODELFVPROC)(GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLLIGHTMODELIPROC)(GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLLIGHTMODELIVPROC)(GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLLIGHTFPROC)(GLenum light, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLLIGHTFVPROC)(GLenum light, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLLIGHTIPROC)(GLenum light, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLLIGHTIVPROC)(GLenum light, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLLINESTIPPLEPROC)(GLint factor, GLushort pattern); +typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat width); +typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMARBPROC)(GLhandleARB programObj); +typedef void (GLAD_API_PTR *PFNGLLISTBASEPROC)(GLuint base); +typedef void (GLAD_API_PTR *PFNGLLOADIDENTITYPROC)(void); +typedef void (GLAD_API_PTR *PFNGLLOADMATRIXDPROC)(const GLdouble * m); +typedef void (GLAD_API_PTR *PFNGLLOADMATRIXFPROC)(const GLfloat * m); +typedef void (GLAD_API_PTR *PFNGLLOADNAMEPROC)(GLuint name); +typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXDPROC)(const GLdouble * m); +typedef void (GLAD_API_PTR *PFNGLLOADTRANSPOSEMATRIXFPROC)(const GLfloat * m); +typedef void (GLAD_API_PTR *PFNGLLOGICOPPROC)(GLenum opcode); +typedef void (GLAD_API_PTR *PFNGLMAP1DPROC)(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble * points); +typedef void (GLAD_API_PTR *PFNGLMAP1FPROC)(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat * points); +typedef void (GLAD_API_PTR *PFNGLMAP2DPROC)(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble * points); +typedef void (GLAD_API_PTR *PFNGLMAP2FPROC)(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat * points); +typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERPROC)(GLenum target, GLenum access); +typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERARBPROC)(GLenum target, GLenum access); +typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GLAD_API_PTR *PFNGLMAPGRID1DPROC)(GLint un, GLdouble u1, GLdouble u2); +typedef void (GLAD_API_PTR *PFNGLMAPGRID1FPROC)(GLint un, GLfloat u1, GLfloat u2); +typedef void (GLAD_API_PTR *PFNGLMAPGRID2DPROC)(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2); +typedef void (GLAD_API_PTR *PFNGLMAPGRID2FPROC)(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2); +typedef void * (GLAD_API_PTR *PFNGLMAPNAMEDBUFFERPROC)(GLuint buffer, GLenum access); +typedef void * (GLAD_API_PTR *PFNGLMAPNAMEDBUFFEREXTPROC)(GLuint buffer, GLenum access); +typedef void * (GLAD_API_PTR *PFNGLMAPNAMEDBUFFERRANGEPROC)(GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void * (GLAD_API_PTR *PFNGLMAPNAMEDBUFFERRANGEEXTPROC)(GLuint buffer, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GLAD_API_PTR *PFNGLMATERIALFPROC)(GLenum face, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLMATERIALFVPROC)(GLenum face, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLMATERIALIPROC)(GLenum face, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLMATERIALIVPROC)(GLenum face, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLMATRIXFRUSTUMEXTPROC)(GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (GLAD_API_PTR *PFNGLMATRIXLOADIDENTITYEXTPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLMATRIXLOADTRANSPOSEDEXTPROC)(GLenum mode, const GLdouble * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXLOADTRANSPOSEFEXTPROC)(GLenum mode, const GLfloat * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXLOADDEXTPROC)(GLenum mode, const GLdouble * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXLOADFEXTPROC)(GLenum mode, const GLfloat * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXMODEPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLMATRIXMULTTRANSPOSEDEXTPROC)(GLenum mode, const GLdouble * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXMULTTRANSPOSEFEXTPROC)(GLenum mode, const GLfloat * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXMULTDEXTPROC)(GLenum mode, const GLdouble * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXMULTFEXTPROC)(GLenum mode, const GLfloat * m); +typedef void (GLAD_API_PTR *PFNGLMATRIXORTHOEXTPROC)(GLenum mode, GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (GLAD_API_PTR *PFNGLMATRIXPOPEXTPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLMATRIXPUSHEXTPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLMATRIXROTATEDEXTPROC)(GLenum mode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLMATRIXROTATEFEXTPROC)(GLenum mode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLMATRIXSCALEDEXTPROC)(GLenum mode, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLMATRIXSCALEFEXTPROC)(GLenum mode, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLMATRIXTRANSLATEDEXTPROC)(GLenum mode, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLMATRIXTRANSLATEFEXTPROC)(GLenum mode, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLMEMORYBARRIERPROC)(GLbitfield barriers); +typedef void (GLAD_API_PTR *PFNGLMEMORYBARRIERBYREGIONPROC)(GLbitfield barriers); +typedef void (GLAD_API_PTR *PFNGLMEMORYBARRIEREXTPROC)(GLbitfield barriers); +typedef void (GLAD_API_PTR *PFNGLMINSAMPLESHADINGPROC)(GLfloat value); +typedef void (GLAD_API_PTR *PFNGLMULTMATRIXDPROC)(const GLdouble * m); +typedef void (GLAD_API_PTR *PFNGLMULTMATRIXFPROC)(const GLfloat * m); +typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXDPROC)(const GLdouble * m); +typedef void (GLAD_API_PTR *PFNGLMULTTRANSPOSEMATRIXFPROC)(const GLfloat * m); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSPROC)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSINDIRECTPROC)(GLenum mode, const void * indirect, GLsizei drawcount, GLsizei stride); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC)(GLenum mode, const void * indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount, const GLint * basevertex); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSINDIRECTPROC)(GLenum mode, GLenum type, const void * indirect, GLsizei drawcount, GLsizei stride); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC)(GLenum mode, GLenum type, const void * indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride); +typedef void (GLAD_API_PTR *PFNGLMULTITEXBUFFEREXTPROC)(GLenum texunit, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DPROC)(GLenum target, GLdouble s); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1DVPROC)(GLenum target, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FPROC)(GLenum target, GLfloat s); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1FVPROC)(GLenum target, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IPROC)(GLenum target, GLint s); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1IVPROC)(GLenum target, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SPROC)(GLenum target, GLshort s); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD1SVPROC)(GLenum target, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DPROC)(GLenum target, GLdouble s, GLdouble t); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2DVPROC)(GLenum target, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FPROC)(GLenum target, GLfloat s, GLfloat t); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2FVPROC)(GLenum target, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IPROC)(GLenum target, GLint s, GLint t); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2IVPROC)(GLenum target, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SPROC)(GLenum target, GLshort s, GLshort t); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD2SVPROC)(GLenum target, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3DVPROC)(GLenum target, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3FVPROC)(GLenum target, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IPROC)(GLenum target, GLint s, GLint t, GLint r); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3IVPROC)(GLenum target, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SPROC)(GLenum target, GLshort s, GLshort t, GLshort r); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD3SVPROC)(GLenum target, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DPROC)(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4DVPROC)(GLenum target, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FPROC)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4FVPROC)(GLenum target, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IPROC)(GLenum target, GLint s, GLint t, GLint r, GLint q); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4IVPROC)(GLenum target, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SPROC)(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORD4SVPROC)(GLenum target, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP1UIPROC)(GLenum texture, GLenum type, GLuint coords); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP1UIVPROC)(GLenum texture, GLenum type, const GLuint * coords); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP2UIPROC)(GLenum texture, GLenum type, GLuint coords); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP2UIVPROC)(GLenum texture, GLenum type, const GLuint * coords); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP3UIPROC)(GLenum texture, GLenum type, GLuint coords); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP3UIVPROC)(GLenum texture, GLenum type, const GLuint * coords); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP4UIPROC)(GLenum texture, GLenum type, GLuint coords); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDP4UIVPROC)(GLenum texture, GLenum type, const GLuint * coords); +typedef void (GLAD_API_PTR *PFNGLMULTITEXCOORDPOINTEREXTPROC)(GLenum texunit, GLint size, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLMULTITEXENVFEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXENVFVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXENVIEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXENVIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXGENDEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, GLdouble param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXGENDVEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, const GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXGENFEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXGENFVEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXGENIEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXGENIVEXTPROC)(GLenum texunit, GLenum coord, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXIMAGE1DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLMULTITEXIMAGE2DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLMULTITEXIMAGE3DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLMULTITEXPARAMETERIIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXPARAMETERIUIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXPARAMETERFEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXPARAMETERFVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXPARAMETERIEXTPROC)(GLenum texunit, GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLMULTITEXPARAMETERIVEXTPROC)(GLenum texunit, GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLMULTITEXRENDERBUFFEREXTPROC)(GLenum texunit, GLenum target, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLMULTITEXSUBIMAGE1DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLMULTITEXSUBIMAGE2DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLMULTITEXSUBIMAGE3DEXTPROC)(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERDATAPROC)(GLuint buffer, GLsizeiptr size, const void * data, GLenum usage); +typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERDATAEXTPROC)(GLuint buffer, GLsizeiptr size, const void * data, GLenum usage); +typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERSTORAGEPROC)(GLuint buffer, GLsizeiptr size, const void * data, GLbitfield flags); +typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERSTORAGEEXTPROC)(GLuint buffer, GLsizeiptr size, const void * data, GLbitfield flags); +typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERSUBDATAPROC)(GLuint buffer, GLintptr offset, GLsizeiptr size, const void * data); +typedef void (GLAD_API_PTR *PFNGLNAMEDBUFFERSUBDATAEXTPROC)(GLuint buffer, GLintptr offset, GLsizeiptr size, const void * data); +typedef void (GLAD_API_PTR *PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC)(GLuint readBuffer, GLuint writeBuffer, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC)(GLuint framebuffer, GLenum buf); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC)(GLuint framebuffer, GLsizei n, const GLenum * bufs); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC)(GLuint framebuffer, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC)(GLuint framebuffer, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC)(GLuint framebuffer, GLenum src); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC)(GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC)(GLuint framebuffer, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTUREPROC)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC)(GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC)(GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC)(GLuint framebuffer, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLenum face); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAD_API_PTR *PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC)(GLuint framebuffer, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC)(GLuint program, GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC)(GLuint program, GLenum target, GLuint index, const GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC)(GLuint program, GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC)(GLuint program, GLenum target, GLuint index, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC)(GLuint program, GLenum target, GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC)(GLuint program, GLenum target, GLuint index, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC)(GLuint program, GLenum target, GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC)(GLuint program, GLenum target, GLuint index, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC)(GLuint program, GLenum target, GLuint index, GLsizei count, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC)(GLuint program, GLenum target, GLuint index, GLsizei count, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC)(GLuint program, GLenum target, GLuint index, GLsizei count, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLNAMEDPROGRAMSTRINGEXTPROC)(GLuint program, GLenum target, GLenum format, GLsizei len, const void * string); +typedef void (GLAD_API_PTR *PFNGLNAMEDRENDERBUFFERSTORAGEPROC)(GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC)(GLuint renderbuffer, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC)(GLuint renderbuffer, GLsizei coverageSamples, GLsizei colorSamples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)(GLuint renderbuffer, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLNEWLISTPROC)(GLuint list, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLNORMAL3BPROC)(GLbyte nx, GLbyte ny, GLbyte nz); +typedef void (GLAD_API_PTR *PFNGLNORMAL3BVPROC)(const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLNORMAL3DPROC)(GLdouble nx, GLdouble ny, GLdouble nz); +typedef void (GLAD_API_PTR *PFNGLNORMAL3DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLNORMAL3FPROC)(GLfloat nx, GLfloat ny, GLfloat nz); +typedef void (GLAD_API_PTR *PFNGLNORMAL3FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLNORMAL3IPROC)(GLint nx, GLint ny, GLint nz); +typedef void (GLAD_API_PTR *PFNGLNORMAL3IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLNORMAL3SPROC)(GLshort nx, GLshort ny, GLshort nz); +typedef void (GLAD_API_PTR *PFNGLNORMAL3SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLNORMALP3UIPROC)(GLenum type, GLuint coords); +typedef void (GLAD_API_PTR *PFNGLNORMALP3UIVPROC)(GLenum type, const GLuint * coords); +typedef void (GLAD_API_PTR *PFNGLNORMALPOINTERPROC)(GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLOBJECTLABELPROC)(GLenum identifier, GLuint name, GLsizei length, const GLchar * label); +typedef void (GLAD_API_PTR *PFNGLOBJECTPTRLABELPROC)(const void * ptr, GLsizei length, const GLchar * label); +typedef void (GLAD_API_PTR *PFNGLORTHOPROC)(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar); +typedef void (GLAD_API_PTR *PFNGLPASSTHROUGHPROC)(GLfloat token); +typedef void (GLAD_API_PTR *PFNGLPATCHPARAMETERFVPROC)(GLenum pname, const GLfloat * values); +typedef void (GLAD_API_PTR *PFNGLPATCHPARAMETERIPROC)(GLenum pname, GLint value); +typedef void (GLAD_API_PTR *PFNGLPAUSETRANSFORMFEEDBACKPROC)(void); +typedef void (GLAD_API_PTR *PFNGLPIXELMAPFVPROC)(GLenum map, GLsizei mapsize, const GLfloat * values); +typedef void (GLAD_API_PTR *PFNGLPIXELMAPUIVPROC)(GLenum map, GLsizei mapsize, const GLuint * values); +typedef void (GLAD_API_PTR *PFNGLPIXELMAPUSVPROC)(GLenum map, GLsizei mapsize, const GLushort * values); +typedef void (GLAD_API_PTR *PFNGLPIXELSTOREFPROC)(GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLPIXELTRANSFERFPROC)(GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLPIXELTRANSFERIPROC)(GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLPIXELZOOMPROC)(GLfloat xfactor, GLfloat yfactor); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFPROC)(GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERFVPROC)(GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIPROC)(GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLPOINTPARAMETERIVPROC)(GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLPOINTSIZEPROC)(GLfloat size); +typedef void (GLAD_API_PTR *PFNGLPOLYGONMODEPROC)(GLenum face, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units); +typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETCLAMPPROC)(GLfloat factor, GLfloat units, GLfloat clamp); +typedef void (GLAD_API_PTR *PFNGLPOLYGONSTIPPLEPROC)(const GLubyte * mask); +typedef void (GLAD_API_PTR *PFNGLPOPATTRIBPROC)(void); +typedef void (GLAD_API_PTR *PFNGLPOPCLIENTATTRIBPROC)(void); +typedef void (GLAD_API_PTR *PFNGLPOPDEBUGGROUPPROC)(void); +typedef void (GLAD_API_PTR *PFNGLPOPMATRIXPROC)(void); +typedef void (GLAD_API_PTR *PFNGLPOPNAMEPROC)(void); +typedef void (GLAD_API_PTR *PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLPRIORITIZETEXTURESPROC)(GLsizei n, const GLuint * textures, const GLfloat * priorities); +typedef void (GLAD_API_PTR *PFNGLPROGRAMBINARYPROC)(GLuint program, GLenum binaryFormat, const void * binary, GLsizei length); +typedef void (GLAD_API_PTR *PFNGLPROGRAMENVPARAMETER4DARBPROC)(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLPROGRAMENVPARAMETER4DVARBPROC)(GLenum target, GLuint index, const GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLPROGRAMENVPARAMETER4FARBPROC)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLPROGRAMENVPARAMETER4FVARBPROC)(GLenum target, GLuint index, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLPROGRAMLOCALPARAMETER4DARBPROC)(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLPROGRAMLOCALPARAMETER4DVARBPROC)(GLenum target, GLuint index, const GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLPROGRAMLOCALPARAMETER4FARBPROC)(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)(GLenum target, GLuint index, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETERIPROC)(GLuint program, GLenum pname, GLint value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETERIEXTPROC)(GLuint program, GLenum pname, GLint value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMSTRINGARBPROC)(GLenum target, GLenum format, GLsizei len, const void * string); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1DPROC)(GLuint program, GLint location, GLdouble v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1DEXTPROC)(GLuint program, GLint location, GLdouble x); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1DVPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1DVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FPROC)(GLuint program, GLint location, GLfloat v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FEXTPROC)(GLuint program, GLint location, GLfloat v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FVPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IPROC)(GLuint program, GLint location, GLint v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IEXTPROC)(GLuint program, GLint location, GLint v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IVPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIPROC)(GLuint program, GLint location, GLuint v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIEXTPROC)(GLuint program, GLint location, GLuint v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIVPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2DPROC)(GLuint program, GLint location, GLdouble v0, GLdouble v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2DEXTPROC)(GLuint program, GLint location, GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2DVPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2DVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FEXTPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FVPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IPROC)(GLuint program, GLint location, GLint v0, GLint v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IEXTPROC)(GLuint program, GLint location, GLint v0, GLint v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IVPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIPROC)(GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIEXTPROC)(GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIVPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3DPROC)(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3DEXTPROC)(GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3DVPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3DVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FEXTPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FVPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IEXTPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IVPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIEXTPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIVPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4DPROC)(GLuint program, GLint location, GLdouble v0, GLdouble v1, GLdouble v2, GLdouble v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4DEXTPROC)(GLuint program, GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4DVPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4DVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FEXTPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FVPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IEXTPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IVPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIEXTPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIVPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIVEXTPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROVOKINGVERTEXPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLPUSHATTRIBPROC)(GLbitfield mask); +typedef void (GLAD_API_PTR *PFNGLPUSHCLIENTATTRIBPROC)(GLbitfield mask); +typedef void (GLAD_API_PTR *PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC)(GLbitfield mask); +typedef void (GLAD_API_PTR *PFNGLPUSHDEBUGGROUPPROC)(GLenum source, GLuint id, GLsizei length, const GLchar * message); +typedef void (GLAD_API_PTR *PFNGLPUSHMATRIXPROC)(void); +typedef void (GLAD_API_PTR *PFNGLPUSHNAMEPROC)(GLuint name); +typedef void (GLAD_API_PTR *PFNGLQUERYCOUNTERPROC)(GLuint id, GLenum target); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS2DPROC)(GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS2DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS2FPROC)(GLfloat x, GLfloat y); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS2FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS2IPROC)(GLint x, GLint y); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS2IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS2SPROC)(GLshort x, GLshort y); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS2SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS3DPROC)(GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS3DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS3FPROC)(GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS3FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS3IPROC)(GLint x, GLint y, GLint z); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS3IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS3SPROC)(GLshort x, GLshort y, GLshort z); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS3SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS4DPROC)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS4DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS4FPROC)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS4FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS4IPROC)(GLint x, GLint y, GLint z, GLint w); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS4IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS4SPROC)(GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAD_API_PTR *PFNGLRASTERPOS4SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLREADBUFFERPROC)(GLenum src); +typedef void (GLAD_API_PTR *PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels); +typedef void (GLAD_API_PTR *PFNGLREADNPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data); +typedef void (GLAD_API_PTR *PFNGLRECTDPROC)(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2); +typedef void (GLAD_API_PTR *PFNGLRECTDVPROC)(const GLdouble * v1, const GLdouble * v2); +typedef void (GLAD_API_PTR *PFNGLRECTFPROC)(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2); +typedef void (GLAD_API_PTR *PFNGLRECTFVPROC)(const GLfloat * v1, const GLfloat * v2); +typedef void (GLAD_API_PTR *PFNGLRECTIPROC)(GLint x1, GLint y1, GLint x2, GLint y2); +typedef void (GLAD_API_PTR *PFNGLRECTIVPROC)(const GLint * v1, const GLint * v2); +typedef void (GLAD_API_PTR *PFNGLRECTSPROC)(GLshort x1, GLshort y1, GLshort x2, GLshort y2); +typedef void (GLAD_API_PTR *PFNGLRECTSVPROC)(const GLshort * v1, const GLshort * v2); +typedef void (GLAD_API_PTR *PFNGLRELEASESHADERCOMPILERPROC)(void); +typedef GLint (GLAD_API_PTR *PFNGLRENDERMODEPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEEXTPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLRESUMETRANSFORMFEEDBACKPROC)(void); +typedef void (GLAD_API_PTR *PFNGLROTATEDPROC)(GLdouble angle, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLROTATEFPROC)(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert); +typedef void (GLAD_API_PTR *PFNGLSAMPLEMASKIPROC)(GLuint maskNumber, GLbitfield mask); +typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, const GLint * param); +typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, const GLuint * param); +typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFPROC)(GLuint sampler, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, const GLfloat * param); +typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIPROC)(GLuint sampler, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, const GLint * param); +typedef void (GLAD_API_PTR *PFNGLSCALEDPROC)(GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLSCALEFPROC)(GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLSCISSORARRAYVPROC)(GLuint first, GLsizei count, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLSCISSORINDEXEDPROC)(GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLSCISSORINDEXEDVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3BPROC)(GLbyte red, GLbyte green, GLbyte blue); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3BVPROC)(const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3DPROC)(GLdouble red, GLdouble green, GLdouble blue); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3FPROC)(GLfloat red, GLfloat green, GLfloat blue); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3IPROC)(GLint red, GLint green, GLint blue); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3SPROC)(GLshort red, GLshort green, GLshort blue); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UBPROC)(GLubyte red, GLubyte green, GLubyte blue); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UBVPROC)(const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UIPROC)(GLuint red, GLuint green, GLuint blue); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3UIVPROC)(const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3USPROC)(GLushort red, GLushort green, GLushort blue); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLOR3USVPROC)(const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORP3UIPROC)(GLenum type, GLuint color); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORP3UIVPROC)(GLenum type, const GLuint * color); +typedef void (GLAD_API_PTR *PFNGLSECONDARYCOLORPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLSELECTBUFFERPROC)(GLsizei size, GLuint * buffer); +typedef void (GLAD_API_PTR *PFNGLSHADEMODELPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLSHADERBINARYPROC)(GLsizei count, const GLuint * shaders, GLenum binaryFormat, const void * binary, GLsizei length); +typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length); +typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEARBPROC)(GLhandleARB shaderObj, GLsizei count, const GLcharARB ** string, const GLint * length); +typedef void (GLAD_API_PTR *PFNGLSHADERSTORAGEBLOCKBINDINGPROC)(GLuint program, GLuint storageBlockIndex, GLuint storageBlockBinding); +typedef void (GLAD_API_PTR *PFNGLSPECIALIZESHADERPROC)(GLuint shader, const GLchar * pEntryPoint, GLuint numSpecializationConstants, const GLuint * pConstantIndex, const GLuint * pConstantValue); +typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILMASKPROC)(GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass); +typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GLAD_API_PTR *PFNGLSUBPIXELPRECISIONBIASNVPROC)(GLuint xbits, GLuint ybits); +typedef void (GLAD_API_PTR *PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLTEXBUFFERRANGEPROC)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD1DPROC)(GLdouble s); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD1DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD1FPROC)(GLfloat s); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD1FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD1IPROC)(GLint s); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD1IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD1SPROC)(GLshort s); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD1SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD2DPROC)(GLdouble s, GLdouble t); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD2DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD2FPROC)(GLfloat s, GLfloat t); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD2FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD2IPROC)(GLint s, GLint t); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD2IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD2SPROC)(GLshort s, GLshort t); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD2SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD3DPROC)(GLdouble s, GLdouble t, GLdouble r); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD3DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD3FPROC)(GLfloat s, GLfloat t, GLfloat r); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD3FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD3IPROC)(GLint s, GLint t, GLint r); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD3IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD3SPROC)(GLshort s, GLshort t, GLshort r); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD3SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD4DPROC)(GLdouble s, GLdouble t, GLdouble r, GLdouble q); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD4DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD4FPROC)(GLfloat s, GLfloat t, GLfloat r, GLfloat q); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD4FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD4IPROC)(GLint s, GLint t, GLint r, GLint q); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD4IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD4SPROC)(GLshort s, GLshort t, GLshort r, GLshort q); +typedef void (GLAD_API_PTR *PFNGLTEXCOORD4SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLTEXCOORDP1UIPROC)(GLenum type, GLuint coords); +typedef void (GLAD_API_PTR *PFNGLTEXCOORDP1UIVPROC)(GLenum type, const GLuint * coords); +typedef void (GLAD_API_PTR *PFNGLTEXCOORDP2UIPROC)(GLenum type, GLuint coords); +typedef void (GLAD_API_PTR *PFNGLTEXCOORDP2UIVPROC)(GLenum type, const GLuint * coords); +typedef void (GLAD_API_PTR *PFNGLTEXCOORDP3UIPROC)(GLenum type, GLuint coords); +typedef void (GLAD_API_PTR *PFNGLTEXCOORDP3UIVPROC)(GLenum type, const GLuint * coords); +typedef void (GLAD_API_PTR *PFNGLTEXCOORDP4UIPROC)(GLenum type, GLuint coords); +typedef void (GLAD_API_PTR *PFNGLTEXCOORDP4UIVPROC)(GLenum type, const GLuint * coords); +typedef void (GLAD_API_PTR *PFNGLTEXCOORDPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLTEXENVFPROC)(GLenum target, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLTEXENVFVPROC)(GLenum target, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLTEXENVIPROC)(GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLTEXENVIVPROC)(GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXGENDPROC)(GLenum coord, GLenum pname, GLdouble param); +typedef void (GLAD_API_PTR *PFNGLTEXGENDVPROC)(GLenum coord, GLenum pname, const GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLTEXGENFPROC)(GLenum coord, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLTEXGENFVPROC)(GLenum coord, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLTEXGENIPROC)(GLenum coord, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLTEXGENIVPROC)(GLenum coord, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE1DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVEXTPROC)(GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVEXTPROC)(GLenum target, GLenum pname, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE1DPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE2DPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE3DPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE1DPROC)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTUREBARRIERPROC)(void); +typedef void (GLAD_API_PTR *PFNGLTEXTUREBUFFERPROC)(GLuint texture, GLenum internalformat, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLTEXTUREBUFFEREXTPROC)(GLuint texture, GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLTEXTUREBUFFERRANGEPROC)(GLuint texture, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLTEXTUREBUFFERRANGEEXTPROC)(GLuint texture, GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLTEXTUREIMAGE1DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTUREIMAGE2DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTUREIMAGE3DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPAGECOMMITMENTEXTPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLboolean commit); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIIVPROC)(GLuint texture, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIIVEXTPROC)(GLuint texture, GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIUIVPROC)(GLuint texture, GLenum pname, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIUIVEXTPROC)(GLuint texture, GLenum target, GLenum pname, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERFPROC)(GLuint texture, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERFEXTPROC)(GLuint texture, GLenum target, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERFVPROC)(GLuint texture, GLenum pname, const GLfloat * param); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERFVEXTPROC)(GLuint texture, GLenum target, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIPROC)(GLuint texture, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIEXTPROC)(GLuint texture, GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIVPROC)(GLuint texture, GLenum pname, const GLint * param); +typedef void (GLAD_API_PTR *PFNGLTEXTUREPARAMETERIVEXTPROC)(GLuint texture, GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXTURERENDERBUFFEREXTPROC)(GLuint texture, GLenum target, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE1DPROC)(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE1DEXTPROC)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE2DPROC)(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE2DEXTPROC)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC)(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC)(GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE3DPROC)(GLuint texture, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE3DEXTPROC)(GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC)(GLuint texture, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC)(GLuint texture, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXTURESUBIMAGE1DPROC)(GLuint texture, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTURESUBIMAGE1DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTURESUBIMAGE2DPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTURESUBIMAGE2DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTURESUBIMAGE3DPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTURESUBIMAGE3DEXTPROC)(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXTUREVIEWPROC)(GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); +typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC)(GLuint xfb, GLuint index, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC)(GLuint xfb, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode); +typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode); +typedef void (GLAD_API_PTR *PFNGLTRANSLATEDPROC)(GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLTRANSLATEFPROC)(GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1DPROC)(GLint location, GLdouble x); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1DVPROC)(GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FARBPROC)(GLint location, GLfloat v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVARBPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint location, GLint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IARBPROC)(GLint location, GLint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVARBPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIEXTPROC)(GLint location, GLuint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIVEXTPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2DPROC)(GLint location, GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2DVPROC)(GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FARBPROC)(GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVARBPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IARBPROC)(GLint location, GLint v0, GLint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVARBPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIEXTPROC)(GLint location, GLuint v0, GLuint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIVEXTPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3DPROC)(GLint location, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3DVPROC)(GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FARBPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVARBPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3IARBPROC)(GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVARBPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIEXTPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIVEXTPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4DPROC)(GLint location, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4DVPROC)(GLint location, GLsizei count, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4FARBPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVARBPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4IARBPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVARBPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIEXTPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIVEXTPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVARBPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X3DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X4DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVARBPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X2DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X4DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVARBPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X2DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X3DVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLdouble * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMSUBROUTINESUIVPROC)(GLenum shadertype, GLsizei count, const GLuint * indices); +typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERPROC)(GLenum target); +typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERARBPROC)(GLenum target); +typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPNAMEDBUFFERPROC)(GLuint buffer); +typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPNAMEDBUFFEREXTPROC)(GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMOBJECTARBPROC)(GLhandleARB programObj); +typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMSTAGESPROC)(GLuint pipeline, GLbitfield stages, GLuint program); +typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMARBPROC)(GLhandleARB programObj); +typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPIPELINEPROC)(GLuint pipeline); +typedef void (GLAD_API_PTR *PFNGLVERTEX2DPROC)(GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLVERTEX2DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEX2FPROC)(GLfloat x, GLfloat y); +typedef void (GLAD_API_PTR *PFNGLVERTEX2FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEX2IPROC)(GLint x, GLint y); +typedef void (GLAD_API_PTR *PFNGLVERTEX2IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEX2SPROC)(GLshort x, GLshort y); +typedef void (GLAD_API_PTR *PFNGLVERTEX2SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEX3DPROC)(GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLVERTEX3DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEX3FPROC)(GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLVERTEX3FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEX3IPROC)(GLint x, GLint y, GLint z); +typedef void (GLAD_API_PTR *PFNGLVERTEX3IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEX3SPROC)(GLshort x, GLshort y, GLshort z); +typedef void (GLAD_API_PTR *PFNGLVERTEX3SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEX4DPROC)(GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLVERTEX4DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEX4FPROC)(GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLVERTEX4FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEX4IPROC)(GLint x, GLint y, GLint z, GLint w); +typedef void (GLAD_API_PTR *PFNGLVERTEX4IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEX4SPROC)(GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAD_API_PTR *PFNGLVERTEX4SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYATTRIBBINDINGPROC)(GLuint vaobj, GLuint attribindex, GLuint bindingindex); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYATTRIBFORMATPROC)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYATTRIBIFORMATPROC)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYATTRIBLFORMATPROC)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC)(GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYBINDINGDIVISORPROC)(GLuint vaobj, GLuint bindingindex, GLuint divisor); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYCOLOROFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYELEMENTBUFFERPROC)(GLuint vaobj, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYINDEXOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLenum texunit, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYNORMALOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC)(GLuint vaobj, GLuint attribindex, GLuint bindingindex); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC)(GLuint vaobj, GLuint index, GLuint divisor); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC)(GLuint vaobj, GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC)(GLuint vaobj, GLuint bindingindex, GLuint divisor); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXBUFFERPROC)(GLuint vaobj, GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXBUFFERSPROC)(GLuint vaobj, GLuint first, GLsizei count, const GLuint * buffers, const GLintptr * offsets, const GLsizei * strides); +typedef void (GLAD_API_PTR *PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC)(GLuint vaobj, GLuint buffer, GLint size, GLenum type, GLsizei stride, GLintptr offset); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DPROC)(GLuint index, GLdouble x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DARBPROC)(GLuint index, GLdouble x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVARBPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FARBPROC)(GLuint index, GLfloat x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVARBPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SPROC)(GLuint index, GLshort x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SARBPROC)(GLuint index, GLshort x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVARBPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DPROC)(GLuint index, GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DARBPROC)(GLuint index, GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVARBPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FARBPROC)(GLuint index, GLfloat x, GLfloat y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVARBPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SPROC)(GLuint index, GLshort x, GLshort y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SARBPROC)(GLuint index, GLshort x, GLshort y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVARBPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DARBPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVARBPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FARBPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVARBPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SPROC)(GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SARBPROC)(GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVARBPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NBVPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NBVARBPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NIVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NIVARBPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NSVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NSVARBPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBARBPROC)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBVPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUBVARBPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUIVARBPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUSVPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUSVARBPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4BVPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4BVARBPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DARBPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4DVARBPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FARBPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVARBPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4IVARBPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SARBPROC)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4SVARBPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVARBPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UIVARBPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4USVPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4USVARBPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBBINDINGPROC)(GLuint attribindex, GLuint bindingindex); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBFORMATPROC)(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IPROC)(GLuint index, GLint x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IEXTPROC)(GLuint index, GLint x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IVEXTPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIPROC)(GLuint index, GLuint x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIEXTPROC)(GLuint index, GLuint x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIVEXTPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IPROC)(GLuint index, GLint x, GLint y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IEXTPROC)(GLuint index, GLint x, GLint y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IVEXTPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIPROC)(GLuint index, GLuint x, GLuint y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIEXTPROC)(GLuint index, GLuint x, GLuint y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIVEXTPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IPROC)(GLuint index, GLint x, GLint y, GLint z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IEXTPROC)(GLuint index, GLint x, GLint y, GLint z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IVEXTPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIEXTPROC)(GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIVEXTPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4BVPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4BVEXTPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IEXTPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IVEXTPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4SVEXTPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UBVPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UBVEXTPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIEXTPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIVEXTPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4USVPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4USVEXTPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIFORMATPROC)(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIPOINTEREXTPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL1DPROC)(GLuint index, GLdouble x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL1DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL2DPROC)(GLuint index, GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL2DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL3DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL4DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBL4DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBLFORMATPROC)(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBLPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP1UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP2UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP3UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIPROC)(GLuint index, GLenum type, GLboolean normalized, GLuint value); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBP4UIVPROC)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERARBPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVERTEXBINDINGDIVISORPROC)(GLuint bindingindex, GLuint divisor); +typedef void (GLAD_API_PTR *PFNGLVERTEXP2UIPROC)(GLenum type, GLuint value); +typedef void (GLAD_API_PTR *PFNGLVERTEXP2UIVPROC)(GLenum type, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLVERTEXP3UIPROC)(GLenum type, GLuint value); +typedef void (GLAD_API_PTR *PFNGLVERTEXP3UIVPROC)(GLenum type, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLVERTEXP4UIPROC)(GLenum type, GLuint value); +typedef void (GLAD_API_PTR *PFNGLVERTEXP4UIVPROC)(GLenum type, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLVERTEXPOINTERPROC)(GLint size, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLVIEWPORTARRAYVPROC)(GLuint first, GLsizei count, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVIEWPORTINDEXEDFPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); +typedef void (GLAD_API_PTR *PFNGLVIEWPORTINDEXEDFVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2DPROC)(GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2FPROC)(GLfloat x, GLfloat y); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2IPROC)(GLint x, GLint y); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2SPROC)(GLshort x, GLshort y); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS2SVPROC)(const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3DPROC)(GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3DVPROC)(const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3FPROC)(GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3FVPROC)(const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3IPROC)(GLint x, GLint y, GLint z); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3IVPROC)(const GLint * v); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3SPROC)(GLshort x, GLshort y, GLshort z); +typedef void (GLAD_API_PTR *PFNGLWINDOWPOS3SVPROC)(const GLshort * v); + +GLAD_API_CALL PFNGLACCUMPROC glad_glAccum; +#define glAccum glad_glAccum +GLAD_API_CALL PFNGLACTIVESHADERPROGRAMPROC glad_glActiveShaderProgram; +#define glActiveShaderProgram glad_glActiveShaderProgram +GLAD_API_CALL PFNGLACTIVETEXTUREPROC glad_glActiveTexture; +#define glActiveTexture glad_glActiveTexture +GLAD_API_CALL PFNGLALPHAFUNCPROC glad_glAlphaFunc; +#define glAlphaFunc glad_glAlphaFunc +GLAD_API_CALL PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident; +#define glAreTexturesResident glad_glAreTexturesResident +GLAD_API_CALL PFNGLARRAYELEMENTPROC glad_glArrayElement; +#define glArrayElement glad_glArrayElement +GLAD_API_CALL PFNGLATTACHOBJECTARBPROC glad_glAttachObjectARB; +#define glAttachObjectARB glad_glAttachObjectARB +GLAD_API_CALL PFNGLATTACHSHADERPROC glad_glAttachShader; +#define glAttachShader glad_glAttachShader +GLAD_API_CALL PFNGLBEGINPROC glad_glBegin; +#define glBegin glad_glBegin +GLAD_API_CALL PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender; +#define glBeginConditionalRender glad_glBeginConditionalRender +GLAD_API_CALL PFNGLBEGINQUERYPROC glad_glBeginQuery; +#define glBeginQuery glad_glBeginQuery +GLAD_API_CALL PFNGLBEGINQUERYINDEXEDPROC glad_glBeginQueryIndexed; +#define glBeginQueryIndexed glad_glBeginQueryIndexed +GLAD_API_CALL PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback; +#define glBeginTransformFeedback glad_glBeginTransformFeedback +GLAD_API_CALL PFNGLBEGINTRANSFORMFEEDBACKEXTPROC glad_glBeginTransformFeedbackEXT; +#define glBeginTransformFeedbackEXT glad_glBeginTransformFeedbackEXT +GLAD_API_CALL PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation; +#define glBindAttribLocation glad_glBindAttribLocation +GLAD_API_CALL PFNGLBINDATTRIBLOCATIONARBPROC glad_glBindAttribLocationARB; +#define glBindAttribLocationARB glad_glBindAttribLocationARB +GLAD_API_CALL PFNGLBINDBUFFERPROC glad_glBindBuffer; +#define glBindBuffer glad_glBindBuffer +GLAD_API_CALL PFNGLBINDBUFFERARBPROC glad_glBindBufferARB; +#define glBindBufferARB glad_glBindBufferARB +GLAD_API_CALL PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase; +#define glBindBufferBase glad_glBindBufferBase +GLAD_API_CALL PFNGLBINDBUFFERBASEEXTPROC glad_glBindBufferBaseEXT; +#define glBindBufferBaseEXT glad_glBindBufferBaseEXT +GLAD_API_CALL PFNGLBINDBUFFEROFFSETEXTPROC glad_glBindBufferOffsetEXT; +#define glBindBufferOffsetEXT glad_glBindBufferOffsetEXT +GLAD_API_CALL PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange; +#define glBindBufferRange glad_glBindBufferRange +GLAD_API_CALL PFNGLBINDBUFFERRANGEEXTPROC glad_glBindBufferRangeEXT; +#define glBindBufferRangeEXT glad_glBindBufferRangeEXT +GLAD_API_CALL PFNGLBINDBUFFERSBASEPROC glad_glBindBuffersBase; +#define glBindBuffersBase glad_glBindBuffersBase +GLAD_API_CALL PFNGLBINDBUFFERSRANGEPROC glad_glBindBuffersRange; +#define glBindBuffersRange glad_glBindBuffersRange +GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation; +#define glBindFragDataLocation glad_glBindFragDataLocation +GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONEXTPROC glad_glBindFragDataLocationEXT; +#define glBindFragDataLocationEXT glad_glBindFragDataLocationEXT +GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed; +#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed +GLAD_API_CALL PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer; +#define glBindFramebuffer glad_glBindFramebuffer +GLAD_API_CALL PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT; +#define glBindFramebufferEXT glad_glBindFramebufferEXT +GLAD_API_CALL PFNGLBINDIMAGETEXTUREPROC glad_glBindImageTexture; +#define glBindImageTexture glad_glBindImageTexture +GLAD_API_CALL PFNGLBINDIMAGETEXTUREEXTPROC glad_glBindImageTextureEXT; +#define glBindImageTextureEXT glad_glBindImageTextureEXT +GLAD_API_CALL PFNGLBINDIMAGETEXTURESPROC glad_glBindImageTextures; +#define glBindImageTextures glad_glBindImageTextures +GLAD_API_CALL PFNGLBINDMULTITEXTUREEXTPROC glad_glBindMultiTextureEXT; +#define glBindMultiTextureEXT glad_glBindMultiTextureEXT +GLAD_API_CALL PFNGLBINDPROGRAMARBPROC glad_glBindProgramARB; +#define glBindProgramARB glad_glBindProgramARB +GLAD_API_CALL PFNGLBINDPROGRAMPIPELINEPROC glad_glBindProgramPipeline; +#define glBindProgramPipeline glad_glBindProgramPipeline +GLAD_API_CALL PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer; +#define glBindRenderbuffer glad_glBindRenderbuffer +GLAD_API_CALL PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT; +#define glBindRenderbufferEXT glad_glBindRenderbufferEXT +GLAD_API_CALL PFNGLBINDSAMPLERPROC glad_glBindSampler; +#define glBindSampler glad_glBindSampler +GLAD_API_CALL PFNGLBINDSAMPLERSPROC glad_glBindSamplers; +#define glBindSamplers glad_glBindSamplers +GLAD_API_CALL PFNGLBINDTEXTUREPROC glad_glBindTexture; +#define glBindTexture glad_glBindTexture +GLAD_API_CALL PFNGLBINDTEXTUREUNITPROC glad_glBindTextureUnit; +#define glBindTextureUnit glad_glBindTextureUnit +GLAD_API_CALL PFNGLBINDTEXTURESPROC glad_glBindTextures; +#define glBindTextures glad_glBindTextures +GLAD_API_CALL PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback; +#define glBindTransformFeedback glad_glBindTransformFeedback +GLAD_API_CALL PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray; +#define glBindVertexArray glad_glBindVertexArray +GLAD_API_CALL PFNGLBINDVERTEXBUFFERPROC glad_glBindVertexBuffer; +#define glBindVertexBuffer glad_glBindVertexBuffer +GLAD_API_CALL PFNGLBINDVERTEXBUFFERSPROC glad_glBindVertexBuffers; +#define glBindVertexBuffers glad_glBindVertexBuffers +GLAD_API_CALL PFNGLBITMAPPROC glad_glBitmap; +#define glBitmap glad_glBitmap +GLAD_API_CALL PFNGLBLENDCOLORPROC glad_glBlendColor; +#define glBlendColor glad_glBlendColor +GLAD_API_CALL PFNGLBLENDEQUATIONPROC glad_glBlendEquation; +#define glBlendEquation glad_glBlendEquation +GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate; +#define glBlendEquationSeparate glad_glBlendEquationSeparate +GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEIPROC glad_glBlendEquationSeparatei; +#define glBlendEquationSeparatei glad_glBlendEquationSeparatei +GLAD_API_CALL PFNGLBLENDEQUATIONIPROC glad_glBlendEquationi; +#define glBlendEquationi glad_glBlendEquationi +GLAD_API_CALL PFNGLBLENDFUNCPROC glad_glBlendFunc; +#define glBlendFunc glad_glBlendFunc +GLAD_API_CALL PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate; +#define glBlendFuncSeparate glad_glBlendFuncSeparate +GLAD_API_CALL PFNGLBLENDFUNCSEPARATEIPROC glad_glBlendFuncSeparatei; +#define glBlendFuncSeparatei glad_glBlendFuncSeparatei +GLAD_API_CALL PFNGLBLENDFUNCIPROC glad_glBlendFunci; +#define glBlendFunci glad_glBlendFunci +GLAD_API_CALL PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer; +#define glBlitFramebuffer glad_glBlitFramebuffer +GLAD_API_CALL PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT; +#define glBlitFramebufferEXT glad_glBlitFramebufferEXT +GLAD_API_CALL PFNGLBLITNAMEDFRAMEBUFFERPROC glad_glBlitNamedFramebuffer; +#define glBlitNamedFramebuffer glad_glBlitNamedFramebuffer +GLAD_API_CALL PFNGLBUFFERDATAPROC glad_glBufferData; +#define glBufferData glad_glBufferData +GLAD_API_CALL PFNGLBUFFERDATAARBPROC glad_glBufferDataARB; +#define glBufferDataARB glad_glBufferDataARB +GLAD_API_CALL PFNGLBUFFERSTORAGEPROC glad_glBufferStorage; +#define glBufferStorage glad_glBufferStorage +GLAD_API_CALL PFNGLBUFFERSUBDATAPROC glad_glBufferSubData; +#define glBufferSubData glad_glBufferSubData +GLAD_API_CALL PFNGLBUFFERSUBDATAARBPROC glad_glBufferSubDataARB; +#define glBufferSubDataARB glad_glBufferSubDataARB +GLAD_API_CALL PFNGLCALLLISTPROC glad_glCallList; +#define glCallList glad_glCallList +GLAD_API_CALL PFNGLCALLLISTSPROC glad_glCallLists; +#define glCallLists glad_glCallLists +GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus; +#define glCheckFramebufferStatus glad_glCheckFramebufferStatus +GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT; +#define glCheckFramebufferStatusEXT glad_glCheckFramebufferStatusEXT +GLAD_API_CALL PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glad_glCheckNamedFramebufferStatus; +#define glCheckNamedFramebufferStatus glad_glCheckNamedFramebufferStatus +GLAD_API_CALL PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC glad_glCheckNamedFramebufferStatusEXT; +#define glCheckNamedFramebufferStatusEXT glad_glCheckNamedFramebufferStatusEXT +GLAD_API_CALL PFNGLCLAMPCOLORPROC glad_glClampColor; +#define glClampColor glad_glClampColor +GLAD_API_CALL PFNGLCLEARPROC glad_glClear; +#define glClear glad_glClear +GLAD_API_CALL PFNGLCLEARACCUMPROC glad_glClearAccum; +#define glClearAccum glad_glClearAccum +GLAD_API_CALL PFNGLCLEARBUFFERDATAPROC glad_glClearBufferData; +#define glClearBufferData glad_glClearBufferData +GLAD_API_CALL PFNGLCLEARBUFFERSUBDATAPROC glad_glClearBufferSubData; +#define glClearBufferSubData glad_glClearBufferSubData +GLAD_API_CALL PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi; +#define glClearBufferfi glad_glClearBufferfi +GLAD_API_CALL PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv; +#define glClearBufferfv glad_glClearBufferfv +GLAD_API_CALL PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv; +#define glClearBufferiv glad_glClearBufferiv +GLAD_API_CALL PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv; +#define glClearBufferuiv glad_glClearBufferuiv +GLAD_API_CALL PFNGLCLEARCOLORPROC glad_glClearColor; +#define glClearColor glad_glClearColor +GLAD_API_CALL PFNGLCLEARCOLORIIEXTPROC glad_glClearColorIiEXT; +#define glClearColorIiEXT glad_glClearColorIiEXT +GLAD_API_CALL PFNGLCLEARCOLORIUIEXTPROC glad_glClearColorIuiEXT; +#define glClearColorIuiEXT glad_glClearColorIuiEXT +GLAD_API_CALL PFNGLCLEARDEPTHPROC glad_glClearDepth; +#define glClearDepth glad_glClearDepth +GLAD_API_CALL PFNGLCLEARDEPTHFPROC glad_glClearDepthf; +#define glClearDepthf glad_glClearDepthf +GLAD_API_CALL PFNGLCLEARINDEXPROC glad_glClearIndex; +#define glClearIndex glad_glClearIndex +GLAD_API_CALL PFNGLCLEARNAMEDBUFFERDATAPROC glad_glClearNamedBufferData; +#define glClearNamedBufferData glad_glClearNamedBufferData +GLAD_API_CALL PFNGLCLEARNAMEDBUFFERDATAEXTPROC glad_glClearNamedBufferDataEXT; +#define glClearNamedBufferDataEXT glad_glClearNamedBufferDataEXT +GLAD_API_CALL PFNGLCLEARNAMEDBUFFERSUBDATAPROC glad_glClearNamedBufferSubData; +#define glClearNamedBufferSubData glad_glClearNamedBufferSubData +GLAD_API_CALL PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC glad_glClearNamedBufferSubDataEXT; +#define glClearNamedBufferSubDataEXT glad_glClearNamedBufferSubDataEXT +GLAD_API_CALL PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glad_glClearNamedFramebufferfi; +#define glClearNamedFramebufferfi glad_glClearNamedFramebufferfi +GLAD_API_CALL PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glad_glClearNamedFramebufferfv; +#define glClearNamedFramebufferfv glad_glClearNamedFramebufferfv +GLAD_API_CALL PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glad_glClearNamedFramebufferiv; +#define glClearNamedFramebufferiv glad_glClearNamedFramebufferiv +GLAD_API_CALL PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glad_glClearNamedFramebufferuiv; +#define glClearNamedFramebufferuiv glad_glClearNamedFramebufferuiv +GLAD_API_CALL PFNGLCLEARSTENCILPROC glad_glClearStencil; +#define glClearStencil glad_glClearStencil +GLAD_API_CALL PFNGLCLEARTEXIMAGEPROC glad_glClearTexImage; +#define glClearTexImage glad_glClearTexImage +GLAD_API_CALL PFNGLCLEARTEXSUBIMAGEPROC glad_glClearTexSubImage; +#define glClearTexSubImage glad_glClearTexSubImage +GLAD_API_CALL PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture; +#define glClientActiveTexture glad_glClientActiveTexture +GLAD_API_CALL PFNGLCLIENTATTRIBDEFAULTEXTPROC glad_glClientAttribDefaultEXT; +#define glClientAttribDefaultEXT glad_glClientAttribDefaultEXT +GLAD_API_CALL PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync; +#define glClientWaitSync glad_glClientWaitSync +GLAD_API_CALL PFNGLCLIPCONTROLPROC glad_glClipControl; +#define glClipControl glad_glClipControl +GLAD_API_CALL PFNGLCLIPPLANEPROC glad_glClipPlane; +#define glClipPlane glad_glClipPlane +GLAD_API_CALL PFNGLCOLOR3BPROC glad_glColor3b; +#define glColor3b glad_glColor3b +GLAD_API_CALL PFNGLCOLOR3BVPROC glad_glColor3bv; +#define glColor3bv glad_glColor3bv +GLAD_API_CALL PFNGLCOLOR3DPROC glad_glColor3d; +#define glColor3d glad_glColor3d +GLAD_API_CALL PFNGLCOLOR3DVPROC glad_glColor3dv; +#define glColor3dv glad_glColor3dv +GLAD_API_CALL PFNGLCOLOR3FPROC glad_glColor3f; +#define glColor3f glad_glColor3f +GLAD_API_CALL PFNGLCOLOR3FVPROC glad_glColor3fv; +#define glColor3fv glad_glColor3fv +GLAD_API_CALL PFNGLCOLOR3IPROC glad_glColor3i; +#define glColor3i glad_glColor3i +GLAD_API_CALL PFNGLCOLOR3IVPROC glad_glColor3iv; +#define glColor3iv glad_glColor3iv +GLAD_API_CALL PFNGLCOLOR3SPROC glad_glColor3s; +#define glColor3s glad_glColor3s +GLAD_API_CALL PFNGLCOLOR3SVPROC glad_glColor3sv; +#define glColor3sv glad_glColor3sv +GLAD_API_CALL PFNGLCOLOR3UBPROC glad_glColor3ub; +#define glColor3ub glad_glColor3ub +GLAD_API_CALL PFNGLCOLOR3UBVPROC glad_glColor3ubv; +#define glColor3ubv glad_glColor3ubv +GLAD_API_CALL PFNGLCOLOR3UIPROC glad_glColor3ui; +#define glColor3ui glad_glColor3ui +GLAD_API_CALL PFNGLCOLOR3UIVPROC glad_glColor3uiv; +#define glColor3uiv glad_glColor3uiv +GLAD_API_CALL PFNGLCOLOR3USPROC glad_glColor3us; +#define glColor3us glad_glColor3us +GLAD_API_CALL PFNGLCOLOR3USVPROC glad_glColor3usv; +#define glColor3usv glad_glColor3usv +GLAD_API_CALL PFNGLCOLOR4BPROC glad_glColor4b; +#define glColor4b glad_glColor4b +GLAD_API_CALL PFNGLCOLOR4BVPROC glad_glColor4bv; +#define glColor4bv glad_glColor4bv +GLAD_API_CALL PFNGLCOLOR4DPROC glad_glColor4d; +#define glColor4d glad_glColor4d +GLAD_API_CALL PFNGLCOLOR4DVPROC glad_glColor4dv; +#define glColor4dv glad_glColor4dv +GLAD_API_CALL PFNGLCOLOR4FPROC glad_glColor4f; +#define glColor4f glad_glColor4f +GLAD_API_CALL PFNGLCOLOR4FVPROC glad_glColor4fv; +#define glColor4fv glad_glColor4fv +GLAD_API_CALL PFNGLCOLOR4IPROC glad_glColor4i; +#define glColor4i glad_glColor4i +GLAD_API_CALL PFNGLCOLOR4IVPROC glad_glColor4iv; +#define glColor4iv glad_glColor4iv +GLAD_API_CALL PFNGLCOLOR4SPROC glad_glColor4s; +#define glColor4s glad_glColor4s +GLAD_API_CALL PFNGLCOLOR4SVPROC glad_glColor4sv; +#define glColor4sv glad_glColor4sv +GLAD_API_CALL PFNGLCOLOR4UBPROC glad_glColor4ub; +#define glColor4ub glad_glColor4ub +GLAD_API_CALL PFNGLCOLOR4UBVPROC glad_glColor4ubv; +#define glColor4ubv glad_glColor4ubv +GLAD_API_CALL PFNGLCOLOR4UIPROC glad_glColor4ui; +#define glColor4ui glad_glColor4ui +GLAD_API_CALL PFNGLCOLOR4UIVPROC glad_glColor4uiv; +#define glColor4uiv glad_glColor4uiv +GLAD_API_CALL PFNGLCOLOR4USPROC glad_glColor4us; +#define glColor4us glad_glColor4us +GLAD_API_CALL PFNGLCOLOR4USVPROC glad_glColor4usv; +#define glColor4usv glad_glColor4usv +GLAD_API_CALL PFNGLCOLORMASKPROC glad_glColorMask; +#define glColorMask glad_glColorMask +GLAD_API_CALL PFNGLCOLORMASKIPROC glad_glColorMaski; +#define glColorMaski glad_glColorMaski +GLAD_API_CALL PFNGLCOLORMATERIALPROC glad_glColorMaterial; +#define glColorMaterial glad_glColorMaterial +GLAD_API_CALL PFNGLCOLORP3UIPROC glad_glColorP3ui; +#define glColorP3ui glad_glColorP3ui +GLAD_API_CALL PFNGLCOLORP3UIVPROC glad_glColorP3uiv; +#define glColorP3uiv glad_glColorP3uiv +GLAD_API_CALL PFNGLCOLORP4UIPROC glad_glColorP4ui; +#define glColorP4ui glad_glColorP4ui +GLAD_API_CALL PFNGLCOLORP4UIVPROC glad_glColorP4uiv; +#define glColorP4uiv glad_glColorP4uiv +GLAD_API_CALL PFNGLCOLORPOINTERPROC glad_glColorPointer; +#define glColorPointer glad_glColorPointer +GLAD_API_CALL PFNGLCOMPILESHADERPROC glad_glCompileShader; +#define glCompileShader glad_glCompileShader +GLAD_API_CALL PFNGLCOMPILESHADERARBPROC glad_glCompileShaderARB; +#define glCompileShaderARB glad_glCompileShaderARB +GLAD_API_CALL PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC glad_glCompressedMultiTexImage1DEXT; +#define glCompressedMultiTexImage1DEXT glad_glCompressedMultiTexImage1DEXT +GLAD_API_CALL PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC glad_glCompressedMultiTexImage2DEXT; +#define glCompressedMultiTexImage2DEXT glad_glCompressedMultiTexImage2DEXT +GLAD_API_CALL PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC glad_glCompressedMultiTexImage3DEXT; +#define glCompressedMultiTexImage3DEXT glad_glCompressedMultiTexImage3DEXT +GLAD_API_CALL PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC glad_glCompressedMultiTexSubImage1DEXT; +#define glCompressedMultiTexSubImage1DEXT glad_glCompressedMultiTexSubImage1DEXT +GLAD_API_CALL PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC glad_glCompressedMultiTexSubImage2DEXT; +#define glCompressedMultiTexSubImage2DEXT glad_glCompressedMultiTexSubImage2DEXT +GLAD_API_CALL PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC glad_glCompressedMultiTexSubImage3DEXT; +#define glCompressedMultiTexSubImage3DEXT glad_glCompressedMultiTexSubImage3DEXT +GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D; +#define glCompressedTexImage1D glad_glCompressedTexImage1D +GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D; +#define glCompressedTexImage2D glad_glCompressedTexImage2D +GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D; +#define glCompressedTexImage3D glad_glCompressedTexImage3D +GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D; +#define glCompressedTexSubImage1D glad_glCompressedTexSubImage1D +GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D; +#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D +GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D; +#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D +GLAD_API_CALL PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC glad_glCompressedTextureImage1DEXT; +#define glCompressedTextureImage1DEXT glad_glCompressedTextureImage1DEXT +GLAD_API_CALL PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC glad_glCompressedTextureImage2DEXT; +#define glCompressedTextureImage2DEXT glad_glCompressedTextureImage2DEXT +GLAD_API_CALL PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC glad_glCompressedTextureImage3DEXT; +#define glCompressedTextureImage3DEXT glad_glCompressedTextureImage3DEXT +GLAD_API_CALL PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glad_glCompressedTextureSubImage1D; +#define glCompressedTextureSubImage1D glad_glCompressedTextureSubImage1D +GLAD_API_CALL PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC glad_glCompressedTextureSubImage1DEXT; +#define glCompressedTextureSubImage1DEXT glad_glCompressedTextureSubImage1DEXT +GLAD_API_CALL PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glad_glCompressedTextureSubImage2D; +#define glCompressedTextureSubImage2D glad_glCompressedTextureSubImage2D +GLAD_API_CALL PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC glad_glCompressedTextureSubImage2DEXT; +#define glCompressedTextureSubImage2DEXT glad_glCompressedTextureSubImage2DEXT +GLAD_API_CALL PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glad_glCompressedTextureSubImage3D; +#define glCompressedTextureSubImage3D glad_glCompressedTextureSubImage3D +GLAD_API_CALL PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC glad_glCompressedTextureSubImage3DEXT; +#define glCompressedTextureSubImage3DEXT glad_glCompressedTextureSubImage3DEXT +GLAD_API_CALL PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData; +#define glCopyBufferSubData glad_glCopyBufferSubData +GLAD_API_CALL PFNGLCOPYIMAGESUBDATAPROC glad_glCopyImageSubData; +#define glCopyImageSubData glad_glCopyImageSubData +GLAD_API_CALL PFNGLCOPYMULTITEXIMAGE1DEXTPROC glad_glCopyMultiTexImage1DEXT; +#define glCopyMultiTexImage1DEXT glad_glCopyMultiTexImage1DEXT +GLAD_API_CALL PFNGLCOPYMULTITEXIMAGE2DEXTPROC glad_glCopyMultiTexImage2DEXT; +#define glCopyMultiTexImage2DEXT glad_glCopyMultiTexImage2DEXT +GLAD_API_CALL PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC glad_glCopyMultiTexSubImage1DEXT; +#define glCopyMultiTexSubImage1DEXT glad_glCopyMultiTexSubImage1DEXT +GLAD_API_CALL PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC glad_glCopyMultiTexSubImage2DEXT; +#define glCopyMultiTexSubImage2DEXT glad_glCopyMultiTexSubImage2DEXT +GLAD_API_CALL PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC glad_glCopyMultiTexSubImage3DEXT; +#define glCopyMultiTexSubImage3DEXT glad_glCopyMultiTexSubImage3DEXT +GLAD_API_CALL PFNGLCOPYNAMEDBUFFERSUBDATAPROC glad_glCopyNamedBufferSubData; +#define glCopyNamedBufferSubData glad_glCopyNamedBufferSubData +GLAD_API_CALL PFNGLCOPYPIXELSPROC glad_glCopyPixels; +#define glCopyPixels glad_glCopyPixels +GLAD_API_CALL PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D; +#define glCopyTexImage1D glad_glCopyTexImage1D +GLAD_API_CALL PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D; +#define glCopyTexImage2D glad_glCopyTexImage2D +GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D; +#define glCopyTexSubImage1D glad_glCopyTexSubImage1D +GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D; +#define glCopyTexSubImage2D glad_glCopyTexSubImage2D +GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D; +#define glCopyTexSubImage3D glad_glCopyTexSubImage3D +GLAD_API_CALL PFNGLCOPYTEXTUREIMAGE1DEXTPROC glad_glCopyTextureImage1DEXT; +#define glCopyTextureImage1DEXT glad_glCopyTextureImage1DEXT +GLAD_API_CALL PFNGLCOPYTEXTUREIMAGE2DEXTPROC glad_glCopyTextureImage2DEXT; +#define glCopyTextureImage2DEXT glad_glCopyTextureImage2DEXT +GLAD_API_CALL PFNGLCOPYTEXTURESUBIMAGE1DPROC glad_glCopyTextureSubImage1D; +#define glCopyTextureSubImage1D glad_glCopyTextureSubImage1D +GLAD_API_CALL PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC glad_glCopyTextureSubImage1DEXT; +#define glCopyTextureSubImage1DEXT glad_glCopyTextureSubImage1DEXT +GLAD_API_CALL PFNGLCOPYTEXTURESUBIMAGE2DPROC glad_glCopyTextureSubImage2D; +#define glCopyTextureSubImage2D glad_glCopyTextureSubImage2D +GLAD_API_CALL PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC glad_glCopyTextureSubImage2DEXT; +#define glCopyTextureSubImage2DEXT glad_glCopyTextureSubImage2DEXT +GLAD_API_CALL PFNGLCOPYTEXTURESUBIMAGE3DPROC glad_glCopyTextureSubImage3D; +#define glCopyTextureSubImage3D glad_glCopyTextureSubImage3D +GLAD_API_CALL PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC glad_glCopyTextureSubImage3DEXT; +#define glCopyTextureSubImage3DEXT glad_glCopyTextureSubImage3DEXT +GLAD_API_CALL PFNGLCREATEBUFFERSPROC glad_glCreateBuffers; +#define glCreateBuffers glad_glCreateBuffers +GLAD_API_CALL PFNGLCREATEFRAMEBUFFERSPROC glad_glCreateFramebuffers; +#define glCreateFramebuffers glad_glCreateFramebuffers +GLAD_API_CALL PFNGLCREATEPROGRAMPROC glad_glCreateProgram; +#define glCreateProgram glad_glCreateProgram +GLAD_API_CALL PFNGLCREATEPROGRAMOBJECTARBPROC glad_glCreateProgramObjectARB; +#define glCreateProgramObjectARB glad_glCreateProgramObjectARB +GLAD_API_CALL PFNGLCREATEPROGRAMPIPELINESPROC glad_glCreateProgramPipelines; +#define glCreateProgramPipelines glad_glCreateProgramPipelines +GLAD_API_CALL PFNGLCREATEQUERIESPROC glad_glCreateQueries; +#define glCreateQueries glad_glCreateQueries +GLAD_API_CALL PFNGLCREATERENDERBUFFERSPROC glad_glCreateRenderbuffers; +#define glCreateRenderbuffers glad_glCreateRenderbuffers +GLAD_API_CALL PFNGLCREATESAMPLERSPROC glad_glCreateSamplers; +#define glCreateSamplers glad_glCreateSamplers +GLAD_API_CALL PFNGLCREATESHADERPROC glad_glCreateShader; +#define glCreateShader glad_glCreateShader +GLAD_API_CALL PFNGLCREATESHADEROBJECTARBPROC glad_glCreateShaderObjectARB; +#define glCreateShaderObjectARB glad_glCreateShaderObjectARB +GLAD_API_CALL PFNGLCREATESHADERPROGRAMVPROC glad_glCreateShaderProgramv; +#define glCreateShaderProgramv glad_glCreateShaderProgramv +GLAD_API_CALL PFNGLCREATETEXTURESPROC glad_glCreateTextures; +#define glCreateTextures glad_glCreateTextures +GLAD_API_CALL PFNGLCREATETRANSFORMFEEDBACKSPROC glad_glCreateTransformFeedbacks; +#define glCreateTransformFeedbacks glad_glCreateTransformFeedbacks +GLAD_API_CALL PFNGLCREATEVERTEXARRAYSPROC glad_glCreateVertexArrays; +#define glCreateVertexArrays glad_glCreateVertexArrays +GLAD_API_CALL PFNGLCULLFACEPROC glad_glCullFace; +#define glCullFace glad_glCullFace +GLAD_API_CALL PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback; +#define glDebugMessageCallback glad_glDebugMessageCallback +GLAD_API_CALL PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB; +#define glDebugMessageCallbackARB glad_glDebugMessageCallbackARB +GLAD_API_CALL PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl; +#define glDebugMessageControl glad_glDebugMessageControl +GLAD_API_CALL PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB; +#define glDebugMessageControlARB glad_glDebugMessageControlARB +GLAD_API_CALL PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert; +#define glDebugMessageInsert glad_glDebugMessageInsert +GLAD_API_CALL PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB; +#define glDebugMessageInsertARB glad_glDebugMessageInsertARB +GLAD_API_CALL PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers; +#define glDeleteBuffers glad_glDeleteBuffers +GLAD_API_CALL PFNGLDELETEBUFFERSARBPROC glad_glDeleteBuffersARB; +#define glDeleteBuffersARB glad_glDeleteBuffersARB +GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers; +#define glDeleteFramebuffers glad_glDeleteFramebuffers +GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT; +#define glDeleteFramebuffersEXT glad_glDeleteFramebuffersEXT +GLAD_API_CALL PFNGLDELETELISTSPROC glad_glDeleteLists; +#define glDeleteLists glad_glDeleteLists +GLAD_API_CALL PFNGLDELETEOBJECTARBPROC glad_glDeleteObjectARB; +#define glDeleteObjectARB glad_glDeleteObjectARB +GLAD_API_CALL PFNGLDELETEPROGRAMPROC glad_glDeleteProgram; +#define glDeleteProgram glad_glDeleteProgram +GLAD_API_CALL PFNGLDELETEPROGRAMPIPELINESPROC glad_glDeleteProgramPipelines; +#define glDeleteProgramPipelines glad_glDeleteProgramPipelines +GLAD_API_CALL PFNGLDELETEPROGRAMSARBPROC glad_glDeleteProgramsARB; +#define glDeleteProgramsARB glad_glDeleteProgramsARB +GLAD_API_CALL PFNGLDELETEQUERIESPROC glad_glDeleteQueries; +#define glDeleteQueries glad_glDeleteQueries +GLAD_API_CALL PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers; +#define glDeleteRenderbuffers glad_glDeleteRenderbuffers +GLAD_API_CALL PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT; +#define glDeleteRenderbuffersEXT glad_glDeleteRenderbuffersEXT +GLAD_API_CALL PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers; +#define glDeleteSamplers glad_glDeleteSamplers +GLAD_API_CALL PFNGLDELETESHADERPROC glad_glDeleteShader; +#define glDeleteShader glad_glDeleteShader +GLAD_API_CALL PFNGLDELETESYNCPROC glad_glDeleteSync; +#define glDeleteSync glad_glDeleteSync +GLAD_API_CALL PFNGLDELETETEXTURESPROC glad_glDeleteTextures; +#define glDeleteTextures glad_glDeleteTextures +GLAD_API_CALL PFNGLDELETETRANSFORMFEEDBACKSPROC glad_glDeleteTransformFeedbacks; +#define glDeleteTransformFeedbacks glad_glDeleteTransformFeedbacks +GLAD_API_CALL PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays; +#define glDeleteVertexArrays glad_glDeleteVertexArrays +GLAD_API_CALL PFNGLDEPTHFUNCPROC glad_glDepthFunc; +#define glDepthFunc glad_glDepthFunc +GLAD_API_CALL PFNGLDEPTHMASKPROC glad_glDepthMask; +#define glDepthMask glad_glDepthMask +GLAD_API_CALL PFNGLDEPTHRANGEPROC glad_glDepthRange; +#define glDepthRange glad_glDepthRange +GLAD_API_CALL PFNGLDEPTHRANGEARRAYVPROC glad_glDepthRangeArrayv; +#define glDepthRangeArrayv glad_glDepthRangeArrayv +GLAD_API_CALL PFNGLDEPTHRANGEINDEXEDPROC glad_glDepthRangeIndexed; +#define glDepthRangeIndexed glad_glDepthRangeIndexed +GLAD_API_CALL PFNGLDEPTHRANGEFPROC glad_glDepthRangef; +#define glDepthRangef glad_glDepthRangef +GLAD_API_CALL PFNGLDETACHOBJECTARBPROC glad_glDetachObjectARB; +#define glDetachObjectARB glad_glDetachObjectARB +GLAD_API_CALL PFNGLDETACHSHADERPROC glad_glDetachShader; +#define glDetachShader glad_glDetachShader +GLAD_API_CALL PFNGLDISABLEPROC glad_glDisable; +#define glDisable glad_glDisable +GLAD_API_CALL PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState; +#define glDisableClientState glad_glDisableClientState +GLAD_API_CALL PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC glad_glDisableClientStateIndexedEXT; +#define glDisableClientStateIndexedEXT glad_glDisableClientStateIndexedEXT +GLAD_API_CALL PFNGLDISABLECLIENTSTATEIEXTPROC glad_glDisableClientStateiEXT; +#define glDisableClientStateiEXT glad_glDisableClientStateiEXT +GLAD_API_CALL PFNGLDISABLEINDEXEDEXTPROC glad_glDisableIndexedEXT; +#define glDisableIndexedEXT glad_glDisableIndexedEXT +GLAD_API_CALL PFNGLDISABLEVERTEXARRAYATTRIBPROC glad_glDisableVertexArrayAttrib; +#define glDisableVertexArrayAttrib glad_glDisableVertexArrayAttrib +GLAD_API_CALL PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC glad_glDisableVertexArrayAttribEXT; +#define glDisableVertexArrayAttribEXT glad_glDisableVertexArrayAttribEXT +GLAD_API_CALL PFNGLDISABLEVERTEXARRAYEXTPROC glad_glDisableVertexArrayEXT; +#define glDisableVertexArrayEXT glad_glDisableVertexArrayEXT +GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray; +#define glDisableVertexAttribArray glad_glDisableVertexAttribArray +GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glad_glDisableVertexAttribArrayARB; +#define glDisableVertexAttribArrayARB glad_glDisableVertexAttribArrayARB +GLAD_API_CALL PFNGLDISABLEIPROC glad_glDisablei; +#define glDisablei glad_glDisablei +GLAD_API_CALL PFNGLDISPATCHCOMPUTEPROC glad_glDispatchCompute; +#define glDispatchCompute glad_glDispatchCompute +GLAD_API_CALL PFNGLDISPATCHCOMPUTEINDIRECTPROC glad_glDispatchComputeIndirect; +#define glDispatchComputeIndirect glad_glDispatchComputeIndirect +GLAD_API_CALL PFNGLDRAWARRAYSPROC glad_glDrawArrays; +#define glDrawArrays glad_glDrawArrays +GLAD_API_CALL PFNGLDRAWARRAYSINDIRECTPROC glad_glDrawArraysIndirect; +#define glDrawArraysIndirect glad_glDrawArraysIndirect +GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced; +#define glDrawArraysInstanced glad_glDrawArraysInstanced +GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC glad_glDrawArraysInstancedBaseInstance; +#define glDrawArraysInstancedBaseInstance glad_glDrawArraysInstancedBaseInstance +GLAD_API_CALL PFNGLDRAWBUFFERPROC glad_glDrawBuffer; +#define glDrawBuffer glad_glDrawBuffer +GLAD_API_CALL PFNGLDRAWBUFFERSPROC glad_glDrawBuffers; +#define glDrawBuffers glad_glDrawBuffers +GLAD_API_CALL PFNGLDRAWELEMENTSPROC glad_glDrawElements; +#define glDrawElements glad_glDrawElements +GLAD_API_CALL PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex; +#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex +GLAD_API_CALL PFNGLDRAWELEMENTSINDIRECTPROC glad_glDrawElementsIndirect; +#define glDrawElementsIndirect glad_glDrawElementsIndirect +GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced; +#define glDrawElementsInstanced glad_glDrawElementsInstanced +GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC glad_glDrawElementsInstancedBaseInstance; +#define glDrawElementsInstancedBaseInstance glad_glDrawElementsInstancedBaseInstance +GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex; +#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex +GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC glad_glDrawElementsInstancedBaseVertexBaseInstance; +#define glDrawElementsInstancedBaseVertexBaseInstance glad_glDrawElementsInstancedBaseVertexBaseInstance +GLAD_API_CALL PFNGLDRAWPIXELSPROC glad_glDrawPixels; +#define glDrawPixels glad_glDrawPixels +GLAD_API_CALL PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements; +#define glDrawRangeElements glad_glDrawRangeElements +GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex; +#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex +GLAD_API_CALL PFNGLDRAWTRANSFORMFEEDBACKPROC glad_glDrawTransformFeedback; +#define glDrawTransformFeedback glad_glDrawTransformFeedback +GLAD_API_CALL PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC glad_glDrawTransformFeedbackInstanced; +#define glDrawTransformFeedbackInstanced glad_glDrawTransformFeedbackInstanced +GLAD_API_CALL PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC glad_glDrawTransformFeedbackStream; +#define glDrawTransformFeedbackStream glad_glDrawTransformFeedbackStream +GLAD_API_CALL PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC glad_glDrawTransformFeedbackStreamInstanced; +#define glDrawTransformFeedbackStreamInstanced glad_glDrawTransformFeedbackStreamInstanced +GLAD_API_CALL PFNGLEDGEFLAGPROC glad_glEdgeFlag; +#define glEdgeFlag glad_glEdgeFlag +GLAD_API_CALL PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer; +#define glEdgeFlagPointer glad_glEdgeFlagPointer +GLAD_API_CALL PFNGLEDGEFLAGVPROC glad_glEdgeFlagv; +#define glEdgeFlagv glad_glEdgeFlagv +GLAD_API_CALL PFNGLENABLEPROC glad_glEnable; +#define glEnable glad_glEnable +GLAD_API_CALL PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState; +#define glEnableClientState glad_glEnableClientState +GLAD_API_CALL PFNGLENABLECLIENTSTATEINDEXEDEXTPROC glad_glEnableClientStateIndexedEXT; +#define glEnableClientStateIndexedEXT glad_glEnableClientStateIndexedEXT +GLAD_API_CALL PFNGLENABLECLIENTSTATEIEXTPROC glad_glEnableClientStateiEXT; +#define glEnableClientStateiEXT glad_glEnableClientStateiEXT +GLAD_API_CALL PFNGLENABLEINDEXEDEXTPROC glad_glEnableIndexedEXT; +#define glEnableIndexedEXT glad_glEnableIndexedEXT +GLAD_API_CALL PFNGLENABLEVERTEXARRAYATTRIBPROC glad_glEnableVertexArrayAttrib; +#define glEnableVertexArrayAttrib glad_glEnableVertexArrayAttrib +GLAD_API_CALL PFNGLENABLEVERTEXARRAYATTRIBEXTPROC glad_glEnableVertexArrayAttribEXT; +#define glEnableVertexArrayAttribEXT glad_glEnableVertexArrayAttribEXT +GLAD_API_CALL PFNGLENABLEVERTEXARRAYEXTPROC glad_glEnableVertexArrayEXT; +#define glEnableVertexArrayEXT glad_glEnableVertexArrayEXT +GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray; +#define glEnableVertexAttribArray glad_glEnableVertexAttribArray +GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYARBPROC glad_glEnableVertexAttribArrayARB; +#define glEnableVertexAttribArrayARB glad_glEnableVertexAttribArrayARB +GLAD_API_CALL PFNGLENABLEIPROC glad_glEnablei; +#define glEnablei glad_glEnablei +GLAD_API_CALL PFNGLENDPROC glad_glEnd; +#define glEnd glad_glEnd +GLAD_API_CALL PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender; +#define glEndConditionalRender glad_glEndConditionalRender +GLAD_API_CALL PFNGLENDLISTPROC glad_glEndList; +#define glEndList glad_glEndList +GLAD_API_CALL PFNGLENDQUERYPROC glad_glEndQuery; +#define glEndQuery glad_glEndQuery +GLAD_API_CALL PFNGLENDQUERYINDEXEDPROC glad_glEndQueryIndexed; +#define glEndQueryIndexed glad_glEndQueryIndexed +GLAD_API_CALL PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback; +#define glEndTransformFeedback glad_glEndTransformFeedback +GLAD_API_CALL PFNGLENDTRANSFORMFEEDBACKEXTPROC glad_glEndTransformFeedbackEXT; +#define glEndTransformFeedbackEXT glad_glEndTransformFeedbackEXT +GLAD_API_CALL PFNGLEVALCOORD1DPROC glad_glEvalCoord1d; +#define glEvalCoord1d glad_glEvalCoord1d +GLAD_API_CALL PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv; +#define glEvalCoord1dv glad_glEvalCoord1dv +GLAD_API_CALL PFNGLEVALCOORD1FPROC glad_glEvalCoord1f; +#define glEvalCoord1f glad_glEvalCoord1f +GLAD_API_CALL PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv; +#define glEvalCoord1fv glad_glEvalCoord1fv +GLAD_API_CALL PFNGLEVALCOORD2DPROC glad_glEvalCoord2d; +#define glEvalCoord2d glad_glEvalCoord2d +GLAD_API_CALL PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv; +#define glEvalCoord2dv glad_glEvalCoord2dv +GLAD_API_CALL PFNGLEVALCOORD2FPROC glad_glEvalCoord2f; +#define glEvalCoord2f glad_glEvalCoord2f +GLAD_API_CALL PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv; +#define glEvalCoord2fv glad_glEvalCoord2fv +GLAD_API_CALL PFNGLEVALMESH1PROC glad_glEvalMesh1; +#define glEvalMesh1 glad_glEvalMesh1 +GLAD_API_CALL PFNGLEVALMESH2PROC glad_glEvalMesh2; +#define glEvalMesh2 glad_glEvalMesh2 +GLAD_API_CALL PFNGLEVALPOINT1PROC glad_glEvalPoint1; +#define glEvalPoint1 glad_glEvalPoint1 +GLAD_API_CALL PFNGLEVALPOINT2PROC glad_glEvalPoint2; +#define glEvalPoint2 glad_glEvalPoint2 +GLAD_API_CALL PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer; +#define glFeedbackBuffer glad_glFeedbackBuffer +GLAD_API_CALL PFNGLFENCESYNCPROC glad_glFenceSync; +#define glFenceSync glad_glFenceSync +GLAD_API_CALL PFNGLFINISHPROC glad_glFinish; +#define glFinish glad_glFinish +GLAD_API_CALL PFNGLFLUSHPROC glad_glFlush; +#define glFlush glad_glFlush +GLAD_API_CALL PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange; +#define glFlushMappedBufferRange glad_glFlushMappedBufferRange +GLAD_API_CALL PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glad_glFlushMappedNamedBufferRange; +#define glFlushMappedNamedBufferRange glad_glFlushMappedNamedBufferRange +GLAD_API_CALL PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC glad_glFlushMappedNamedBufferRangeEXT; +#define glFlushMappedNamedBufferRangeEXT glad_glFlushMappedNamedBufferRangeEXT +GLAD_API_CALL PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer; +#define glFogCoordPointer glad_glFogCoordPointer +GLAD_API_CALL PFNGLFOGCOORDDPROC glad_glFogCoordd; +#define glFogCoordd glad_glFogCoordd +GLAD_API_CALL PFNGLFOGCOORDDVPROC glad_glFogCoorddv; +#define glFogCoorddv glad_glFogCoorddv +GLAD_API_CALL PFNGLFOGCOORDFPROC glad_glFogCoordf; +#define glFogCoordf glad_glFogCoordf +GLAD_API_CALL PFNGLFOGCOORDFVPROC glad_glFogCoordfv; +#define glFogCoordfv glad_glFogCoordfv +GLAD_API_CALL PFNGLFOGFPROC glad_glFogf; +#define glFogf glad_glFogf +GLAD_API_CALL PFNGLFOGFVPROC glad_glFogfv; +#define glFogfv glad_glFogfv +GLAD_API_CALL PFNGLFOGIPROC glad_glFogi; +#define glFogi glad_glFogi +GLAD_API_CALL PFNGLFOGIVPROC glad_glFogiv; +#define glFogiv glad_glFogiv +GLAD_API_CALL PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC glad_glFramebufferDrawBufferEXT; +#define glFramebufferDrawBufferEXT glad_glFramebufferDrawBufferEXT +GLAD_API_CALL PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC glad_glFramebufferDrawBuffersEXT; +#define glFramebufferDrawBuffersEXT glad_glFramebufferDrawBuffersEXT +GLAD_API_CALL PFNGLFRAMEBUFFERPARAMETERIPROC glad_glFramebufferParameteri; +#define glFramebufferParameteri glad_glFramebufferParameteri +GLAD_API_CALL PFNGLFRAMEBUFFERREADBUFFEREXTPROC glad_glFramebufferReadBufferEXT; +#define glFramebufferReadBufferEXT glad_glFramebufferReadBufferEXT +GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer; +#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer +GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT; +#define glFramebufferRenderbufferEXT glad_glFramebufferRenderbufferEXT +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture; +#define glFramebufferTexture glad_glFramebufferTexture +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D; +#define glFramebufferTexture1D glad_glFramebufferTexture1D +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT; +#define glFramebufferTexture1DEXT glad_glFramebufferTexture1DEXT +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D; +#define glFramebufferTexture2D glad_glFramebufferTexture2D +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT; +#define glFramebufferTexture2DEXT glad_glFramebufferTexture2DEXT +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D; +#define glFramebufferTexture3D glad_glFramebufferTexture3D +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT; +#define glFramebufferTexture3DEXT glad_glFramebufferTexture3DEXT +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer; +#define glFramebufferTextureLayer glad_glFramebufferTextureLayer +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glad_glFramebufferTextureLayerEXT; +#define glFramebufferTextureLayerEXT glad_glFramebufferTextureLayerEXT +GLAD_API_CALL PFNGLFRONTFACEPROC glad_glFrontFace; +#define glFrontFace glad_glFrontFace +GLAD_API_CALL PFNGLFRUSTUMPROC glad_glFrustum; +#define glFrustum glad_glFrustum +GLAD_API_CALL PFNGLGENBUFFERSPROC glad_glGenBuffers; +#define glGenBuffers glad_glGenBuffers +GLAD_API_CALL PFNGLGENBUFFERSARBPROC glad_glGenBuffersARB; +#define glGenBuffersARB glad_glGenBuffersARB +GLAD_API_CALL PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers; +#define glGenFramebuffers glad_glGenFramebuffers +GLAD_API_CALL PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT; +#define glGenFramebuffersEXT glad_glGenFramebuffersEXT +GLAD_API_CALL PFNGLGENLISTSPROC glad_glGenLists; +#define glGenLists glad_glGenLists +GLAD_API_CALL PFNGLGENPROGRAMPIPELINESPROC glad_glGenProgramPipelines; +#define glGenProgramPipelines glad_glGenProgramPipelines +GLAD_API_CALL PFNGLGENPROGRAMSARBPROC glad_glGenProgramsARB; +#define glGenProgramsARB glad_glGenProgramsARB +GLAD_API_CALL PFNGLGENQUERIESPROC glad_glGenQueries; +#define glGenQueries glad_glGenQueries +GLAD_API_CALL PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers; +#define glGenRenderbuffers glad_glGenRenderbuffers +GLAD_API_CALL PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT; +#define glGenRenderbuffersEXT glad_glGenRenderbuffersEXT +GLAD_API_CALL PFNGLGENSAMPLERSPROC glad_glGenSamplers; +#define glGenSamplers glad_glGenSamplers +GLAD_API_CALL PFNGLGENTEXTURESPROC glad_glGenTextures; +#define glGenTextures glad_glGenTextures +GLAD_API_CALL PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks; +#define glGenTransformFeedbacks glad_glGenTransformFeedbacks +GLAD_API_CALL PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays; +#define glGenVertexArrays glad_glGenVertexArrays +GLAD_API_CALL PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap; +#define glGenerateMipmap glad_glGenerateMipmap +GLAD_API_CALL PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT; +#define glGenerateMipmapEXT glad_glGenerateMipmapEXT +GLAD_API_CALL PFNGLGENERATEMULTITEXMIPMAPEXTPROC glad_glGenerateMultiTexMipmapEXT; +#define glGenerateMultiTexMipmapEXT glad_glGenerateMultiTexMipmapEXT +GLAD_API_CALL PFNGLGENERATETEXTUREMIPMAPPROC glad_glGenerateTextureMipmap; +#define glGenerateTextureMipmap glad_glGenerateTextureMipmap +GLAD_API_CALL PFNGLGENERATETEXTUREMIPMAPEXTPROC glad_glGenerateTextureMipmapEXT; +#define glGenerateTextureMipmapEXT glad_glGenerateTextureMipmapEXT +GLAD_API_CALL PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC glad_glGetActiveAtomicCounterBufferiv; +#define glGetActiveAtomicCounterBufferiv glad_glGetActiveAtomicCounterBufferiv +GLAD_API_CALL PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib; +#define glGetActiveAttrib glad_glGetActiveAttrib +GLAD_API_CALL PFNGLGETACTIVEATTRIBARBPROC glad_glGetActiveAttribARB; +#define glGetActiveAttribARB glad_glGetActiveAttribARB +GLAD_API_CALL PFNGLGETACTIVESUBROUTINENAMEPROC glad_glGetActiveSubroutineName; +#define glGetActiveSubroutineName glad_glGetActiveSubroutineName +GLAD_API_CALL PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC glad_glGetActiveSubroutineUniformName; +#define glGetActiveSubroutineUniformName glad_glGetActiveSubroutineUniformName +GLAD_API_CALL PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC glad_glGetActiveSubroutineUniformiv; +#define glGetActiveSubroutineUniformiv glad_glGetActiveSubroutineUniformiv +GLAD_API_CALL PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform; +#define glGetActiveUniform glad_glGetActiveUniform +GLAD_API_CALL PFNGLGETACTIVEUNIFORMARBPROC glad_glGetActiveUniformARB; +#define glGetActiveUniformARB glad_glGetActiveUniformARB +GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName; +#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName +GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv; +#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv +GLAD_API_CALL PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName; +#define glGetActiveUniformName glad_glGetActiveUniformName +GLAD_API_CALL PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv; +#define glGetActiveUniformsiv glad_glGetActiveUniformsiv +GLAD_API_CALL PFNGLGETATTACHEDOBJECTSARBPROC glad_glGetAttachedObjectsARB; +#define glGetAttachedObjectsARB glad_glGetAttachedObjectsARB +GLAD_API_CALL PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders; +#define glGetAttachedShaders glad_glGetAttachedShaders +GLAD_API_CALL PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation; +#define glGetAttribLocation glad_glGetAttribLocation +GLAD_API_CALL PFNGLGETATTRIBLOCATIONARBPROC glad_glGetAttribLocationARB; +#define glGetAttribLocationARB glad_glGetAttribLocationARB +GLAD_API_CALL PFNGLGETBOOLEANINDEXEDVEXTPROC glad_glGetBooleanIndexedvEXT; +#define glGetBooleanIndexedvEXT glad_glGetBooleanIndexedvEXT +GLAD_API_CALL PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v; +#define glGetBooleani_v glad_glGetBooleani_v +GLAD_API_CALL PFNGLGETBOOLEANVPROC glad_glGetBooleanv; +#define glGetBooleanv glad_glGetBooleanv +GLAD_API_CALL PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v; +#define glGetBufferParameteri64v glad_glGetBufferParameteri64v +GLAD_API_CALL PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv; +#define glGetBufferParameteriv glad_glGetBufferParameteriv +GLAD_API_CALL PFNGLGETBUFFERPARAMETERIVARBPROC glad_glGetBufferParameterivARB; +#define glGetBufferParameterivARB glad_glGetBufferParameterivARB +GLAD_API_CALL PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv; +#define glGetBufferPointerv glad_glGetBufferPointerv +GLAD_API_CALL PFNGLGETBUFFERPOINTERVARBPROC glad_glGetBufferPointervARB; +#define glGetBufferPointervARB glad_glGetBufferPointervARB +GLAD_API_CALL PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData; +#define glGetBufferSubData glad_glGetBufferSubData +GLAD_API_CALL PFNGLGETBUFFERSUBDATAARBPROC glad_glGetBufferSubDataARB; +#define glGetBufferSubDataARB glad_glGetBufferSubDataARB +GLAD_API_CALL PFNGLGETCLIPPLANEPROC glad_glGetClipPlane; +#define glGetClipPlane glad_glGetClipPlane +GLAD_API_CALL PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC glad_glGetCompressedMultiTexImageEXT; +#define glGetCompressedMultiTexImageEXT glad_glGetCompressedMultiTexImageEXT +GLAD_API_CALL PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage; +#define glGetCompressedTexImage glad_glGetCompressedTexImage +GLAD_API_CALL PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glad_glGetCompressedTextureImage; +#define glGetCompressedTextureImage glad_glGetCompressedTextureImage +GLAD_API_CALL PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC glad_glGetCompressedTextureImageEXT; +#define glGetCompressedTextureImageEXT glad_glGetCompressedTextureImageEXT +GLAD_API_CALL PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glad_glGetCompressedTextureSubImage; +#define glGetCompressedTextureSubImage glad_glGetCompressedTextureSubImage +GLAD_API_CALL PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog; +#define glGetDebugMessageLog glad_glGetDebugMessageLog +GLAD_API_CALL PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB; +#define glGetDebugMessageLogARB glad_glGetDebugMessageLogARB +GLAD_API_CALL PFNGLGETDOUBLEINDEXEDVEXTPROC glad_glGetDoubleIndexedvEXT; +#define glGetDoubleIndexedvEXT glad_glGetDoubleIndexedvEXT +GLAD_API_CALL PFNGLGETDOUBLEI_VPROC glad_glGetDoublei_v; +#define glGetDoublei_v glad_glGetDoublei_v +GLAD_API_CALL PFNGLGETDOUBLEI_VEXTPROC glad_glGetDoublei_vEXT; +#define glGetDoublei_vEXT glad_glGetDoublei_vEXT +GLAD_API_CALL PFNGLGETDOUBLEVPROC glad_glGetDoublev; +#define glGetDoublev glad_glGetDoublev +GLAD_API_CALL PFNGLGETERRORPROC glad_glGetError; +#define glGetError glad_glGetError +GLAD_API_CALL PFNGLGETFLOATINDEXEDVEXTPROC glad_glGetFloatIndexedvEXT; +#define glGetFloatIndexedvEXT glad_glGetFloatIndexedvEXT +GLAD_API_CALL PFNGLGETFLOATI_VPROC glad_glGetFloati_v; +#define glGetFloati_v glad_glGetFloati_v +GLAD_API_CALL PFNGLGETFLOATI_VEXTPROC glad_glGetFloati_vEXT; +#define glGetFloati_vEXT glad_glGetFloati_vEXT +GLAD_API_CALL PFNGLGETFLOATVPROC glad_glGetFloatv; +#define glGetFloatv glad_glGetFloatv +GLAD_API_CALL PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex; +#define glGetFragDataIndex glad_glGetFragDataIndex +GLAD_API_CALL PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation; +#define glGetFragDataLocation glad_glGetFragDataLocation +GLAD_API_CALL PFNGLGETFRAGDATALOCATIONEXTPROC glad_glGetFragDataLocationEXT; +#define glGetFragDataLocationEXT glad_glGetFragDataLocationEXT +GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv; +#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv +GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT; +#define glGetFramebufferAttachmentParameterivEXT glad_glGetFramebufferAttachmentParameterivEXT +GLAD_API_CALL PFNGLGETFRAMEBUFFERPARAMETERIVPROC glad_glGetFramebufferParameteriv; +#define glGetFramebufferParameteriv glad_glGetFramebufferParameteriv +GLAD_API_CALL PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC glad_glGetFramebufferParameterivEXT; +#define glGetFramebufferParameterivEXT glad_glGetFramebufferParameterivEXT +GLAD_API_CALL PFNGLGETGRAPHICSRESETSTATUSPROC glad_glGetGraphicsResetStatus; +#define glGetGraphicsResetStatus glad_glGetGraphicsResetStatus +GLAD_API_CALL PFNGLGETHANDLEARBPROC glad_glGetHandleARB; +#define glGetHandleARB glad_glGetHandleARB +GLAD_API_CALL PFNGLGETINFOLOGARBPROC glad_glGetInfoLogARB; +#define glGetInfoLogARB glad_glGetInfoLogARB +GLAD_API_CALL PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v; +#define glGetInteger64i_v glad_glGetInteger64i_v +GLAD_API_CALL PFNGLGETINTEGER64VPROC glad_glGetInteger64v; +#define glGetInteger64v glad_glGetInteger64v +GLAD_API_CALL PFNGLGETINTEGERINDEXEDVEXTPROC glad_glGetIntegerIndexedvEXT; +#define glGetIntegerIndexedvEXT glad_glGetIntegerIndexedvEXT +GLAD_API_CALL PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v; +#define glGetIntegeri_v glad_glGetIntegeri_v +GLAD_API_CALL PFNGLGETINTEGERVPROC glad_glGetIntegerv; +#define glGetIntegerv glad_glGetIntegerv +GLAD_API_CALL PFNGLGETINTERNALFORMATI64VPROC glad_glGetInternalformati64v; +#define glGetInternalformati64v glad_glGetInternalformati64v +GLAD_API_CALL PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ; +#define glGetInternalformativ glad_glGetInternalformativ +GLAD_API_CALL PFNGLGETLIGHTFVPROC glad_glGetLightfv; +#define glGetLightfv glad_glGetLightfv +GLAD_API_CALL PFNGLGETLIGHTIVPROC glad_glGetLightiv; +#define glGetLightiv glad_glGetLightiv +GLAD_API_CALL PFNGLGETMAPDVPROC glad_glGetMapdv; +#define glGetMapdv glad_glGetMapdv +GLAD_API_CALL PFNGLGETMAPFVPROC glad_glGetMapfv; +#define glGetMapfv glad_glGetMapfv +GLAD_API_CALL PFNGLGETMAPIVPROC glad_glGetMapiv; +#define glGetMapiv glad_glGetMapiv +GLAD_API_CALL PFNGLGETMATERIALFVPROC glad_glGetMaterialfv; +#define glGetMaterialfv glad_glGetMaterialfv +GLAD_API_CALL PFNGLGETMATERIALIVPROC glad_glGetMaterialiv; +#define glGetMaterialiv glad_glGetMaterialiv +GLAD_API_CALL PFNGLGETMULTITEXENVFVEXTPROC glad_glGetMultiTexEnvfvEXT; +#define glGetMultiTexEnvfvEXT glad_glGetMultiTexEnvfvEXT +GLAD_API_CALL PFNGLGETMULTITEXENVIVEXTPROC glad_glGetMultiTexEnvivEXT; +#define glGetMultiTexEnvivEXT glad_glGetMultiTexEnvivEXT +GLAD_API_CALL PFNGLGETMULTITEXGENDVEXTPROC glad_glGetMultiTexGendvEXT; +#define glGetMultiTexGendvEXT glad_glGetMultiTexGendvEXT +GLAD_API_CALL PFNGLGETMULTITEXGENFVEXTPROC glad_glGetMultiTexGenfvEXT; +#define glGetMultiTexGenfvEXT glad_glGetMultiTexGenfvEXT +GLAD_API_CALL PFNGLGETMULTITEXGENIVEXTPROC glad_glGetMultiTexGenivEXT; +#define glGetMultiTexGenivEXT glad_glGetMultiTexGenivEXT +GLAD_API_CALL PFNGLGETMULTITEXIMAGEEXTPROC glad_glGetMultiTexImageEXT; +#define glGetMultiTexImageEXT glad_glGetMultiTexImageEXT +GLAD_API_CALL PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC glad_glGetMultiTexLevelParameterfvEXT; +#define glGetMultiTexLevelParameterfvEXT glad_glGetMultiTexLevelParameterfvEXT +GLAD_API_CALL PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC glad_glGetMultiTexLevelParameterivEXT; +#define glGetMultiTexLevelParameterivEXT glad_glGetMultiTexLevelParameterivEXT +GLAD_API_CALL PFNGLGETMULTITEXPARAMETERIIVEXTPROC glad_glGetMultiTexParameterIivEXT; +#define glGetMultiTexParameterIivEXT glad_glGetMultiTexParameterIivEXT +GLAD_API_CALL PFNGLGETMULTITEXPARAMETERIUIVEXTPROC glad_glGetMultiTexParameterIuivEXT; +#define glGetMultiTexParameterIuivEXT glad_glGetMultiTexParameterIuivEXT +GLAD_API_CALL PFNGLGETMULTITEXPARAMETERFVEXTPROC glad_glGetMultiTexParameterfvEXT; +#define glGetMultiTexParameterfvEXT glad_glGetMultiTexParameterfvEXT +GLAD_API_CALL PFNGLGETMULTITEXPARAMETERIVEXTPROC glad_glGetMultiTexParameterivEXT; +#define glGetMultiTexParameterivEXT glad_glGetMultiTexParameterivEXT +GLAD_API_CALL PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv; +#define glGetMultisamplefv glad_glGetMultisamplefv +GLAD_API_CALL PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glad_glGetNamedBufferParameteri64v; +#define glGetNamedBufferParameteri64v glad_glGetNamedBufferParameteri64v +GLAD_API_CALL PFNGLGETNAMEDBUFFERPARAMETERIVPROC glad_glGetNamedBufferParameteriv; +#define glGetNamedBufferParameteriv glad_glGetNamedBufferParameteriv +GLAD_API_CALL PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC glad_glGetNamedBufferParameterivEXT; +#define glGetNamedBufferParameterivEXT glad_glGetNamedBufferParameterivEXT +GLAD_API_CALL PFNGLGETNAMEDBUFFERPOINTERVPROC glad_glGetNamedBufferPointerv; +#define glGetNamedBufferPointerv glad_glGetNamedBufferPointerv +GLAD_API_CALL PFNGLGETNAMEDBUFFERPOINTERVEXTPROC glad_glGetNamedBufferPointervEXT; +#define glGetNamedBufferPointervEXT glad_glGetNamedBufferPointervEXT +GLAD_API_CALL PFNGLGETNAMEDBUFFERSUBDATAPROC glad_glGetNamedBufferSubData; +#define glGetNamedBufferSubData glad_glGetNamedBufferSubData +GLAD_API_CALL PFNGLGETNAMEDBUFFERSUBDATAEXTPROC glad_glGetNamedBufferSubDataEXT; +#define glGetNamedBufferSubDataEXT glad_glGetNamedBufferSubDataEXT +GLAD_API_CALL PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetNamedFramebufferAttachmentParameteriv; +#define glGetNamedFramebufferAttachmentParameteriv glad_glGetNamedFramebufferAttachmentParameteriv +GLAD_API_CALL PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetNamedFramebufferAttachmentParameterivEXT; +#define glGetNamedFramebufferAttachmentParameterivEXT glad_glGetNamedFramebufferAttachmentParameterivEXT +GLAD_API_CALL PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glad_glGetNamedFramebufferParameteriv; +#define glGetNamedFramebufferParameteriv glad_glGetNamedFramebufferParameteriv +GLAD_API_CALL PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC glad_glGetNamedFramebufferParameterivEXT; +#define glGetNamedFramebufferParameterivEXT glad_glGetNamedFramebufferParameterivEXT +GLAD_API_CALL PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC glad_glGetNamedProgramLocalParameterIivEXT; +#define glGetNamedProgramLocalParameterIivEXT glad_glGetNamedProgramLocalParameterIivEXT +GLAD_API_CALL PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC glad_glGetNamedProgramLocalParameterIuivEXT; +#define glGetNamedProgramLocalParameterIuivEXT glad_glGetNamedProgramLocalParameterIuivEXT +GLAD_API_CALL PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC glad_glGetNamedProgramLocalParameterdvEXT; +#define glGetNamedProgramLocalParameterdvEXT glad_glGetNamedProgramLocalParameterdvEXT +GLAD_API_CALL PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC glad_glGetNamedProgramLocalParameterfvEXT; +#define glGetNamedProgramLocalParameterfvEXT glad_glGetNamedProgramLocalParameterfvEXT +GLAD_API_CALL PFNGLGETNAMEDPROGRAMSTRINGEXTPROC glad_glGetNamedProgramStringEXT; +#define glGetNamedProgramStringEXT glad_glGetNamedProgramStringEXT +GLAD_API_CALL PFNGLGETNAMEDPROGRAMIVEXTPROC glad_glGetNamedProgramivEXT; +#define glGetNamedProgramivEXT glad_glGetNamedProgramivEXT +GLAD_API_CALL PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glad_glGetNamedRenderbufferParameteriv; +#define glGetNamedRenderbufferParameteriv glad_glGetNamedRenderbufferParameteriv +GLAD_API_CALL PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC glad_glGetNamedRenderbufferParameterivEXT; +#define glGetNamedRenderbufferParameterivEXT glad_glGetNamedRenderbufferParameterivEXT +GLAD_API_CALL PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel; +#define glGetObjectLabel glad_glGetObjectLabel +GLAD_API_CALL PFNGLGETOBJECTPARAMETERFVARBPROC glad_glGetObjectParameterfvARB; +#define glGetObjectParameterfvARB glad_glGetObjectParameterfvARB +GLAD_API_CALL PFNGLGETOBJECTPARAMETERIVARBPROC glad_glGetObjectParameterivARB; +#define glGetObjectParameterivARB glad_glGetObjectParameterivARB +GLAD_API_CALL PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel; +#define glGetObjectPtrLabel glad_glGetObjectPtrLabel +GLAD_API_CALL PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv; +#define glGetPixelMapfv glad_glGetPixelMapfv +GLAD_API_CALL PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv; +#define glGetPixelMapuiv glad_glGetPixelMapuiv +GLAD_API_CALL PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv; +#define glGetPixelMapusv glad_glGetPixelMapusv +GLAD_API_CALL PFNGLGETPOINTERINDEXEDVEXTPROC glad_glGetPointerIndexedvEXT; +#define glGetPointerIndexedvEXT glad_glGetPointerIndexedvEXT +GLAD_API_CALL PFNGLGETPOINTERI_VEXTPROC glad_glGetPointeri_vEXT; +#define glGetPointeri_vEXT glad_glGetPointeri_vEXT +GLAD_API_CALL PFNGLGETPOINTERVPROC glad_glGetPointerv; +#define glGetPointerv glad_glGetPointerv +GLAD_API_CALL PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple; +#define glGetPolygonStipple glad_glGetPolygonStipple +GLAD_API_CALL PFNGLGETPROGRAMBINARYPROC glad_glGetProgramBinary; +#define glGetProgramBinary glad_glGetProgramBinary +GLAD_API_CALL PFNGLGETPROGRAMENVPARAMETERDVARBPROC glad_glGetProgramEnvParameterdvARB; +#define glGetProgramEnvParameterdvARB glad_glGetProgramEnvParameterdvARB +GLAD_API_CALL PFNGLGETPROGRAMENVPARAMETERFVARBPROC glad_glGetProgramEnvParameterfvARB; +#define glGetProgramEnvParameterfvARB glad_glGetProgramEnvParameterfvARB +GLAD_API_CALL PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog; +#define glGetProgramInfoLog glad_glGetProgramInfoLog +GLAD_API_CALL PFNGLGETPROGRAMINTERFACEIVPROC glad_glGetProgramInterfaceiv; +#define glGetProgramInterfaceiv glad_glGetProgramInterfaceiv +GLAD_API_CALL PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glad_glGetProgramLocalParameterdvARB; +#define glGetProgramLocalParameterdvARB glad_glGetProgramLocalParameterdvARB +GLAD_API_CALL PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glad_glGetProgramLocalParameterfvARB; +#define glGetProgramLocalParameterfvARB glad_glGetProgramLocalParameterfvARB +GLAD_API_CALL PFNGLGETPROGRAMPIPELINEINFOLOGPROC glad_glGetProgramPipelineInfoLog; +#define glGetProgramPipelineInfoLog glad_glGetProgramPipelineInfoLog +GLAD_API_CALL PFNGLGETPROGRAMPIPELINEIVPROC glad_glGetProgramPipelineiv; +#define glGetProgramPipelineiv glad_glGetProgramPipelineiv +GLAD_API_CALL PFNGLGETPROGRAMRESOURCEINDEXPROC glad_glGetProgramResourceIndex; +#define glGetProgramResourceIndex glad_glGetProgramResourceIndex +GLAD_API_CALL PFNGLGETPROGRAMRESOURCELOCATIONPROC glad_glGetProgramResourceLocation; +#define glGetProgramResourceLocation glad_glGetProgramResourceLocation +GLAD_API_CALL PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC glad_glGetProgramResourceLocationIndex; +#define glGetProgramResourceLocationIndex glad_glGetProgramResourceLocationIndex +GLAD_API_CALL PFNGLGETPROGRAMRESOURCENAMEPROC glad_glGetProgramResourceName; +#define glGetProgramResourceName glad_glGetProgramResourceName +GLAD_API_CALL PFNGLGETPROGRAMRESOURCEIVPROC glad_glGetProgramResourceiv; +#define glGetProgramResourceiv glad_glGetProgramResourceiv +GLAD_API_CALL PFNGLGETPROGRAMSTAGEIVPROC glad_glGetProgramStageiv; +#define glGetProgramStageiv glad_glGetProgramStageiv +GLAD_API_CALL PFNGLGETPROGRAMSTRINGARBPROC glad_glGetProgramStringARB; +#define glGetProgramStringARB glad_glGetProgramStringARB +GLAD_API_CALL PFNGLGETPROGRAMIVPROC glad_glGetProgramiv; +#define glGetProgramiv glad_glGetProgramiv +GLAD_API_CALL PFNGLGETPROGRAMIVARBPROC glad_glGetProgramivARB; +#define glGetProgramivARB glad_glGetProgramivARB +GLAD_API_CALL PFNGLGETQUERYBUFFEROBJECTI64VPROC glad_glGetQueryBufferObjecti64v; +#define glGetQueryBufferObjecti64v glad_glGetQueryBufferObjecti64v +GLAD_API_CALL PFNGLGETQUERYBUFFEROBJECTIVPROC glad_glGetQueryBufferObjectiv; +#define glGetQueryBufferObjectiv glad_glGetQueryBufferObjectiv +GLAD_API_CALL PFNGLGETQUERYBUFFEROBJECTUI64VPROC glad_glGetQueryBufferObjectui64v; +#define glGetQueryBufferObjectui64v glad_glGetQueryBufferObjectui64v +GLAD_API_CALL PFNGLGETQUERYBUFFEROBJECTUIVPROC glad_glGetQueryBufferObjectuiv; +#define glGetQueryBufferObjectuiv glad_glGetQueryBufferObjectuiv +GLAD_API_CALL PFNGLGETQUERYINDEXEDIVPROC glad_glGetQueryIndexediv; +#define glGetQueryIndexediv glad_glGetQueryIndexediv +GLAD_API_CALL PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v; +#define glGetQueryObjecti64v glad_glGetQueryObjecti64v +GLAD_API_CALL PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv; +#define glGetQueryObjectiv glad_glGetQueryObjectiv +GLAD_API_CALL PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v; +#define glGetQueryObjectui64v glad_glGetQueryObjectui64v +GLAD_API_CALL PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv; +#define glGetQueryObjectuiv glad_glGetQueryObjectuiv +GLAD_API_CALL PFNGLGETQUERYIVPROC glad_glGetQueryiv; +#define glGetQueryiv glad_glGetQueryiv +GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv; +#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv +GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT; +#define glGetRenderbufferParameterivEXT glad_glGetRenderbufferParameterivEXT +GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv; +#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv +GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv; +#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv +GLAD_API_CALL PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv; +#define glGetSamplerParameterfv glad_glGetSamplerParameterfv +GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv; +#define glGetSamplerParameteriv glad_glGetSamplerParameteriv +GLAD_API_CALL PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog; +#define glGetShaderInfoLog glad_glGetShaderInfoLog +GLAD_API_CALL PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat; +#define glGetShaderPrecisionFormat glad_glGetShaderPrecisionFormat +GLAD_API_CALL PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource; +#define glGetShaderSource glad_glGetShaderSource +GLAD_API_CALL PFNGLGETSHADERSOURCEARBPROC glad_glGetShaderSourceARB; +#define glGetShaderSourceARB glad_glGetShaderSourceARB +GLAD_API_CALL PFNGLGETSHADERIVPROC glad_glGetShaderiv; +#define glGetShaderiv glad_glGetShaderiv +GLAD_API_CALL PFNGLGETSTRINGPROC glad_glGetString; +#define glGetString glad_glGetString +GLAD_API_CALL PFNGLGETSTRINGIPROC glad_glGetStringi; +#define glGetStringi glad_glGetStringi +GLAD_API_CALL PFNGLGETSUBROUTINEINDEXPROC glad_glGetSubroutineIndex; +#define glGetSubroutineIndex glad_glGetSubroutineIndex +GLAD_API_CALL PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC glad_glGetSubroutineUniformLocation; +#define glGetSubroutineUniformLocation glad_glGetSubroutineUniformLocation +GLAD_API_CALL PFNGLGETSYNCIVPROC glad_glGetSynciv; +#define glGetSynciv glad_glGetSynciv +GLAD_API_CALL PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv; +#define glGetTexEnvfv glad_glGetTexEnvfv +GLAD_API_CALL PFNGLGETTEXENVIVPROC glad_glGetTexEnviv; +#define glGetTexEnviv glad_glGetTexEnviv +GLAD_API_CALL PFNGLGETTEXGENDVPROC glad_glGetTexGendv; +#define glGetTexGendv glad_glGetTexGendv +GLAD_API_CALL PFNGLGETTEXGENFVPROC glad_glGetTexGenfv; +#define glGetTexGenfv glad_glGetTexGenfv +GLAD_API_CALL PFNGLGETTEXGENIVPROC glad_glGetTexGeniv; +#define glGetTexGeniv glad_glGetTexGeniv +GLAD_API_CALL PFNGLGETTEXIMAGEPROC glad_glGetTexImage; +#define glGetTexImage glad_glGetTexImage +GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv; +#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv +GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv; +#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv +GLAD_API_CALL PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv; +#define glGetTexParameterIiv glad_glGetTexParameterIiv +GLAD_API_CALL PFNGLGETTEXPARAMETERIIVEXTPROC glad_glGetTexParameterIivEXT; +#define glGetTexParameterIivEXT glad_glGetTexParameterIivEXT +GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv; +#define glGetTexParameterIuiv glad_glGetTexParameterIuiv +GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVEXTPROC glad_glGetTexParameterIuivEXT; +#define glGetTexParameterIuivEXT glad_glGetTexParameterIuivEXT +GLAD_API_CALL PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv; +#define glGetTexParameterfv glad_glGetTexParameterfv +GLAD_API_CALL PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv; +#define glGetTexParameteriv glad_glGetTexParameteriv +GLAD_API_CALL PFNGLGETTEXTUREIMAGEPROC glad_glGetTextureImage; +#define glGetTextureImage glad_glGetTextureImage +GLAD_API_CALL PFNGLGETTEXTUREIMAGEEXTPROC glad_glGetTextureImageEXT; +#define glGetTextureImageEXT glad_glGetTextureImageEXT +GLAD_API_CALL PFNGLGETTEXTURELEVELPARAMETERFVPROC glad_glGetTextureLevelParameterfv; +#define glGetTextureLevelParameterfv glad_glGetTextureLevelParameterfv +GLAD_API_CALL PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC glad_glGetTextureLevelParameterfvEXT; +#define glGetTextureLevelParameterfvEXT glad_glGetTextureLevelParameterfvEXT +GLAD_API_CALL PFNGLGETTEXTURELEVELPARAMETERIVPROC glad_glGetTextureLevelParameteriv; +#define glGetTextureLevelParameteriv glad_glGetTextureLevelParameteriv +GLAD_API_CALL PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC glad_glGetTextureLevelParameterivEXT; +#define glGetTextureLevelParameterivEXT glad_glGetTextureLevelParameterivEXT +GLAD_API_CALL PFNGLGETTEXTUREPARAMETERIIVPROC glad_glGetTextureParameterIiv; +#define glGetTextureParameterIiv glad_glGetTextureParameterIiv +GLAD_API_CALL PFNGLGETTEXTUREPARAMETERIIVEXTPROC glad_glGetTextureParameterIivEXT; +#define glGetTextureParameterIivEXT glad_glGetTextureParameterIivEXT +GLAD_API_CALL PFNGLGETTEXTUREPARAMETERIUIVPROC glad_glGetTextureParameterIuiv; +#define glGetTextureParameterIuiv glad_glGetTextureParameterIuiv +GLAD_API_CALL PFNGLGETTEXTUREPARAMETERIUIVEXTPROC glad_glGetTextureParameterIuivEXT; +#define glGetTextureParameterIuivEXT glad_glGetTextureParameterIuivEXT +GLAD_API_CALL PFNGLGETTEXTUREPARAMETERFVPROC glad_glGetTextureParameterfv; +#define glGetTextureParameterfv glad_glGetTextureParameterfv +GLAD_API_CALL PFNGLGETTEXTUREPARAMETERFVEXTPROC glad_glGetTextureParameterfvEXT; +#define glGetTextureParameterfvEXT glad_glGetTextureParameterfvEXT +GLAD_API_CALL PFNGLGETTEXTUREPARAMETERIVPROC glad_glGetTextureParameteriv; +#define glGetTextureParameteriv glad_glGetTextureParameteriv +GLAD_API_CALL PFNGLGETTEXTUREPARAMETERIVEXTPROC glad_glGetTextureParameterivEXT; +#define glGetTextureParameterivEXT glad_glGetTextureParameterivEXT +GLAD_API_CALL PFNGLGETTEXTURESUBIMAGEPROC glad_glGetTextureSubImage; +#define glGetTextureSubImage glad_glGetTextureSubImage +GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying; +#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying +GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC glad_glGetTransformFeedbackVaryingEXT; +#define glGetTransformFeedbackVaryingEXT glad_glGetTransformFeedbackVaryingEXT +GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKI64_VPROC glad_glGetTransformFeedbacki64_v; +#define glGetTransformFeedbacki64_v glad_glGetTransformFeedbacki64_v +GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKI_VPROC glad_glGetTransformFeedbacki_v; +#define glGetTransformFeedbacki_v glad_glGetTransformFeedbacki_v +GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKIVPROC glad_glGetTransformFeedbackiv; +#define glGetTransformFeedbackiv glad_glGetTransformFeedbackiv +GLAD_API_CALL PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex; +#define glGetUniformBlockIndex glad_glGetUniformBlockIndex +GLAD_API_CALL PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices; +#define glGetUniformIndices glad_glGetUniformIndices +GLAD_API_CALL PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation; +#define glGetUniformLocation glad_glGetUniformLocation +GLAD_API_CALL PFNGLGETUNIFORMLOCATIONARBPROC glad_glGetUniformLocationARB; +#define glGetUniformLocationARB glad_glGetUniformLocationARB +GLAD_API_CALL PFNGLGETUNIFORMSUBROUTINEUIVPROC glad_glGetUniformSubroutineuiv; +#define glGetUniformSubroutineuiv glad_glGetUniformSubroutineuiv +GLAD_API_CALL PFNGLGETUNIFORMDVPROC glad_glGetUniformdv; +#define glGetUniformdv glad_glGetUniformdv +GLAD_API_CALL PFNGLGETUNIFORMFVPROC glad_glGetUniformfv; +#define glGetUniformfv glad_glGetUniformfv +GLAD_API_CALL PFNGLGETUNIFORMFVARBPROC glad_glGetUniformfvARB; +#define glGetUniformfvARB glad_glGetUniformfvARB +GLAD_API_CALL PFNGLGETUNIFORMIVPROC glad_glGetUniformiv; +#define glGetUniformiv glad_glGetUniformiv +GLAD_API_CALL PFNGLGETUNIFORMIVARBPROC glad_glGetUniformivARB; +#define glGetUniformivARB glad_glGetUniformivARB +GLAD_API_CALL PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv; +#define glGetUniformuiv glad_glGetUniformuiv +GLAD_API_CALL PFNGLGETUNIFORMUIVEXTPROC glad_glGetUniformuivEXT; +#define glGetUniformuivEXT glad_glGetUniformuivEXT +GLAD_API_CALL PFNGLGETVERTEXARRAYINDEXED64IVPROC glad_glGetVertexArrayIndexed64iv; +#define glGetVertexArrayIndexed64iv glad_glGetVertexArrayIndexed64iv +GLAD_API_CALL PFNGLGETVERTEXARRAYINDEXEDIVPROC glad_glGetVertexArrayIndexediv; +#define glGetVertexArrayIndexediv glad_glGetVertexArrayIndexediv +GLAD_API_CALL PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC glad_glGetVertexArrayIntegeri_vEXT; +#define glGetVertexArrayIntegeri_vEXT glad_glGetVertexArrayIntegeri_vEXT +GLAD_API_CALL PFNGLGETVERTEXARRAYINTEGERVEXTPROC glad_glGetVertexArrayIntegervEXT; +#define glGetVertexArrayIntegervEXT glad_glGetVertexArrayIntegervEXT +GLAD_API_CALL PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC glad_glGetVertexArrayPointeri_vEXT; +#define glGetVertexArrayPointeri_vEXT glad_glGetVertexArrayPointeri_vEXT +GLAD_API_CALL PFNGLGETVERTEXARRAYPOINTERVEXTPROC glad_glGetVertexArrayPointervEXT; +#define glGetVertexArrayPointervEXT glad_glGetVertexArrayPointervEXT +GLAD_API_CALL PFNGLGETVERTEXARRAYIVPROC glad_glGetVertexArrayiv; +#define glGetVertexArrayiv glad_glGetVertexArrayiv +GLAD_API_CALL PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv; +#define glGetVertexAttribIiv glad_glGetVertexAttribIiv +GLAD_API_CALL PFNGLGETVERTEXATTRIBIIVEXTPROC glad_glGetVertexAttribIivEXT; +#define glGetVertexAttribIivEXT glad_glGetVertexAttribIivEXT +GLAD_API_CALL PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv; +#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv +GLAD_API_CALL PFNGLGETVERTEXATTRIBIUIVEXTPROC glad_glGetVertexAttribIuivEXT; +#define glGetVertexAttribIuivEXT glad_glGetVertexAttribIuivEXT +GLAD_API_CALL PFNGLGETVERTEXATTRIBLDVPROC glad_glGetVertexAttribLdv; +#define glGetVertexAttribLdv glad_glGetVertexAttribLdv +GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv; +#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv +GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVARBPROC glad_glGetVertexAttribPointervARB; +#define glGetVertexAttribPointervARB glad_glGetVertexAttribPointervARB +GLAD_API_CALL PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv; +#define glGetVertexAttribdv glad_glGetVertexAttribdv +GLAD_API_CALL PFNGLGETVERTEXATTRIBDVARBPROC glad_glGetVertexAttribdvARB; +#define glGetVertexAttribdvARB glad_glGetVertexAttribdvARB +GLAD_API_CALL PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv; +#define glGetVertexAttribfv glad_glGetVertexAttribfv +GLAD_API_CALL PFNGLGETVERTEXATTRIBFVARBPROC glad_glGetVertexAttribfvARB; +#define glGetVertexAttribfvARB glad_glGetVertexAttribfvARB +GLAD_API_CALL PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv; +#define glGetVertexAttribiv glad_glGetVertexAttribiv +GLAD_API_CALL PFNGLGETVERTEXATTRIBIVARBPROC glad_glGetVertexAttribivARB; +#define glGetVertexAttribivARB glad_glGetVertexAttribivARB +GLAD_API_CALL PFNGLGETNCOLORTABLEPROC glad_glGetnColorTable; +#define glGetnColorTable glad_glGetnColorTable +GLAD_API_CALL PFNGLGETNCOMPRESSEDTEXIMAGEPROC glad_glGetnCompressedTexImage; +#define glGetnCompressedTexImage glad_glGetnCompressedTexImage +GLAD_API_CALL PFNGLGETNCONVOLUTIONFILTERPROC glad_glGetnConvolutionFilter; +#define glGetnConvolutionFilter glad_glGetnConvolutionFilter +GLAD_API_CALL PFNGLGETNHISTOGRAMPROC glad_glGetnHistogram; +#define glGetnHistogram glad_glGetnHistogram +GLAD_API_CALL PFNGLGETNMAPDVPROC glad_glGetnMapdv; +#define glGetnMapdv glad_glGetnMapdv +GLAD_API_CALL PFNGLGETNMAPFVPROC glad_glGetnMapfv; +#define glGetnMapfv glad_glGetnMapfv +GLAD_API_CALL PFNGLGETNMAPIVPROC glad_glGetnMapiv; +#define glGetnMapiv glad_glGetnMapiv +GLAD_API_CALL PFNGLGETNMINMAXPROC glad_glGetnMinmax; +#define glGetnMinmax glad_glGetnMinmax +GLAD_API_CALL PFNGLGETNPIXELMAPFVPROC glad_glGetnPixelMapfv; +#define glGetnPixelMapfv glad_glGetnPixelMapfv +GLAD_API_CALL PFNGLGETNPIXELMAPUIVPROC glad_glGetnPixelMapuiv; +#define glGetnPixelMapuiv glad_glGetnPixelMapuiv +GLAD_API_CALL PFNGLGETNPIXELMAPUSVPROC glad_glGetnPixelMapusv; +#define glGetnPixelMapusv glad_glGetnPixelMapusv +GLAD_API_CALL PFNGLGETNPOLYGONSTIPPLEPROC glad_glGetnPolygonStipple; +#define glGetnPolygonStipple glad_glGetnPolygonStipple +GLAD_API_CALL PFNGLGETNSEPARABLEFILTERPROC glad_glGetnSeparableFilter; +#define glGetnSeparableFilter glad_glGetnSeparableFilter +GLAD_API_CALL PFNGLGETNTEXIMAGEPROC glad_glGetnTexImage; +#define glGetnTexImage glad_glGetnTexImage +GLAD_API_CALL PFNGLGETNUNIFORMDVPROC glad_glGetnUniformdv; +#define glGetnUniformdv glad_glGetnUniformdv +GLAD_API_CALL PFNGLGETNUNIFORMFVPROC glad_glGetnUniformfv; +#define glGetnUniformfv glad_glGetnUniformfv +GLAD_API_CALL PFNGLGETNUNIFORMIVPROC glad_glGetnUniformiv; +#define glGetnUniformiv glad_glGetnUniformiv +GLAD_API_CALL PFNGLGETNUNIFORMUIVPROC glad_glGetnUniformuiv; +#define glGetnUniformuiv glad_glGetnUniformuiv +GLAD_API_CALL PFNGLHINTPROC glad_glHint; +#define glHint glad_glHint +GLAD_API_CALL PFNGLINDEXMASKPROC glad_glIndexMask; +#define glIndexMask glad_glIndexMask +GLAD_API_CALL PFNGLINDEXPOINTERPROC glad_glIndexPointer; +#define glIndexPointer glad_glIndexPointer +GLAD_API_CALL PFNGLINDEXDPROC glad_glIndexd; +#define glIndexd glad_glIndexd +GLAD_API_CALL PFNGLINDEXDVPROC glad_glIndexdv; +#define glIndexdv glad_glIndexdv +GLAD_API_CALL PFNGLINDEXFPROC glad_glIndexf; +#define glIndexf glad_glIndexf +GLAD_API_CALL PFNGLINDEXFVPROC glad_glIndexfv; +#define glIndexfv glad_glIndexfv +GLAD_API_CALL PFNGLINDEXIPROC glad_glIndexi; +#define glIndexi glad_glIndexi +GLAD_API_CALL PFNGLINDEXIVPROC glad_glIndexiv; +#define glIndexiv glad_glIndexiv +GLAD_API_CALL PFNGLINDEXSPROC glad_glIndexs; +#define glIndexs glad_glIndexs +GLAD_API_CALL PFNGLINDEXSVPROC glad_glIndexsv; +#define glIndexsv glad_glIndexsv +GLAD_API_CALL PFNGLINDEXUBPROC glad_glIndexub; +#define glIndexub glad_glIndexub +GLAD_API_CALL PFNGLINDEXUBVPROC glad_glIndexubv; +#define glIndexubv glad_glIndexubv +GLAD_API_CALL PFNGLINITNAMESPROC glad_glInitNames; +#define glInitNames glad_glInitNames +GLAD_API_CALL PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays; +#define glInterleavedArrays glad_glInterleavedArrays +GLAD_API_CALL PFNGLINVALIDATEBUFFERDATAPROC glad_glInvalidateBufferData; +#define glInvalidateBufferData glad_glInvalidateBufferData +GLAD_API_CALL PFNGLINVALIDATEBUFFERSUBDATAPROC glad_glInvalidateBufferSubData; +#define glInvalidateBufferSubData glad_glInvalidateBufferSubData +GLAD_API_CALL PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer; +#define glInvalidateFramebuffer glad_glInvalidateFramebuffer +GLAD_API_CALL PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glad_glInvalidateNamedFramebufferData; +#define glInvalidateNamedFramebufferData glad_glInvalidateNamedFramebufferData +GLAD_API_CALL PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glad_glInvalidateNamedFramebufferSubData; +#define glInvalidateNamedFramebufferSubData glad_glInvalidateNamedFramebufferSubData +GLAD_API_CALL PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer; +#define glInvalidateSubFramebuffer glad_glInvalidateSubFramebuffer +GLAD_API_CALL PFNGLINVALIDATETEXIMAGEPROC glad_glInvalidateTexImage; +#define glInvalidateTexImage glad_glInvalidateTexImage +GLAD_API_CALL PFNGLINVALIDATETEXSUBIMAGEPROC glad_glInvalidateTexSubImage; +#define glInvalidateTexSubImage glad_glInvalidateTexSubImage +GLAD_API_CALL PFNGLISBUFFERPROC glad_glIsBuffer; +#define glIsBuffer glad_glIsBuffer +GLAD_API_CALL PFNGLISBUFFERARBPROC glad_glIsBufferARB; +#define glIsBufferARB glad_glIsBufferARB +GLAD_API_CALL PFNGLISENABLEDPROC glad_glIsEnabled; +#define glIsEnabled glad_glIsEnabled +GLAD_API_CALL PFNGLISENABLEDINDEXEDEXTPROC glad_glIsEnabledIndexedEXT; +#define glIsEnabledIndexedEXT glad_glIsEnabledIndexedEXT +GLAD_API_CALL PFNGLISENABLEDIPROC glad_glIsEnabledi; +#define glIsEnabledi glad_glIsEnabledi +GLAD_API_CALL PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer; +#define glIsFramebuffer glad_glIsFramebuffer +GLAD_API_CALL PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT; +#define glIsFramebufferEXT glad_glIsFramebufferEXT +GLAD_API_CALL PFNGLISLISTPROC glad_glIsList; +#define glIsList glad_glIsList +GLAD_API_CALL PFNGLISPROGRAMPROC glad_glIsProgram; +#define glIsProgram glad_glIsProgram +GLAD_API_CALL PFNGLISPROGRAMARBPROC glad_glIsProgramARB; +#define glIsProgramARB glad_glIsProgramARB +GLAD_API_CALL PFNGLISPROGRAMPIPELINEPROC glad_glIsProgramPipeline; +#define glIsProgramPipeline glad_glIsProgramPipeline +GLAD_API_CALL PFNGLISQUERYPROC glad_glIsQuery; +#define glIsQuery glad_glIsQuery +GLAD_API_CALL PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer; +#define glIsRenderbuffer glad_glIsRenderbuffer +GLAD_API_CALL PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT; +#define glIsRenderbufferEXT glad_glIsRenderbufferEXT +GLAD_API_CALL PFNGLISSAMPLERPROC glad_glIsSampler; +#define glIsSampler glad_glIsSampler +GLAD_API_CALL PFNGLISSHADERPROC glad_glIsShader; +#define glIsShader glad_glIsShader +GLAD_API_CALL PFNGLISSYNCPROC glad_glIsSync; +#define glIsSync glad_glIsSync +GLAD_API_CALL PFNGLISTEXTUREPROC glad_glIsTexture; +#define glIsTexture glad_glIsTexture +GLAD_API_CALL PFNGLISTRANSFORMFEEDBACKPROC glad_glIsTransformFeedback; +#define glIsTransformFeedback glad_glIsTransformFeedback +GLAD_API_CALL PFNGLISVERTEXARRAYPROC glad_glIsVertexArray; +#define glIsVertexArray glad_glIsVertexArray +GLAD_API_CALL PFNGLLIGHTMODELFPROC glad_glLightModelf; +#define glLightModelf glad_glLightModelf +GLAD_API_CALL PFNGLLIGHTMODELFVPROC glad_glLightModelfv; +#define glLightModelfv glad_glLightModelfv +GLAD_API_CALL PFNGLLIGHTMODELIPROC glad_glLightModeli; +#define glLightModeli glad_glLightModeli +GLAD_API_CALL PFNGLLIGHTMODELIVPROC glad_glLightModeliv; +#define glLightModeliv glad_glLightModeliv +GLAD_API_CALL PFNGLLIGHTFPROC glad_glLightf; +#define glLightf glad_glLightf +GLAD_API_CALL PFNGLLIGHTFVPROC glad_glLightfv; +#define glLightfv glad_glLightfv +GLAD_API_CALL PFNGLLIGHTIPROC glad_glLighti; +#define glLighti glad_glLighti +GLAD_API_CALL PFNGLLIGHTIVPROC glad_glLightiv; +#define glLightiv glad_glLightiv +GLAD_API_CALL PFNGLLINESTIPPLEPROC glad_glLineStipple; +#define glLineStipple glad_glLineStipple +GLAD_API_CALL PFNGLLINEWIDTHPROC glad_glLineWidth; +#define glLineWidth glad_glLineWidth +GLAD_API_CALL PFNGLLINKPROGRAMPROC glad_glLinkProgram; +#define glLinkProgram glad_glLinkProgram +GLAD_API_CALL PFNGLLINKPROGRAMARBPROC glad_glLinkProgramARB; +#define glLinkProgramARB glad_glLinkProgramARB +GLAD_API_CALL PFNGLLISTBASEPROC glad_glListBase; +#define glListBase glad_glListBase +GLAD_API_CALL PFNGLLOADIDENTITYPROC glad_glLoadIdentity; +#define glLoadIdentity glad_glLoadIdentity +GLAD_API_CALL PFNGLLOADMATRIXDPROC glad_glLoadMatrixd; +#define glLoadMatrixd glad_glLoadMatrixd +GLAD_API_CALL PFNGLLOADMATRIXFPROC glad_glLoadMatrixf; +#define glLoadMatrixf glad_glLoadMatrixf +GLAD_API_CALL PFNGLLOADNAMEPROC glad_glLoadName; +#define glLoadName glad_glLoadName +GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd; +#define glLoadTransposeMatrixd glad_glLoadTransposeMatrixd +GLAD_API_CALL PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf; +#define glLoadTransposeMatrixf glad_glLoadTransposeMatrixf +GLAD_API_CALL PFNGLLOGICOPPROC glad_glLogicOp; +#define glLogicOp glad_glLogicOp +GLAD_API_CALL PFNGLMAP1DPROC glad_glMap1d; +#define glMap1d glad_glMap1d +GLAD_API_CALL PFNGLMAP1FPROC glad_glMap1f; +#define glMap1f glad_glMap1f +GLAD_API_CALL PFNGLMAP2DPROC glad_glMap2d; +#define glMap2d glad_glMap2d +GLAD_API_CALL PFNGLMAP2FPROC glad_glMap2f; +#define glMap2f glad_glMap2f +GLAD_API_CALL PFNGLMAPBUFFERPROC glad_glMapBuffer; +#define glMapBuffer glad_glMapBuffer +GLAD_API_CALL PFNGLMAPBUFFERARBPROC glad_glMapBufferARB; +#define glMapBufferARB glad_glMapBufferARB +GLAD_API_CALL PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange; +#define glMapBufferRange glad_glMapBufferRange +GLAD_API_CALL PFNGLMAPGRID1DPROC glad_glMapGrid1d; +#define glMapGrid1d glad_glMapGrid1d +GLAD_API_CALL PFNGLMAPGRID1FPROC glad_glMapGrid1f; +#define glMapGrid1f glad_glMapGrid1f +GLAD_API_CALL PFNGLMAPGRID2DPROC glad_glMapGrid2d; +#define glMapGrid2d glad_glMapGrid2d +GLAD_API_CALL PFNGLMAPGRID2FPROC glad_glMapGrid2f; +#define glMapGrid2f glad_glMapGrid2f +GLAD_API_CALL PFNGLMAPNAMEDBUFFERPROC glad_glMapNamedBuffer; +#define glMapNamedBuffer glad_glMapNamedBuffer +GLAD_API_CALL PFNGLMAPNAMEDBUFFEREXTPROC glad_glMapNamedBufferEXT; +#define glMapNamedBufferEXT glad_glMapNamedBufferEXT +GLAD_API_CALL PFNGLMAPNAMEDBUFFERRANGEPROC glad_glMapNamedBufferRange; +#define glMapNamedBufferRange glad_glMapNamedBufferRange +GLAD_API_CALL PFNGLMAPNAMEDBUFFERRANGEEXTPROC glad_glMapNamedBufferRangeEXT; +#define glMapNamedBufferRangeEXT glad_glMapNamedBufferRangeEXT +GLAD_API_CALL PFNGLMATERIALFPROC glad_glMaterialf; +#define glMaterialf glad_glMaterialf +GLAD_API_CALL PFNGLMATERIALFVPROC glad_glMaterialfv; +#define glMaterialfv glad_glMaterialfv +GLAD_API_CALL PFNGLMATERIALIPROC glad_glMateriali; +#define glMateriali glad_glMateriali +GLAD_API_CALL PFNGLMATERIALIVPROC glad_glMaterialiv; +#define glMaterialiv glad_glMaterialiv +GLAD_API_CALL PFNGLMATRIXFRUSTUMEXTPROC glad_glMatrixFrustumEXT; +#define glMatrixFrustumEXT glad_glMatrixFrustumEXT +GLAD_API_CALL PFNGLMATRIXLOADIDENTITYEXTPROC glad_glMatrixLoadIdentityEXT; +#define glMatrixLoadIdentityEXT glad_glMatrixLoadIdentityEXT +GLAD_API_CALL PFNGLMATRIXLOADTRANSPOSEDEXTPROC glad_glMatrixLoadTransposedEXT; +#define glMatrixLoadTransposedEXT glad_glMatrixLoadTransposedEXT +GLAD_API_CALL PFNGLMATRIXLOADTRANSPOSEFEXTPROC glad_glMatrixLoadTransposefEXT; +#define glMatrixLoadTransposefEXT glad_glMatrixLoadTransposefEXT +GLAD_API_CALL PFNGLMATRIXLOADDEXTPROC glad_glMatrixLoaddEXT; +#define glMatrixLoaddEXT glad_glMatrixLoaddEXT +GLAD_API_CALL PFNGLMATRIXLOADFEXTPROC glad_glMatrixLoadfEXT; +#define glMatrixLoadfEXT glad_glMatrixLoadfEXT +GLAD_API_CALL PFNGLMATRIXMODEPROC glad_glMatrixMode; +#define glMatrixMode glad_glMatrixMode +GLAD_API_CALL PFNGLMATRIXMULTTRANSPOSEDEXTPROC glad_glMatrixMultTransposedEXT; +#define glMatrixMultTransposedEXT glad_glMatrixMultTransposedEXT +GLAD_API_CALL PFNGLMATRIXMULTTRANSPOSEFEXTPROC glad_glMatrixMultTransposefEXT; +#define glMatrixMultTransposefEXT glad_glMatrixMultTransposefEXT +GLAD_API_CALL PFNGLMATRIXMULTDEXTPROC glad_glMatrixMultdEXT; +#define glMatrixMultdEXT glad_glMatrixMultdEXT +GLAD_API_CALL PFNGLMATRIXMULTFEXTPROC glad_glMatrixMultfEXT; +#define glMatrixMultfEXT glad_glMatrixMultfEXT +GLAD_API_CALL PFNGLMATRIXORTHOEXTPROC glad_glMatrixOrthoEXT; +#define glMatrixOrthoEXT glad_glMatrixOrthoEXT +GLAD_API_CALL PFNGLMATRIXPOPEXTPROC glad_glMatrixPopEXT; +#define glMatrixPopEXT glad_glMatrixPopEXT +GLAD_API_CALL PFNGLMATRIXPUSHEXTPROC glad_glMatrixPushEXT; +#define glMatrixPushEXT glad_glMatrixPushEXT +GLAD_API_CALL PFNGLMATRIXROTATEDEXTPROC glad_glMatrixRotatedEXT; +#define glMatrixRotatedEXT glad_glMatrixRotatedEXT +GLAD_API_CALL PFNGLMATRIXROTATEFEXTPROC glad_glMatrixRotatefEXT; +#define glMatrixRotatefEXT glad_glMatrixRotatefEXT +GLAD_API_CALL PFNGLMATRIXSCALEDEXTPROC glad_glMatrixScaledEXT; +#define glMatrixScaledEXT glad_glMatrixScaledEXT +GLAD_API_CALL PFNGLMATRIXSCALEFEXTPROC glad_glMatrixScalefEXT; +#define glMatrixScalefEXT glad_glMatrixScalefEXT +GLAD_API_CALL PFNGLMATRIXTRANSLATEDEXTPROC glad_glMatrixTranslatedEXT; +#define glMatrixTranslatedEXT glad_glMatrixTranslatedEXT +GLAD_API_CALL PFNGLMATRIXTRANSLATEFEXTPROC glad_glMatrixTranslatefEXT; +#define glMatrixTranslatefEXT glad_glMatrixTranslatefEXT +GLAD_API_CALL PFNGLMEMORYBARRIERPROC glad_glMemoryBarrier; +#define glMemoryBarrier glad_glMemoryBarrier +GLAD_API_CALL PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion; +#define glMemoryBarrierByRegion glad_glMemoryBarrierByRegion +GLAD_API_CALL PFNGLMEMORYBARRIEREXTPROC glad_glMemoryBarrierEXT; +#define glMemoryBarrierEXT glad_glMemoryBarrierEXT +GLAD_API_CALL PFNGLMINSAMPLESHADINGPROC glad_glMinSampleShading; +#define glMinSampleShading glad_glMinSampleShading +GLAD_API_CALL PFNGLMULTMATRIXDPROC glad_glMultMatrixd; +#define glMultMatrixd glad_glMultMatrixd +GLAD_API_CALL PFNGLMULTMATRIXFPROC glad_glMultMatrixf; +#define glMultMatrixf glad_glMultMatrixf +GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd; +#define glMultTransposeMatrixd glad_glMultTransposeMatrixd +GLAD_API_CALL PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf; +#define glMultTransposeMatrixf glad_glMultTransposeMatrixf +GLAD_API_CALL PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays; +#define glMultiDrawArrays glad_glMultiDrawArrays +GLAD_API_CALL PFNGLMULTIDRAWARRAYSINDIRECTPROC glad_glMultiDrawArraysIndirect; +#define glMultiDrawArraysIndirect glad_glMultiDrawArraysIndirect +GLAD_API_CALL PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC glad_glMultiDrawArraysIndirectCount; +#define glMultiDrawArraysIndirectCount glad_glMultiDrawArraysIndirectCount +GLAD_API_CALL PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements; +#define glMultiDrawElements glad_glMultiDrawElements +GLAD_API_CALL PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex; +#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex +GLAD_API_CALL PFNGLMULTIDRAWELEMENTSINDIRECTPROC glad_glMultiDrawElementsIndirect; +#define glMultiDrawElementsIndirect glad_glMultiDrawElementsIndirect +GLAD_API_CALL PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC glad_glMultiDrawElementsIndirectCount; +#define glMultiDrawElementsIndirectCount glad_glMultiDrawElementsIndirectCount +GLAD_API_CALL PFNGLMULTITEXBUFFEREXTPROC glad_glMultiTexBufferEXT; +#define glMultiTexBufferEXT glad_glMultiTexBufferEXT +GLAD_API_CALL PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d; +#define glMultiTexCoord1d glad_glMultiTexCoord1d +GLAD_API_CALL PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv; +#define glMultiTexCoord1dv glad_glMultiTexCoord1dv +GLAD_API_CALL PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f; +#define glMultiTexCoord1f glad_glMultiTexCoord1f +GLAD_API_CALL PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv; +#define glMultiTexCoord1fv glad_glMultiTexCoord1fv +GLAD_API_CALL PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i; +#define glMultiTexCoord1i glad_glMultiTexCoord1i +GLAD_API_CALL PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv; +#define glMultiTexCoord1iv glad_glMultiTexCoord1iv +GLAD_API_CALL PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s; +#define glMultiTexCoord1s glad_glMultiTexCoord1s +GLAD_API_CALL PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv; +#define glMultiTexCoord1sv glad_glMultiTexCoord1sv +GLAD_API_CALL PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d; +#define glMultiTexCoord2d glad_glMultiTexCoord2d +GLAD_API_CALL PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv; +#define glMultiTexCoord2dv glad_glMultiTexCoord2dv +GLAD_API_CALL PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f; +#define glMultiTexCoord2f glad_glMultiTexCoord2f +GLAD_API_CALL PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv; +#define glMultiTexCoord2fv glad_glMultiTexCoord2fv +GLAD_API_CALL PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i; +#define glMultiTexCoord2i glad_glMultiTexCoord2i +GLAD_API_CALL PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv; +#define glMultiTexCoord2iv glad_glMultiTexCoord2iv +GLAD_API_CALL PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s; +#define glMultiTexCoord2s glad_glMultiTexCoord2s +GLAD_API_CALL PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv; +#define glMultiTexCoord2sv glad_glMultiTexCoord2sv +GLAD_API_CALL PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d; +#define glMultiTexCoord3d glad_glMultiTexCoord3d +GLAD_API_CALL PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv; +#define glMultiTexCoord3dv glad_glMultiTexCoord3dv +GLAD_API_CALL PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f; +#define glMultiTexCoord3f glad_glMultiTexCoord3f +GLAD_API_CALL PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv; +#define glMultiTexCoord3fv glad_glMultiTexCoord3fv +GLAD_API_CALL PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i; +#define glMultiTexCoord3i glad_glMultiTexCoord3i +GLAD_API_CALL PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv; +#define glMultiTexCoord3iv glad_glMultiTexCoord3iv +GLAD_API_CALL PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s; +#define glMultiTexCoord3s glad_glMultiTexCoord3s +GLAD_API_CALL PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv; +#define glMultiTexCoord3sv glad_glMultiTexCoord3sv +GLAD_API_CALL PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d; +#define glMultiTexCoord4d glad_glMultiTexCoord4d +GLAD_API_CALL PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv; +#define glMultiTexCoord4dv glad_glMultiTexCoord4dv +GLAD_API_CALL PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f; +#define glMultiTexCoord4f glad_glMultiTexCoord4f +GLAD_API_CALL PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv; +#define glMultiTexCoord4fv glad_glMultiTexCoord4fv +GLAD_API_CALL PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i; +#define glMultiTexCoord4i glad_glMultiTexCoord4i +GLAD_API_CALL PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv; +#define glMultiTexCoord4iv glad_glMultiTexCoord4iv +GLAD_API_CALL PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s; +#define glMultiTexCoord4s glad_glMultiTexCoord4s +GLAD_API_CALL PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv; +#define glMultiTexCoord4sv glad_glMultiTexCoord4sv +GLAD_API_CALL PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui; +#define glMultiTexCoordP1ui glad_glMultiTexCoordP1ui +GLAD_API_CALL PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv; +#define glMultiTexCoordP1uiv glad_glMultiTexCoordP1uiv +GLAD_API_CALL PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui; +#define glMultiTexCoordP2ui glad_glMultiTexCoordP2ui +GLAD_API_CALL PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv; +#define glMultiTexCoordP2uiv glad_glMultiTexCoordP2uiv +GLAD_API_CALL PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui; +#define glMultiTexCoordP3ui glad_glMultiTexCoordP3ui +GLAD_API_CALL PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv; +#define glMultiTexCoordP3uiv glad_glMultiTexCoordP3uiv +GLAD_API_CALL PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui; +#define glMultiTexCoordP4ui glad_glMultiTexCoordP4ui +GLAD_API_CALL PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv; +#define glMultiTexCoordP4uiv glad_glMultiTexCoordP4uiv +GLAD_API_CALL PFNGLMULTITEXCOORDPOINTEREXTPROC glad_glMultiTexCoordPointerEXT; +#define glMultiTexCoordPointerEXT glad_glMultiTexCoordPointerEXT +GLAD_API_CALL PFNGLMULTITEXENVFEXTPROC glad_glMultiTexEnvfEXT; +#define glMultiTexEnvfEXT glad_glMultiTexEnvfEXT +GLAD_API_CALL PFNGLMULTITEXENVFVEXTPROC glad_glMultiTexEnvfvEXT; +#define glMultiTexEnvfvEXT glad_glMultiTexEnvfvEXT +GLAD_API_CALL PFNGLMULTITEXENVIEXTPROC glad_glMultiTexEnviEXT; +#define glMultiTexEnviEXT glad_glMultiTexEnviEXT +GLAD_API_CALL PFNGLMULTITEXENVIVEXTPROC glad_glMultiTexEnvivEXT; +#define glMultiTexEnvivEXT glad_glMultiTexEnvivEXT +GLAD_API_CALL PFNGLMULTITEXGENDEXTPROC glad_glMultiTexGendEXT; +#define glMultiTexGendEXT glad_glMultiTexGendEXT +GLAD_API_CALL PFNGLMULTITEXGENDVEXTPROC glad_glMultiTexGendvEXT; +#define glMultiTexGendvEXT glad_glMultiTexGendvEXT +GLAD_API_CALL PFNGLMULTITEXGENFEXTPROC glad_glMultiTexGenfEXT; +#define glMultiTexGenfEXT glad_glMultiTexGenfEXT +GLAD_API_CALL PFNGLMULTITEXGENFVEXTPROC glad_glMultiTexGenfvEXT; +#define glMultiTexGenfvEXT glad_glMultiTexGenfvEXT +GLAD_API_CALL PFNGLMULTITEXGENIEXTPROC glad_glMultiTexGeniEXT; +#define glMultiTexGeniEXT glad_glMultiTexGeniEXT +GLAD_API_CALL PFNGLMULTITEXGENIVEXTPROC glad_glMultiTexGenivEXT; +#define glMultiTexGenivEXT glad_glMultiTexGenivEXT +GLAD_API_CALL PFNGLMULTITEXIMAGE1DEXTPROC glad_glMultiTexImage1DEXT; +#define glMultiTexImage1DEXT glad_glMultiTexImage1DEXT +GLAD_API_CALL PFNGLMULTITEXIMAGE2DEXTPROC glad_glMultiTexImage2DEXT; +#define glMultiTexImage2DEXT glad_glMultiTexImage2DEXT +GLAD_API_CALL PFNGLMULTITEXIMAGE3DEXTPROC glad_glMultiTexImage3DEXT; +#define glMultiTexImage3DEXT glad_glMultiTexImage3DEXT +GLAD_API_CALL PFNGLMULTITEXPARAMETERIIVEXTPROC glad_glMultiTexParameterIivEXT; +#define glMultiTexParameterIivEXT glad_glMultiTexParameterIivEXT +GLAD_API_CALL PFNGLMULTITEXPARAMETERIUIVEXTPROC glad_glMultiTexParameterIuivEXT; +#define glMultiTexParameterIuivEXT glad_glMultiTexParameterIuivEXT +GLAD_API_CALL PFNGLMULTITEXPARAMETERFEXTPROC glad_glMultiTexParameterfEXT; +#define glMultiTexParameterfEXT glad_glMultiTexParameterfEXT +GLAD_API_CALL PFNGLMULTITEXPARAMETERFVEXTPROC glad_glMultiTexParameterfvEXT; +#define glMultiTexParameterfvEXT glad_glMultiTexParameterfvEXT +GLAD_API_CALL PFNGLMULTITEXPARAMETERIEXTPROC glad_glMultiTexParameteriEXT; +#define glMultiTexParameteriEXT glad_glMultiTexParameteriEXT +GLAD_API_CALL PFNGLMULTITEXPARAMETERIVEXTPROC glad_glMultiTexParameterivEXT; +#define glMultiTexParameterivEXT glad_glMultiTexParameterivEXT +GLAD_API_CALL PFNGLMULTITEXRENDERBUFFEREXTPROC glad_glMultiTexRenderbufferEXT; +#define glMultiTexRenderbufferEXT glad_glMultiTexRenderbufferEXT +GLAD_API_CALL PFNGLMULTITEXSUBIMAGE1DEXTPROC glad_glMultiTexSubImage1DEXT; +#define glMultiTexSubImage1DEXT glad_glMultiTexSubImage1DEXT +GLAD_API_CALL PFNGLMULTITEXSUBIMAGE2DEXTPROC glad_glMultiTexSubImage2DEXT; +#define glMultiTexSubImage2DEXT glad_glMultiTexSubImage2DEXT +GLAD_API_CALL PFNGLMULTITEXSUBIMAGE3DEXTPROC glad_glMultiTexSubImage3DEXT; +#define glMultiTexSubImage3DEXT glad_glMultiTexSubImage3DEXT +GLAD_API_CALL PFNGLNAMEDBUFFERDATAPROC glad_glNamedBufferData; +#define glNamedBufferData glad_glNamedBufferData +GLAD_API_CALL PFNGLNAMEDBUFFERDATAEXTPROC glad_glNamedBufferDataEXT; +#define glNamedBufferDataEXT glad_glNamedBufferDataEXT +GLAD_API_CALL PFNGLNAMEDBUFFERSTORAGEPROC glad_glNamedBufferStorage; +#define glNamedBufferStorage glad_glNamedBufferStorage +GLAD_API_CALL PFNGLNAMEDBUFFERSTORAGEEXTPROC glad_glNamedBufferStorageEXT; +#define glNamedBufferStorageEXT glad_glNamedBufferStorageEXT +GLAD_API_CALL PFNGLNAMEDBUFFERSUBDATAPROC glad_glNamedBufferSubData; +#define glNamedBufferSubData glad_glNamedBufferSubData +GLAD_API_CALL PFNGLNAMEDBUFFERSUBDATAEXTPROC glad_glNamedBufferSubDataEXT; +#define glNamedBufferSubDataEXT glad_glNamedBufferSubDataEXT +GLAD_API_CALL PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC glad_glNamedCopyBufferSubDataEXT; +#define glNamedCopyBufferSubDataEXT glad_glNamedCopyBufferSubDataEXT +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glad_glNamedFramebufferDrawBuffer; +#define glNamedFramebufferDrawBuffer glad_glNamedFramebufferDrawBuffer +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glad_glNamedFramebufferDrawBuffers; +#define glNamedFramebufferDrawBuffers glad_glNamedFramebufferDrawBuffers +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glad_glNamedFramebufferParameteri; +#define glNamedFramebufferParameteri glad_glNamedFramebufferParameteri +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC glad_glNamedFramebufferParameteriEXT; +#define glNamedFramebufferParameteriEXT glad_glNamedFramebufferParameteriEXT +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glad_glNamedFramebufferReadBuffer; +#define glNamedFramebufferReadBuffer glad_glNamedFramebufferReadBuffer +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glad_glNamedFramebufferRenderbuffer; +#define glNamedFramebufferRenderbuffer glad_glNamedFramebufferRenderbuffer +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC glad_glNamedFramebufferRenderbufferEXT; +#define glNamedFramebufferRenderbufferEXT glad_glNamedFramebufferRenderbufferEXT +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glad_glNamedFramebufferTexture; +#define glNamedFramebufferTexture glad_glNamedFramebufferTexture +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC glad_glNamedFramebufferTexture1DEXT; +#define glNamedFramebufferTexture1DEXT glad_glNamedFramebufferTexture1DEXT +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC glad_glNamedFramebufferTexture2DEXT; +#define glNamedFramebufferTexture2DEXT glad_glNamedFramebufferTexture2DEXT +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC glad_glNamedFramebufferTexture3DEXT; +#define glNamedFramebufferTexture3DEXT glad_glNamedFramebufferTexture3DEXT +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC glad_glNamedFramebufferTextureEXT; +#define glNamedFramebufferTextureEXT glad_glNamedFramebufferTextureEXT +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC glad_glNamedFramebufferTextureFaceEXT; +#define glNamedFramebufferTextureFaceEXT glad_glNamedFramebufferTextureFaceEXT +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glad_glNamedFramebufferTextureLayer; +#define glNamedFramebufferTextureLayer glad_glNamedFramebufferTextureLayer +GLAD_API_CALL PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC glad_glNamedFramebufferTextureLayerEXT; +#define glNamedFramebufferTextureLayerEXT glad_glNamedFramebufferTextureLayerEXT +GLAD_API_CALL PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC glad_glNamedProgramLocalParameter4dEXT; +#define glNamedProgramLocalParameter4dEXT glad_glNamedProgramLocalParameter4dEXT +GLAD_API_CALL PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC glad_glNamedProgramLocalParameter4dvEXT; +#define glNamedProgramLocalParameter4dvEXT glad_glNamedProgramLocalParameter4dvEXT +GLAD_API_CALL PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC glad_glNamedProgramLocalParameter4fEXT; +#define glNamedProgramLocalParameter4fEXT glad_glNamedProgramLocalParameter4fEXT +GLAD_API_CALL PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC glad_glNamedProgramLocalParameter4fvEXT; +#define glNamedProgramLocalParameter4fvEXT glad_glNamedProgramLocalParameter4fvEXT +GLAD_API_CALL PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC glad_glNamedProgramLocalParameterI4iEXT; +#define glNamedProgramLocalParameterI4iEXT glad_glNamedProgramLocalParameterI4iEXT +GLAD_API_CALL PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC glad_glNamedProgramLocalParameterI4ivEXT; +#define glNamedProgramLocalParameterI4ivEXT glad_glNamedProgramLocalParameterI4ivEXT +GLAD_API_CALL PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC glad_glNamedProgramLocalParameterI4uiEXT; +#define glNamedProgramLocalParameterI4uiEXT glad_glNamedProgramLocalParameterI4uiEXT +GLAD_API_CALL PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC glad_glNamedProgramLocalParameterI4uivEXT; +#define glNamedProgramLocalParameterI4uivEXT glad_glNamedProgramLocalParameterI4uivEXT +GLAD_API_CALL PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC glad_glNamedProgramLocalParameters4fvEXT; +#define glNamedProgramLocalParameters4fvEXT glad_glNamedProgramLocalParameters4fvEXT +GLAD_API_CALL PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC glad_glNamedProgramLocalParametersI4ivEXT; +#define glNamedProgramLocalParametersI4ivEXT glad_glNamedProgramLocalParametersI4ivEXT +GLAD_API_CALL PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC glad_glNamedProgramLocalParametersI4uivEXT; +#define glNamedProgramLocalParametersI4uivEXT glad_glNamedProgramLocalParametersI4uivEXT +GLAD_API_CALL PFNGLNAMEDPROGRAMSTRINGEXTPROC glad_glNamedProgramStringEXT; +#define glNamedProgramStringEXT glad_glNamedProgramStringEXT +GLAD_API_CALL PFNGLNAMEDRENDERBUFFERSTORAGEPROC glad_glNamedRenderbufferStorage; +#define glNamedRenderbufferStorage glad_glNamedRenderbufferStorage +GLAD_API_CALL PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC glad_glNamedRenderbufferStorageEXT; +#define glNamedRenderbufferStorageEXT glad_glNamedRenderbufferStorageEXT +GLAD_API_CALL PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glNamedRenderbufferStorageMultisample; +#define glNamedRenderbufferStorageMultisample glad_glNamedRenderbufferStorageMultisample +GLAD_API_CALL PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC glad_glNamedRenderbufferStorageMultisampleCoverageEXT; +#define glNamedRenderbufferStorageMultisampleCoverageEXT glad_glNamedRenderbufferStorageMultisampleCoverageEXT +GLAD_API_CALL PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glNamedRenderbufferStorageMultisampleEXT; +#define glNamedRenderbufferStorageMultisampleEXT glad_glNamedRenderbufferStorageMultisampleEXT +GLAD_API_CALL PFNGLNEWLISTPROC glad_glNewList; +#define glNewList glad_glNewList +GLAD_API_CALL PFNGLNORMAL3BPROC glad_glNormal3b; +#define glNormal3b glad_glNormal3b +GLAD_API_CALL PFNGLNORMAL3BVPROC glad_glNormal3bv; +#define glNormal3bv glad_glNormal3bv +GLAD_API_CALL PFNGLNORMAL3DPROC glad_glNormal3d; +#define glNormal3d glad_glNormal3d +GLAD_API_CALL PFNGLNORMAL3DVPROC glad_glNormal3dv; +#define glNormal3dv glad_glNormal3dv +GLAD_API_CALL PFNGLNORMAL3FPROC glad_glNormal3f; +#define glNormal3f glad_glNormal3f +GLAD_API_CALL PFNGLNORMAL3FVPROC glad_glNormal3fv; +#define glNormal3fv glad_glNormal3fv +GLAD_API_CALL PFNGLNORMAL3IPROC glad_glNormal3i; +#define glNormal3i glad_glNormal3i +GLAD_API_CALL PFNGLNORMAL3IVPROC glad_glNormal3iv; +#define glNormal3iv glad_glNormal3iv +GLAD_API_CALL PFNGLNORMAL3SPROC glad_glNormal3s; +#define glNormal3s glad_glNormal3s +GLAD_API_CALL PFNGLNORMAL3SVPROC glad_glNormal3sv; +#define glNormal3sv glad_glNormal3sv +GLAD_API_CALL PFNGLNORMALP3UIPROC glad_glNormalP3ui; +#define glNormalP3ui glad_glNormalP3ui +GLAD_API_CALL PFNGLNORMALP3UIVPROC glad_glNormalP3uiv; +#define glNormalP3uiv glad_glNormalP3uiv +GLAD_API_CALL PFNGLNORMALPOINTERPROC glad_glNormalPointer; +#define glNormalPointer glad_glNormalPointer +GLAD_API_CALL PFNGLOBJECTLABELPROC glad_glObjectLabel; +#define glObjectLabel glad_glObjectLabel +GLAD_API_CALL PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel; +#define glObjectPtrLabel glad_glObjectPtrLabel +GLAD_API_CALL PFNGLORTHOPROC glad_glOrtho; +#define glOrtho glad_glOrtho +GLAD_API_CALL PFNGLPASSTHROUGHPROC glad_glPassThrough; +#define glPassThrough glad_glPassThrough +GLAD_API_CALL PFNGLPATCHPARAMETERFVPROC glad_glPatchParameterfv; +#define glPatchParameterfv glad_glPatchParameterfv +GLAD_API_CALL PFNGLPATCHPARAMETERIPROC glad_glPatchParameteri; +#define glPatchParameteri glad_glPatchParameteri +GLAD_API_CALL PFNGLPAUSETRANSFORMFEEDBACKPROC glad_glPauseTransformFeedback; +#define glPauseTransformFeedback glad_glPauseTransformFeedback +GLAD_API_CALL PFNGLPIXELMAPFVPROC glad_glPixelMapfv; +#define glPixelMapfv glad_glPixelMapfv +GLAD_API_CALL PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv; +#define glPixelMapuiv glad_glPixelMapuiv +GLAD_API_CALL PFNGLPIXELMAPUSVPROC glad_glPixelMapusv; +#define glPixelMapusv glad_glPixelMapusv +GLAD_API_CALL PFNGLPIXELSTOREFPROC glad_glPixelStoref; +#define glPixelStoref glad_glPixelStoref +GLAD_API_CALL PFNGLPIXELSTOREIPROC glad_glPixelStorei; +#define glPixelStorei glad_glPixelStorei +GLAD_API_CALL PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf; +#define glPixelTransferf glad_glPixelTransferf +GLAD_API_CALL PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi; +#define glPixelTransferi glad_glPixelTransferi +GLAD_API_CALL PFNGLPIXELZOOMPROC glad_glPixelZoom; +#define glPixelZoom glad_glPixelZoom +GLAD_API_CALL PFNGLPOINTPARAMETERFPROC glad_glPointParameterf; +#define glPointParameterf glad_glPointParameterf +GLAD_API_CALL PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv; +#define glPointParameterfv glad_glPointParameterfv +GLAD_API_CALL PFNGLPOINTPARAMETERIPROC glad_glPointParameteri; +#define glPointParameteri glad_glPointParameteri +GLAD_API_CALL PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv; +#define glPointParameteriv glad_glPointParameteriv +GLAD_API_CALL PFNGLPOINTSIZEPROC glad_glPointSize; +#define glPointSize glad_glPointSize +GLAD_API_CALL PFNGLPOLYGONMODEPROC glad_glPolygonMode; +#define glPolygonMode glad_glPolygonMode +GLAD_API_CALL PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset; +#define glPolygonOffset glad_glPolygonOffset +GLAD_API_CALL PFNGLPOLYGONOFFSETCLAMPPROC glad_glPolygonOffsetClamp; +#define glPolygonOffsetClamp glad_glPolygonOffsetClamp +GLAD_API_CALL PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple; +#define glPolygonStipple glad_glPolygonStipple +GLAD_API_CALL PFNGLPOPATTRIBPROC glad_glPopAttrib; +#define glPopAttrib glad_glPopAttrib +GLAD_API_CALL PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib; +#define glPopClientAttrib glad_glPopClientAttrib +GLAD_API_CALL PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup; +#define glPopDebugGroup glad_glPopDebugGroup +GLAD_API_CALL PFNGLPOPMATRIXPROC glad_glPopMatrix; +#define glPopMatrix glad_glPopMatrix +GLAD_API_CALL PFNGLPOPNAMEPROC glad_glPopName; +#define glPopName glad_glPopName +GLAD_API_CALL PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex; +#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex +GLAD_API_CALL PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures; +#define glPrioritizeTextures glad_glPrioritizeTextures +GLAD_API_CALL PFNGLPROGRAMBINARYPROC glad_glProgramBinary; +#define glProgramBinary glad_glProgramBinary +GLAD_API_CALL PFNGLPROGRAMENVPARAMETER4DARBPROC glad_glProgramEnvParameter4dARB; +#define glProgramEnvParameter4dARB glad_glProgramEnvParameter4dARB +GLAD_API_CALL PFNGLPROGRAMENVPARAMETER4DVARBPROC glad_glProgramEnvParameter4dvARB; +#define glProgramEnvParameter4dvARB glad_glProgramEnvParameter4dvARB +GLAD_API_CALL PFNGLPROGRAMENVPARAMETER4FARBPROC glad_glProgramEnvParameter4fARB; +#define glProgramEnvParameter4fARB glad_glProgramEnvParameter4fARB +GLAD_API_CALL PFNGLPROGRAMENVPARAMETER4FVARBPROC glad_glProgramEnvParameter4fvARB; +#define glProgramEnvParameter4fvARB glad_glProgramEnvParameter4fvARB +GLAD_API_CALL PFNGLPROGRAMLOCALPARAMETER4DARBPROC glad_glProgramLocalParameter4dARB; +#define glProgramLocalParameter4dARB glad_glProgramLocalParameter4dARB +GLAD_API_CALL PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glad_glProgramLocalParameter4dvARB; +#define glProgramLocalParameter4dvARB glad_glProgramLocalParameter4dvARB +GLAD_API_CALL PFNGLPROGRAMLOCALPARAMETER4FARBPROC glad_glProgramLocalParameter4fARB; +#define glProgramLocalParameter4fARB glad_glProgramLocalParameter4fARB +GLAD_API_CALL PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glad_glProgramLocalParameter4fvARB; +#define glProgramLocalParameter4fvARB glad_glProgramLocalParameter4fvARB +GLAD_API_CALL PFNGLPROGRAMPARAMETERIPROC glad_glProgramParameteri; +#define glProgramParameteri glad_glProgramParameteri +GLAD_API_CALL PFNGLPROGRAMPARAMETERIEXTPROC glad_glProgramParameteriEXT; +#define glProgramParameteriEXT glad_glProgramParameteriEXT +GLAD_API_CALL PFNGLPROGRAMSTRINGARBPROC glad_glProgramStringARB; +#define glProgramStringARB glad_glProgramStringARB +GLAD_API_CALL PFNGLPROGRAMUNIFORM1DPROC glad_glProgramUniform1d; +#define glProgramUniform1d glad_glProgramUniform1d +GLAD_API_CALL PFNGLPROGRAMUNIFORM1DEXTPROC glad_glProgramUniform1dEXT; +#define glProgramUniform1dEXT glad_glProgramUniform1dEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM1DVPROC glad_glProgramUniform1dv; +#define glProgramUniform1dv glad_glProgramUniform1dv +GLAD_API_CALL PFNGLPROGRAMUNIFORM1DVEXTPROC glad_glProgramUniform1dvEXT; +#define glProgramUniform1dvEXT glad_glProgramUniform1dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM1FPROC glad_glProgramUniform1f; +#define glProgramUniform1f glad_glProgramUniform1f +GLAD_API_CALL PFNGLPROGRAMUNIFORM1FEXTPROC glad_glProgramUniform1fEXT; +#define glProgramUniform1fEXT glad_glProgramUniform1fEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM1FVPROC glad_glProgramUniform1fv; +#define glProgramUniform1fv glad_glProgramUniform1fv +GLAD_API_CALL PFNGLPROGRAMUNIFORM1FVEXTPROC glad_glProgramUniform1fvEXT; +#define glProgramUniform1fvEXT glad_glProgramUniform1fvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM1IPROC glad_glProgramUniform1i; +#define glProgramUniform1i glad_glProgramUniform1i +GLAD_API_CALL PFNGLPROGRAMUNIFORM1IEXTPROC glad_glProgramUniform1iEXT; +#define glProgramUniform1iEXT glad_glProgramUniform1iEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM1IVPROC glad_glProgramUniform1iv; +#define glProgramUniform1iv glad_glProgramUniform1iv +GLAD_API_CALL PFNGLPROGRAMUNIFORM1IVEXTPROC glad_glProgramUniform1ivEXT; +#define glProgramUniform1ivEXT glad_glProgramUniform1ivEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM1UIPROC glad_glProgramUniform1ui; +#define glProgramUniform1ui glad_glProgramUniform1ui +GLAD_API_CALL PFNGLPROGRAMUNIFORM1UIEXTPROC glad_glProgramUniform1uiEXT; +#define glProgramUniform1uiEXT glad_glProgramUniform1uiEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM1UIVPROC glad_glProgramUniform1uiv; +#define glProgramUniform1uiv glad_glProgramUniform1uiv +GLAD_API_CALL PFNGLPROGRAMUNIFORM1UIVEXTPROC glad_glProgramUniform1uivEXT; +#define glProgramUniform1uivEXT glad_glProgramUniform1uivEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM2DPROC glad_glProgramUniform2d; +#define glProgramUniform2d glad_glProgramUniform2d +GLAD_API_CALL PFNGLPROGRAMUNIFORM2DEXTPROC glad_glProgramUniform2dEXT; +#define glProgramUniform2dEXT glad_glProgramUniform2dEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM2DVPROC glad_glProgramUniform2dv; +#define glProgramUniform2dv glad_glProgramUniform2dv +GLAD_API_CALL PFNGLPROGRAMUNIFORM2DVEXTPROC glad_glProgramUniform2dvEXT; +#define glProgramUniform2dvEXT glad_glProgramUniform2dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM2FPROC glad_glProgramUniform2f; +#define glProgramUniform2f glad_glProgramUniform2f +GLAD_API_CALL PFNGLPROGRAMUNIFORM2FEXTPROC glad_glProgramUniform2fEXT; +#define glProgramUniform2fEXT glad_glProgramUniform2fEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM2FVPROC glad_glProgramUniform2fv; +#define glProgramUniform2fv glad_glProgramUniform2fv +GLAD_API_CALL PFNGLPROGRAMUNIFORM2FVEXTPROC glad_glProgramUniform2fvEXT; +#define glProgramUniform2fvEXT glad_glProgramUniform2fvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM2IPROC glad_glProgramUniform2i; +#define glProgramUniform2i glad_glProgramUniform2i +GLAD_API_CALL PFNGLPROGRAMUNIFORM2IEXTPROC glad_glProgramUniform2iEXT; +#define glProgramUniform2iEXT glad_glProgramUniform2iEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM2IVPROC glad_glProgramUniform2iv; +#define glProgramUniform2iv glad_glProgramUniform2iv +GLAD_API_CALL PFNGLPROGRAMUNIFORM2IVEXTPROC glad_glProgramUniform2ivEXT; +#define glProgramUniform2ivEXT glad_glProgramUniform2ivEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM2UIPROC glad_glProgramUniform2ui; +#define glProgramUniform2ui glad_glProgramUniform2ui +GLAD_API_CALL PFNGLPROGRAMUNIFORM2UIEXTPROC glad_glProgramUniform2uiEXT; +#define glProgramUniform2uiEXT glad_glProgramUniform2uiEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM2UIVPROC glad_glProgramUniform2uiv; +#define glProgramUniform2uiv glad_glProgramUniform2uiv +GLAD_API_CALL PFNGLPROGRAMUNIFORM2UIVEXTPROC glad_glProgramUniform2uivEXT; +#define glProgramUniform2uivEXT glad_glProgramUniform2uivEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM3DPROC glad_glProgramUniform3d; +#define glProgramUniform3d glad_glProgramUniform3d +GLAD_API_CALL PFNGLPROGRAMUNIFORM3DEXTPROC glad_glProgramUniform3dEXT; +#define glProgramUniform3dEXT glad_glProgramUniform3dEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM3DVPROC glad_glProgramUniform3dv; +#define glProgramUniform3dv glad_glProgramUniform3dv +GLAD_API_CALL PFNGLPROGRAMUNIFORM3DVEXTPROC glad_glProgramUniform3dvEXT; +#define glProgramUniform3dvEXT glad_glProgramUniform3dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM3FPROC glad_glProgramUniform3f; +#define glProgramUniform3f glad_glProgramUniform3f +GLAD_API_CALL PFNGLPROGRAMUNIFORM3FEXTPROC glad_glProgramUniform3fEXT; +#define glProgramUniform3fEXT glad_glProgramUniform3fEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM3FVPROC glad_glProgramUniform3fv; +#define glProgramUniform3fv glad_glProgramUniform3fv +GLAD_API_CALL PFNGLPROGRAMUNIFORM3FVEXTPROC glad_glProgramUniform3fvEXT; +#define glProgramUniform3fvEXT glad_glProgramUniform3fvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM3IPROC glad_glProgramUniform3i; +#define glProgramUniform3i glad_glProgramUniform3i +GLAD_API_CALL PFNGLPROGRAMUNIFORM3IEXTPROC glad_glProgramUniform3iEXT; +#define glProgramUniform3iEXT glad_glProgramUniform3iEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM3IVPROC glad_glProgramUniform3iv; +#define glProgramUniform3iv glad_glProgramUniform3iv +GLAD_API_CALL PFNGLPROGRAMUNIFORM3IVEXTPROC glad_glProgramUniform3ivEXT; +#define glProgramUniform3ivEXT glad_glProgramUniform3ivEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM3UIPROC glad_glProgramUniform3ui; +#define glProgramUniform3ui glad_glProgramUniform3ui +GLAD_API_CALL PFNGLPROGRAMUNIFORM3UIEXTPROC glad_glProgramUniform3uiEXT; +#define glProgramUniform3uiEXT glad_glProgramUniform3uiEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM3UIVPROC glad_glProgramUniform3uiv; +#define glProgramUniform3uiv glad_glProgramUniform3uiv +GLAD_API_CALL PFNGLPROGRAMUNIFORM3UIVEXTPROC glad_glProgramUniform3uivEXT; +#define glProgramUniform3uivEXT glad_glProgramUniform3uivEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM4DPROC glad_glProgramUniform4d; +#define glProgramUniform4d glad_glProgramUniform4d +GLAD_API_CALL PFNGLPROGRAMUNIFORM4DEXTPROC glad_glProgramUniform4dEXT; +#define glProgramUniform4dEXT glad_glProgramUniform4dEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM4DVPROC glad_glProgramUniform4dv; +#define glProgramUniform4dv glad_glProgramUniform4dv +GLAD_API_CALL PFNGLPROGRAMUNIFORM4DVEXTPROC glad_glProgramUniform4dvEXT; +#define glProgramUniform4dvEXT glad_glProgramUniform4dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM4FPROC glad_glProgramUniform4f; +#define glProgramUniform4f glad_glProgramUniform4f +GLAD_API_CALL PFNGLPROGRAMUNIFORM4FEXTPROC glad_glProgramUniform4fEXT; +#define glProgramUniform4fEXT glad_glProgramUniform4fEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM4FVPROC glad_glProgramUniform4fv; +#define glProgramUniform4fv glad_glProgramUniform4fv +GLAD_API_CALL PFNGLPROGRAMUNIFORM4FVEXTPROC glad_glProgramUniform4fvEXT; +#define glProgramUniform4fvEXT glad_glProgramUniform4fvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM4IPROC glad_glProgramUniform4i; +#define glProgramUniform4i glad_glProgramUniform4i +GLAD_API_CALL PFNGLPROGRAMUNIFORM4IEXTPROC glad_glProgramUniform4iEXT; +#define glProgramUniform4iEXT glad_glProgramUniform4iEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM4IVPROC glad_glProgramUniform4iv; +#define glProgramUniform4iv glad_glProgramUniform4iv +GLAD_API_CALL PFNGLPROGRAMUNIFORM4IVEXTPROC glad_glProgramUniform4ivEXT; +#define glProgramUniform4ivEXT glad_glProgramUniform4ivEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM4UIPROC glad_glProgramUniform4ui; +#define glProgramUniform4ui glad_glProgramUniform4ui +GLAD_API_CALL PFNGLPROGRAMUNIFORM4UIEXTPROC glad_glProgramUniform4uiEXT; +#define glProgramUniform4uiEXT glad_glProgramUniform4uiEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORM4UIVPROC glad_glProgramUniform4uiv; +#define glProgramUniform4uiv glad_glProgramUniform4uiv +GLAD_API_CALL PFNGLPROGRAMUNIFORM4UIVEXTPROC glad_glProgramUniform4uivEXT; +#define glProgramUniform4uivEXT glad_glProgramUniform4uivEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2DVPROC glad_glProgramUniformMatrix2dv; +#define glProgramUniformMatrix2dv glad_glProgramUniformMatrix2dv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC glad_glProgramUniformMatrix2dvEXT; +#define glProgramUniformMatrix2dvEXT glad_glProgramUniformMatrix2dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2FVPROC glad_glProgramUniformMatrix2fv; +#define glProgramUniformMatrix2fv glad_glProgramUniformMatrix2fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC glad_glProgramUniformMatrix2fvEXT; +#define glProgramUniformMatrix2fvEXT glad_glProgramUniformMatrix2fvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC glad_glProgramUniformMatrix2x3dv; +#define glProgramUniformMatrix2x3dv glad_glProgramUniformMatrix2x3dv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC glad_glProgramUniformMatrix2x3dvEXT; +#define glProgramUniformMatrix2x3dvEXT glad_glProgramUniformMatrix2x3dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC glad_glProgramUniformMatrix2x3fv; +#define glProgramUniformMatrix2x3fv glad_glProgramUniformMatrix2x3fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC glad_glProgramUniformMatrix2x3fvEXT; +#define glProgramUniformMatrix2x3fvEXT glad_glProgramUniformMatrix2x3fvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC glad_glProgramUniformMatrix2x4dv; +#define glProgramUniformMatrix2x4dv glad_glProgramUniformMatrix2x4dv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC glad_glProgramUniformMatrix2x4dvEXT; +#define glProgramUniformMatrix2x4dvEXT glad_glProgramUniformMatrix2x4dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC glad_glProgramUniformMatrix2x4fv; +#define glProgramUniformMatrix2x4fv glad_glProgramUniformMatrix2x4fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC glad_glProgramUniformMatrix2x4fvEXT; +#define glProgramUniformMatrix2x4fvEXT glad_glProgramUniformMatrix2x4fvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3DVPROC glad_glProgramUniformMatrix3dv; +#define glProgramUniformMatrix3dv glad_glProgramUniformMatrix3dv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC glad_glProgramUniformMatrix3dvEXT; +#define glProgramUniformMatrix3dvEXT glad_glProgramUniformMatrix3dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3FVPROC glad_glProgramUniformMatrix3fv; +#define glProgramUniformMatrix3fv glad_glProgramUniformMatrix3fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC glad_glProgramUniformMatrix3fvEXT; +#define glProgramUniformMatrix3fvEXT glad_glProgramUniformMatrix3fvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC glad_glProgramUniformMatrix3x2dv; +#define glProgramUniformMatrix3x2dv glad_glProgramUniformMatrix3x2dv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC glad_glProgramUniformMatrix3x2dvEXT; +#define glProgramUniformMatrix3x2dvEXT glad_glProgramUniformMatrix3x2dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC glad_glProgramUniformMatrix3x2fv; +#define glProgramUniformMatrix3x2fv glad_glProgramUniformMatrix3x2fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC glad_glProgramUniformMatrix3x2fvEXT; +#define glProgramUniformMatrix3x2fvEXT glad_glProgramUniformMatrix3x2fvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC glad_glProgramUniformMatrix3x4dv; +#define glProgramUniformMatrix3x4dv glad_glProgramUniformMatrix3x4dv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC glad_glProgramUniformMatrix3x4dvEXT; +#define glProgramUniformMatrix3x4dvEXT glad_glProgramUniformMatrix3x4dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC glad_glProgramUniformMatrix3x4fv; +#define glProgramUniformMatrix3x4fv glad_glProgramUniformMatrix3x4fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC glad_glProgramUniformMatrix3x4fvEXT; +#define glProgramUniformMatrix3x4fvEXT glad_glProgramUniformMatrix3x4fvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4DVPROC glad_glProgramUniformMatrix4dv; +#define glProgramUniformMatrix4dv glad_glProgramUniformMatrix4dv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC glad_glProgramUniformMatrix4dvEXT; +#define glProgramUniformMatrix4dvEXT glad_glProgramUniformMatrix4dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4FVPROC glad_glProgramUniformMatrix4fv; +#define glProgramUniformMatrix4fv glad_glProgramUniformMatrix4fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC glad_glProgramUniformMatrix4fvEXT; +#define glProgramUniformMatrix4fvEXT glad_glProgramUniformMatrix4fvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC glad_glProgramUniformMatrix4x2dv; +#define glProgramUniformMatrix4x2dv glad_glProgramUniformMatrix4x2dv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC glad_glProgramUniformMatrix4x2dvEXT; +#define glProgramUniformMatrix4x2dvEXT glad_glProgramUniformMatrix4x2dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC glad_glProgramUniformMatrix4x2fv; +#define glProgramUniformMatrix4x2fv glad_glProgramUniformMatrix4x2fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC glad_glProgramUniformMatrix4x2fvEXT; +#define glProgramUniformMatrix4x2fvEXT glad_glProgramUniformMatrix4x2fvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC glad_glProgramUniformMatrix4x3dv; +#define glProgramUniformMatrix4x3dv glad_glProgramUniformMatrix4x3dv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC glad_glProgramUniformMatrix4x3dvEXT; +#define glProgramUniformMatrix4x3dvEXT glad_glProgramUniformMatrix4x3dvEXT +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC glad_glProgramUniformMatrix4x3fv; +#define glProgramUniformMatrix4x3fv glad_glProgramUniformMatrix4x3fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC glad_glProgramUniformMatrix4x3fvEXT; +#define glProgramUniformMatrix4x3fvEXT glad_glProgramUniformMatrix4x3fvEXT +GLAD_API_CALL PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex; +#define glProvokingVertex glad_glProvokingVertex +GLAD_API_CALL PFNGLPUSHATTRIBPROC glad_glPushAttrib; +#define glPushAttrib glad_glPushAttrib +GLAD_API_CALL PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib; +#define glPushClientAttrib glad_glPushClientAttrib +GLAD_API_CALL PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC glad_glPushClientAttribDefaultEXT; +#define glPushClientAttribDefaultEXT glad_glPushClientAttribDefaultEXT +GLAD_API_CALL PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup; +#define glPushDebugGroup glad_glPushDebugGroup +GLAD_API_CALL PFNGLPUSHMATRIXPROC glad_glPushMatrix; +#define glPushMatrix glad_glPushMatrix +GLAD_API_CALL PFNGLPUSHNAMEPROC glad_glPushName; +#define glPushName glad_glPushName +GLAD_API_CALL PFNGLQUERYCOUNTERPROC glad_glQueryCounter; +#define glQueryCounter glad_glQueryCounter +GLAD_API_CALL PFNGLRASTERPOS2DPROC glad_glRasterPos2d; +#define glRasterPos2d glad_glRasterPos2d +GLAD_API_CALL PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv; +#define glRasterPos2dv glad_glRasterPos2dv +GLAD_API_CALL PFNGLRASTERPOS2FPROC glad_glRasterPos2f; +#define glRasterPos2f glad_glRasterPos2f +GLAD_API_CALL PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv; +#define glRasterPos2fv glad_glRasterPos2fv +GLAD_API_CALL PFNGLRASTERPOS2IPROC glad_glRasterPos2i; +#define glRasterPos2i glad_glRasterPos2i +GLAD_API_CALL PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv; +#define glRasterPos2iv glad_glRasterPos2iv +GLAD_API_CALL PFNGLRASTERPOS2SPROC glad_glRasterPos2s; +#define glRasterPos2s glad_glRasterPos2s +GLAD_API_CALL PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv; +#define glRasterPos2sv glad_glRasterPos2sv +GLAD_API_CALL PFNGLRASTERPOS3DPROC glad_glRasterPos3d; +#define glRasterPos3d glad_glRasterPos3d +GLAD_API_CALL PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv; +#define glRasterPos3dv glad_glRasterPos3dv +GLAD_API_CALL PFNGLRASTERPOS3FPROC glad_glRasterPos3f; +#define glRasterPos3f glad_glRasterPos3f +GLAD_API_CALL PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv; +#define glRasterPos3fv glad_glRasterPos3fv +GLAD_API_CALL PFNGLRASTERPOS3IPROC glad_glRasterPos3i; +#define glRasterPos3i glad_glRasterPos3i +GLAD_API_CALL PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv; +#define glRasterPos3iv glad_glRasterPos3iv +GLAD_API_CALL PFNGLRASTERPOS3SPROC glad_glRasterPos3s; +#define glRasterPos3s glad_glRasterPos3s +GLAD_API_CALL PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv; +#define glRasterPos3sv glad_glRasterPos3sv +GLAD_API_CALL PFNGLRASTERPOS4DPROC glad_glRasterPos4d; +#define glRasterPos4d glad_glRasterPos4d +GLAD_API_CALL PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv; +#define glRasterPos4dv glad_glRasterPos4dv +GLAD_API_CALL PFNGLRASTERPOS4FPROC glad_glRasterPos4f; +#define glRasterPos4f glad_glRasterPos4f +GLAD_API_CALL PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv; +#define glRasterPos4fv glad_glRasterPos4fv +GLAD_API_CALL PFNGLRASTERPOS4IPROC glad_glRasterPos4i; +#define glRasterPos4i glad_glRasterPos4i +GLAD_API_CALL PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv; +#define glRasterPos4iv glad_glRasterPos4iv +GLAD_API_CALL PFNGLRASTERPOS4SPROC glad_glRasterPos4s; +#define glRasterPos4s glad_glRasterPos4s +GLAD_API_CALL PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv; +#define glRasterPos4sv glad_glRasterPos4sv +GLAD_API_CALL PFNGLREADBUFFERPROC glad_glReadBuffer; +#define glReadBuffer glad_glReadBuffer +GLAD_API_CALL PFNGLREADPIXELSPROC glad_glReadPixels; +#define glReadPixels glad_glReadPixels +GLAD_API_CALL PFNGLREADNPIXELSPROC glad_glReadnPixels; +#define glReadnPixels glad_glReadnPixels +GLAD_API_CALL PFNGLRECTDPROC glad_glRectd; +#define glRectd glad_glRectd +GLAD_API_CALL PFNGLRECTDVPROC glad_glRectdv; +#define glRectdv glad_glRectdv +GLAD_API_CALL PFNGLRECTFPROC glad_glRectf; +#define glRectf glad_glRectf +GLAD_API_CALL PFNGLRECTFVPROC glad_glRectfv; +#define glRectfv glad_glRectfv +GLAD_API_CALL PFNGLRECTIPROC glad_glRecti; +#define glRecti glad_glRecti +GLAD_API_CALL PFNGLRECTIVPROC glad_glRectiv; +#define glRectiv glad_glRectiv +GLAD_API_CALL PFNGLRECTSPROC glad_glRects; +#define glRects glad_glRects +GLAD_API_CALL PFNGLRECTSVPROC glad_glRectsv; +#define glRectsv glad_glRectsv +GLAD_API_CALL PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler; +#define glReleaseShaderCompiler glad_glReleaseShaderCompiler +GLAD_API_CALL PFNGLRENDERMODEPROC glad_glRenderMode; +#define glRenderMode glad_glRenderMode +GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage; +#define glRenderbufferStorage glad_glRenderbufferStorage +GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT; +#define glRenderbufferStorageEXT glad_glRenderbufferStorageEXT +GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample; +#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample +GLAD_API_CALL PFNGLRESUMETRANSFORMFEEDBACKPROC glad_glResumeTransformFeedback; +#define glResumeTransformFeedback glad_glResumeTransformFeedback +GLAD_API_CALL PFNGLROTATEDPROC glad_glRotated; +#define glRotated glad_glRotated +GLAD_API_CALL PFNGLROTATEFPROC glad_glRotatef; +#define glRotatef glad_glRotatef +GLAD_API_CALL PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage; +#define glSampleCoverage glad_glSampleCoverage +GLAD_API_CALL PFNGLSAMPLEMASKIPROC glad_glSampleMaski; +#define glSampleMaski glad_glSampleMaski +GLAD_API_CALL PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv; +#define glSamplerParameterIiv glad_glSamplerParameterIiv +GLAD_API_CALL PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv; +#define glSamplerParameterIuiv glad_glSamplerParameterIuiv +GLAD_API_CALL PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf; +#define glSamplerParameterf glad_glSamplerParameterf +GLAD_API_CALL PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv; +#define glSamplerParameterfv glad_glSamplerParameterfv +GLAD_API_CALL PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri; +#define glSamplerParameteri glad_glSamplerParameteri +GLAD_API_CALL PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv; +#define glSamplerParameteriv glad_glSamplerParameteriv +GLAD_API_CALL PFNGLSCALEDPROC glad_glScaled; +#define glScaled glad_glScaled +GLAD_API_CALL PFNGLSCALEFPROC glad_glScalef; +#define glScalef glad_glScalef +GLAD_API_CALL PFNGLSCISSORPROC glad_glScissor; +#define glScissor glad_glScissor +GLAD_API_CALL PFNGLSCISSORARRAYVPROC glad_glScissorArrayv; +#define glScissorArrayv glad_glScissorArrayv +GLAD_API_CALL PFNGLSCISSORINDEXEDPROC glad_glScissorIndexed; +#define glScissorIndexed glad_glScissorIndexed +GLAD_API_CALL PFNGLSCISSORINDEXEDVPROC glad_glScissorIndexedv; +#define glScissorIndexedv glad_glScissorIndexedv +GLAD_API_CALL PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b; +#define glSecondaryColor3b glad_glSecondaryColor3b +GLAD_API_CALL PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv; +#define glSecondaryColor3bv glad_glSecondaryColor3bv +GLAD_API_CALL PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d; +#define glSecondaryColor3d glad_glSecondaryColor3d +GLAD_API_CALL PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv; +#define glSecondaryColor3dv glad_glSecondaryColor3dv +GLAD_API_CALL PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f; +#define glSecondaryColor3f glad_glSecondaryColor3f +GLAD_API_CALL PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv; +#define glSecondaryColor3fv glad_glSecondaryColor3fv +GLAD_API_CALL PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i; +#define glSecondaryColor3i glad_glSecondaryColor3i +GLAD_API_CALL PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv; +#define glSecondaryColor3iv glad_glSecondaryColor3iv +GLAD_API_CALL PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s; +#define glSecondaryColor3s glad_glSecondaryColor3s +GLAD_API_CALL PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv; +#define glSecondaryColor3sv glad_glSecondaryColor3sv +GLAD_API_CALL PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub; +#define glSecondaryColor3ub glad_glSecondaryColor3ub +GLAD_API_CALL PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv; +#define glSecondaryColor3ubv glad_glSecondaryColor3ubv +GLAD_API_CALL PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui; +#define glSecondaryColor3ui glad_glSecondaryColor3ui +GLAD_API_CALL PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv; +#define glSecondaryColor3uiv glad_glSecondaryColor3uiv +GLAD_API_CALL PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us; +#define glSecondaryColor3us glad_glSecondaryColor3us +GLAD_API_CALL PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv; +#define glSecondaryColor3usv glad_glSecondaryColor3usv +GLAD_API_CALL PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui; +#define glSecondaryColorP3ui glad_glSecondaryColorP3ui +GLAD_API_CALL PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv; +#define glSecondaryColorP3uiv glad_glSecondaryColorP3uiv +GLAD_API_CALL PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer; +#define glSecondaryColorPointer glad_glSecondaryColorPointer +GLAD_API_CALL PFNGLSELECTBUFFERPROC glad_glSelectBuffer; +#define glSelectBuffer glad_glSelectBuffer +GLAD_API_CALL PFNGLSHADEMODELPROC glad_glShadeModel; +#define glShadeModel glad_glShadeModel +GLAD_API_CALL PFNGLSHADERBINARYPROC glad_glShaderBinary; +#define glShaderBinary glad_glShaderBinary +GLAD_API_CALL PFNGLSHADERSOURCEPROC glad_glShaderSource; +#define glShaderSource glad_glShaderSource +GLAD_API_CALL PFNGLSHADERSOURCEARBPROC glad_glShaderSourceARB; +#define glShaderSourceARB glad_glShaderSourceARB +GLAD_API_CALL PFNGLSHADERSTORAGEBLOCKBINDINGPROC glad_glShaderStorageBlockBinding; +#define glShaderStorageBlockBinding glad_glShaderStorageBlockBinding +GLAD_API_CALL PFNGLSPECIALIZESHADERPROC glad_glSpecializeShader; +#define glSpecializeShader glad_glSpecializeShader +GLAD_API_CALL PFNGLSTENCILFUNCPROC glad_glStencilFunc; +#define glStencilFunc glad_glStencilFunc +GLAD_API_CALL PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate; +#define glStencilFuncSeparate glad_glStencilFuncSeparate +GLAD_API_CALL PFNGLSTENCILMASKPROC glad_glStencilMask; +#define glStencilMask glad_glStencilMask +GLAD_API_CALL PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate; +#define glStencilMaskSeparate glad_glStencilMaskSeparate +GLAD_API_CALL PFNGLSTENCILOPPROC glad_glStencilOp; +#define glStencilOp glad_glStencilOp +GLAD_API_CALL PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate; +#define glStencilOpSeparate glad_glStencilOpSeparate +GLAD_API_CALL PFNGLSUBPIXELPRECISIONBIASNVPROC glad_glSubpixelPrecisionBiasNV; +#define glSubpixelPrecisionBiasNV glad_glSubpixelPrecisionBiasNV +GLAD_API_CALL PFNGLTEXBUFFERPROC glad_glTexBuffer; +#define glTexBuffer glad_glTexBuffer +GLAD_API_CALL PFNGLTEXBUFFERRANGEPROC glad_glTexBufferRange; +#define glTexBufferRange glad_glTexBufferRange +GLAD_API_CALL PFNGLTEXCOORD1DPROC glad_glTexCoord1d; +#define glTexCoord1d glad_glTexCoord1d +GLAD_API_CALL PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv; +#define glTexCoord1dv glad_glTexCoord1dv +GLAD_API_CALL PFNGLTEXCOORD1FPROC glad_glTexCoord1f; +#define glTexCoord1f glad_glTexCoord1f +GLAD_API_CALL PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv; +#define glTexCoord1fv glad_glTexCoord1fv +GLAD_API_CALL PFNGLTEXCOORD1IPROC glad_glTexCoord1i; +#define glTexCoord1i glad_glTexCoord1i +GLAD_API_CALL PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv; +#define glTexCoord1iv glad_glTexCoord1iv +GLAD_API_CALL PFNGLTEXCOORD1SPROC glad_glTexCoord1s; +#define glTexCoord1s glad_glTexCoord1s +GLAD_API_CALL PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv; +#define glTexCoord1sv glad_glTexCoord1sv +GLAD_API_CALL PFNGLTEXCOORD2DPROC glad_glTexCoord2d; +#define glTexCoord2d glad_glTexCoord2d +GLAD_API_CALL PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv; +#define glTexCoord2dv glad_glTexCoord2dv +GLAD_API_CALL PFNGLTEXCOORD2FPROC glad_glTexCoord2f; +#define glTexCoord2f glad_glTexCoord2f +GLAD_API_CALL PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv; +#define glTexCoord2fv glad_glTexCoord2fv +GLAD_API_CALL PFNGLTEXCOORD2IPROC glad_glTexCoord2i; +#define glTexCoord2i glad_glTexCoord2i +GLAD_API_CALL PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv; +#define glTexCoord2iv glad_glTexCoord2iv +GLAD_API_CALL PFNGLTEXCOORD2SPROC glad_glTexCoord2s; +#define glTexCoord2s glad_glTexCoord2s +GLAD_API_CALL PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv; +#define glTexCoord2sv glad_glTexCoord2sv +GLAD_API_CALL PFNGLTEXCOORD3DPROC glad_glTexCoord3d; +#define glTexCoord3d glad_glTexCoord3d +GLAD_API_CALL PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv; +#define glTexCoord3dv glad_glTexCoord3dv +GLAD_API_CALL PFNGLTEXCOORD3FPROC glad_glTexCoord3f; +#define glTexCoord3f glad_glTexCoord3f +GLAD_API_CALL PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv; +#define glTexCoord3fv glad_glTexCoord3fv +GLAD_API_CALL PFNGLTEXCOORD3IPROC glad_glTexCoord3i; +#define glTexCoord3i glad_glTexCoord3i +GLAD_API_CALL PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv; +#define glTexCoord3iv glad_glTexCoord3iv +GLAD_API_CALL PFNGLTEXCOORD3SPROC glad_glTexCoord3s; +#define glTexCoord3s glad_glTexCoord3s +GLAD_API_CALL PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv; +#define glTexCoord3sv glad_glTexCoord3sv +GLAD_API_CALL PFNGLTEXCOORD4DPROC glad_glTexCoord4d; +#define glTexCoord4d glad_glTexCoord4d +GLAD_API_CALL PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv; +#define glTexCoord4dv glad_glTexCoord4dv +GLAD_API_CALL PFNGLTEXCOORD4FPROC glad_glTexCoord4f; +#define glTexCoord4f glad_glTexCoord4f +GLAD_API_CALL PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv; +#define glTexCoord4fv glad_glTexCoord4fv +GLAD_API_CALL PFNGLTEXCOORD4IPROC glad_glTexCoord4i; +#define glTexCoord4i glad_glTexCoord4i +GLAD_API_CALL PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv; +#define glTexCoord4iv glad_glTexCoord4iv +GLAD_API_CALL PFNGLTEXCOORD4SPROC glad_glTexCoord4s; +#define glTexCoord4s glad_glTexCoord4s +GLAD_API_CALL PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv; +#define glTexCoord4sv glad_glTexCoord4sv +GLAD_API_CALL PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui; +#define glTexCoordP1ui glad_glTexCoordP1ui +GLAD_API_CALL PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv; +#define glTexCoordP1uiv glad_glTexCoordP1uiv +GLAD_API_CALL PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui; +#define glTexCoordP2ui glad_glTexCoordP2ui +GLAD_API_CALL PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv; +#define glTexCoordP2uiv glad_glTexCoordP2uiv +GLAD_API_CALL PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui; +#define glTexCoordP3ui glad_glTexCoordP3ui +GLAD_API_CALL PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv; +#define glTexCoordP3uiv glad_glTexCoordP3uiv +GLAD_API_CALL PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui; +#define glTexCoordP4ui glad_glTexCoordP4ui +GLAD_API_CALL PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv; +#define glTexCoordP4uiv glad_glTexCoordP4uiv +GLAD_API_CALL PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer; +#define glTexCoordPointer glad_glTexCoordPointer +GLAD_API_CALL PFNGLTEXENVFPROC glad_glTexEnvf; +#define glTexEnvf glad_glTexEnvf +GLAD_API_CALL PFNGLTEXENVFVPROC glad_glTexEnvfv; +#define glTexEnvfv glad_glTexEnvfv +GLAD_API_CALL PFNGLTEXENVIPROC glad_glTexEnvi; +#define glTexEnvi glad_glTexEnvi +GLAD_API_CALL PFNGLTEXENVIVPROC glad_glTexEnviv; +#define glTexEnviv glad_glTexEnviv +GLAD_API_CALL PFNGLTEXGENDPROC glad_glTexGend; +#define glTexGend glad_glTexGend +GLAD_API_CALL PFNGLTEXGENDVPROC glad_glTexGendv; +#define glTexGendv glad_glTexGendv +GLAD_API_CALL PFNGLTEXGENFPROC glad_glTexGenf; +#define glTexGenf glad_glTexGenf +GLAD_API_CALL PFNGLTEXGENFVPROC glad_glTexGenfv; +#define glTexGenfv glad_glTexGenfv +GLAD_API_CALL PFNGLTEXGENIPROC glad_glTexGeni; +#define glTexGeni glad_glTexGeni +GLAD_API_CALL PFNGLTEXGENIVPROC glad_glTexGeniv; +#define glTexGeniv glad_glTexGeniv +GLAD_API_CALL PFNGLTEXIMAGE1DPROC glad_glTexImage1D; +#define glTexImage1D glad_glTexImage1D +GLAD_API_CALL PFNGLTEXIMAGE2DPROC glad_glTexImage2D; +#define glTexImage2D glad_glTexImage2D +GLAD_API_CALL PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample; +#define glTexImage2DMultisample glad_glTexImage2DMultisample +GLAD_API_CALL PFNGLTEXIMAGE3DPROC glad_glTexImage3D; +#define glTexImage3D glad_glTexImage3D +GLAD_API_CALL PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample; +#define glTexImage3DMultisample glad_glTexImage3DMultisample +GLAD_API_CALL PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv; +#define glTexParameterIiv glad_glTexParameterIiv +GLAD_API_CALL PFNGLTEXPARAMETERIIVEXTPROC glad_glTexParameterIivEXT; +#define glTexParameterIivEXT glad_glTexParameterIivEXT +GLAD_API_CALL PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv; +#define glTexParameterIuiv glad_glTexParameterIuiv +GLAD_API_CALL PFNGLTEXPARAMETERIUIVEXTPROC glad_glTexParameterIuivEXT; +#define glTexParameterIuivEXT glad_glTexParameterIuivEXT +GLAD_API_CALL PFNGLTEXPARAMETERFPROC glad_glTexParameterf; +#define glTexParameterf glad_glTexParameterf +GLAD_API_CALL PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv; +#define glTexParameterfv glad_glTexParameterfv +GLAD_API_CALL PFNGLTEXPARAMETERIPROC glad_glTexParameteri; +#define glTexParameteri glad_glTexParameteri +GLAD_API_CALL PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv; +#define glTexParameteriv glad_glTexParameteriv +GLAD_API_CALL PFNGLTEXSTORAGE1DPROC glad_glTexStorage1D; +#define glTexStorage1D glad_glTexStorage1D +GLAD_API_CALL PFNGLTEXSTORAGE2DPROC glad_glTexStorage2D; +#define glTexStorage2D glad_glTexStorage2D +GLAD_API_CALL PFNGLTEXSTORAGE2DMULTISAMPLEPROC glad_glTexStorage2DMultisample; +#define glTexStorage2DMultisample glad_glTexStorage2DMultisample +GLAD_API_CALL PFNGLTEXSTORAGE3DPROC glad_glTexStorage3D; +#define glTexStorage3D glad_glTexStorage3D +GLAD_API_CALL PFNGLTEXSTORAGE3DMULTISAMPLEPROC glad_glTexStorage3DMultisample; +#define glTexStorage3DMultisample glad_glTexStorage3DMultisample +GLAD_API_CALL PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D; +#define glTexSubImage1D glad_glTexSubImage1D +GLAD_API_CALL PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D; +#define glTexSubImage2D glad_glTexSubImage2D +GLAD_API_CALL PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D; +#define glTexSubImage3D glad_glTexSubImage3D +GLAD_API_CALL PFNGLTEXTUREBARRIERPROC glad_glTextureBarrier; +#define glTextureBarrier glad_glTextureBarrier +GLAD_API_CALL PFNGLTEXTUREBUFFERPROC glad_glTextureBuffer; +#define glTextureBuffer glad_glTextureBuffer +GLAD_API_CALL PFNGLTEXTUREBUFFEREXTPROC glad_glTextureBufferEXT; +#define glTextureBufferEXT glad_glTextureBufferEXT +GLAD_API_CALL PFNGLTEXTUREBUFFERRANGEPROC glad_glTextureBufferRange; +#define glTextureBufferRange glad_glTextureBufferRange +GLAD_API_CALL PFNGLTEXTUREBUFFERRANGEEXTPROC glad_glTextureBufferRangeEXT; +#define glTextureBufferRangeEXT glad_glTextureBufferRangeEXT +GLAD_API_CALL PFNGLTEXTUREIMAGE1DEXTPROC glad_glTextureImage1DEXT; +#define glTextureImage1DEXT glad_glTextureImage1DEXT +GLAD_API_CALL PFNGLTEXTUREIMAGE2DEXTPROC glad_glTextureImage2DEXT; +#define glTextureImage2DEXT glad_glTextureImage2DEXT +GLAD_API_CALL PFNGLTEXTUREIMAGE3DEXTPROC glad_glTextureImage3DEXT; +#define glTextureImage3DEXT glad_glTextureImage3DEXT +GLAD_API_CALL PFNGLTEXTUREPAGECOMMITMENTEXTPROC glad_glTexturePageCommitmentEXT; +#define glTexturePageCommitmentEXT glad_glTexturePageCommitmentEXT +GLAD_API_CALL PFNGLTEXTUREPARAMETERIIVPROC glad_glTextureParameterIiv; +#define glTextureParameterIiv glad_glTextureParameterIiv +GLAD_API_CALL PFNGLTEXTUREPARAMETERIIVEXTPROC glad_glTextureParameterIivEXT; +#define glTextureParameterIivEXT glad_glTextureParameterIivEXT +GLAD_API_CALL PFNGLTEXTUREPARAMETERIUIVPROC glad_glTextureParameterIuiv; +#define glTextureParameterIuiv glad_glTextureParameterIuiv +GLAD_API_CALL PFNGLTEXTUREPARAMETERIUIVEXTPROC glad_glTextureParameterIuivEXT; +#define glTextureParameterIuivEXT glad_glTextureParameterIuivEXT +GLAD_API_CALL PFNGLTEXTUREPARAMETERFPROC glad_glTextureParameterf; +#define glTextureParameterf glad_glTextureParameterf +GLAD_API_CALL PFNGLTEXTUREPARAMETERFEXTPROC glad_glTextureParameterfEXT; +#define glTextureParameterfEXT glad_glTextureParameterfEXT +GLAD_API_CALL PFNGLTEXTUREPARAMETERFVPROC glad_glTextureParameterfv; +#define glTextureParameterfv glad_glTextureParameterfv +GLAD_API_CALL PFNGLTEXTUREPARAMETERFVEXTPROC glad_glTextureParameterfvEXT; +#define glTextureParameterfvEXT glad_glTextureParameterfvEXT +GLAD_API_CALL PFNGLTEXTUREPARAMETERIPROC glad_glTextureParameteri; +#define glTextureParameteri glad_glTextureParameteri +GLAD_API_CALL PFNGLTEXTUREPARAMETERIEXTPROC glad_glTextureParameteriEXT; +#define glTextureParameteriEXT glad_glTextureParameteriEXT +GLAD_API_CALL PFNGLTEXTUREPARAMETERIVPROC glad_glTextureParameteriv; +#define glTextureParameteriv glad_glTextureParameteriv +GLAD_API_CALL PFNGLTEXTUREPARAMETERIVEXTPROC glad_glTextureParameterivEXT; +#define glTextureParameterivEXT glad_glTextureParameterivEXT +GLAD_API_CALL PFNGLTEXTURERENDERBUFFEREXTPROC glad_glTextureRenderbufferEXT; +#define glTextureRenderbufferEXT glad_glTextureRenderbufferEXT +GLAD_API_CALL PFNGLTEXTURESTORAGE1DPROC glad_glTextureStorage1D; +#define glTextureStorage1D glad_glTextureStorage1D +GLAD_API_CALL PFNGLTEXTURESTORAGE1DEXTPROC glad_glTextureStorage1DEXT; +#define glTextureStorage1DEXT glad_glTextureStorage1DEXT +GLAD_API_CALL PFNGLTEXTURESTORAGE2DPROC glad_glTextureStorage2D; +#define glTextureStorage2D glad_glTextureStorage2D +GLAD_API_CALL PFNGLTEXTURESTORAGE2DEXTPROC glad_glTextureStorage2DEXT; +#define glTextureStorage2DEXT glad_glTextureStorage2DEXT +GLAD_API_CALL PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glad_glTextureStorage2DMultisample; +#define glTextureStorage2DMultisample glad_glTextureStorage2DMultisample +GLAD_API_CALL PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC glad_glTextureStorage2DMultisampleEXT; +#define glTextureStorage2DMultisampleEXT glad_glTextureStorage2DMultisampleEXT +GLAD_API_CALL PFNGLTEXTURESTORAGE3DPROC glad_glTextureStorage3D; +#define glTextureStorage3D glad_glTextureStorage3D +GLAD_API_CALL PFNGLTEXTURESTORAGE3DEXTPROC glad_glTextureStorage3DEXT; +#define glTextureStorage3DEXT glad_glTextureStorage3DEXT +GLAD_API_CALL PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glad_glTextureStorage3DMultisample; +#define glTextureStorage3DMultisample glad_glTextureStorage3DMultisample +GLAD_API_CALL PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC glad_glTextureStorage3DMultisampleEXT; +#define glTextureStorage3DMultisampleEXT glad_glTextureStorage3DMultisampleEXT +GLAD_API_CALL PFNGLTEXTURESUBIMAGE1DPROC glad_glTextureSubImage1D; +#define glTextureSubImage1D glad_glTextureSubImage1D +GLAD_API_CALL PFNGLTEXTURESUBIMAGE1DEXTPROC glad_glTextureSubImage1DEXT; +#define glTextureSubImage1DEXT glad_glTextureSubImage1DEXT +GLAD_API_CALL PFNGLTEXTURESUBIMAGE2DPROC glad_glTextureSubImage2D; +#define glTextureSubImage2D glad_glTextureSubImage2D +GLAD_API_CALL PFNGLTEXTURESUBIMAGE2DEXTPROC glad_glTextureSubImage2DEXT; +#define glTextureSubImage2DEXT glad_glTextureSubImage2DEXT +GLAD_API_CALL PFNGLTEXTURESUBIMAGE3DPROC glad_glTextureSubImage3D; +#define glTextureSubImage3D glad_glTextureSubImage3D +GLAD_API_CALL PFNGLTEXTURESUBIMAGE3DEXTPROC glad_glTextureSubImage3DEXT; +#define glTextureSubImage3DEXT glad_glTextureSubImage3DEXT +GLAD_API_CALL PFNGLTEXTUREVIEWPROC glad_glTextureView; +#define glTextureView glad_glTextureView +GLAD_API_CALL PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glad_glTransformFeedbackBufferBase; +#define glTransformFeedbackBufferBase glad_glTransformFeedbackBufferBase +GLAD_API_CALL PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glad_glTransformFeedbackBufferRange; +#define glTransformFeedbackBufferRange glad_glTransformFeedbackBufferRange +GLAD_API_CALL PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings; +#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings +GLAD_API_CALL PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC glad_glTransformFeedbackVaryingsEXT; +#define glTransformFeedbackVaryingsEXT glad_glTransformFeedbackVaryingsEXT +GLAD_API_CALL PFNGLTRANSLATEDPROC glad_glTranslated; +#define glTranslated glad_glTranslated +GLAD_API_CALL PFNGLTRANSLATEFPROC glad_glTranslatef; +#define glTranslatef glad_glTranslatef +GLAD_API_CALL PFNGLUNIFORM1DPROC glad_glUniform1d; +#define glUniform1d glad_glUniform1d +GLAD_API_CALL PFNGLUNIFORM1DVPROC glad_glUniform1dv; +#define glUniform1dv glad_glUniform1dv +GLAD_API_CALL PFNGLUNIFORM1FPROC glad_glUniform1f; +#define glUniform1f glad_glUniform1f +GLAD_API_CALL PFNGLUNIFORM1FARBPROC glad_glUniform1fARB; +#define glUniform1fARB glad_glUniform1fARB +GLAD_API_CALL PFNGLUNIFORM1FVPROC glad_glUniform1fv; +#define glUniform1fv glad_glUniform1fv +GLAD_API_CALL PFNGLUNIFORM1FVARBPROC glad_glUniform1fvARB; +#define glUniform1fvARB glad_glUniform1fvARB +GLAD_API_CALL PFNGLUNIFORM1IPROC glad_glUniform1i; +#define glUniform1i glad_glUniform1i +GLAD_API_CALL PFNGLUNIFORM1IARBPROC glad_glUniform1iARB; +#define glUniform1iARB glad_glUniform1iARB +GLAD_API_CALL PFNGLUNIFORM1IVPROC glad_glUniform1iv; +#define glUniform1iv glad_glUniform1iv +GLAD_API_CALL PFNGLUNIFORM1IVARBPROC glad_glUniform1ivARB; +#define glUniform1ivARB glad_glUniform1ivARB +GLAD_API_CALL PFNGLUNIFORM1UIPROC glad_glUniform1ui; +#define glUniform1ui glad_glUniform1ui +GLAD_API_CALL PFNGLUNIFORM1UIEXTPROC glad_glUniform1uiEXT; +#define glUniform1uiEXT glad_glUniform1uiEXT +GLAD_API_CALL PFNGLUNIFORM1UIVPROC glad_glUniform1uiv; +#define glUniform1uiv glad_glUniform1uiv +GLAD_API_CALL PFNGLUNIFORM1UIVEXTPROC glad_glUniform1uivEXT; +#define glUniform1uivEXT glad_glUniform1uivEXT +GLAD_API_CALL PFNGLUNIFORM2DPROC glad_glUniform2d; +#define glUniform2d glad_glUniform2d +GLAD_API_CALL PFNGLUNIFORM2DVPROC glad_glUniform2dv; +#define glUniform2dv glad_glUniform2dv +GLAD_API_CALL PFNGLUNIFORM2FPROC glad_glUniform2f; +#define glUniform2f glad_glUniform2f +GLAD_API_CALL PFNGLUNIFORM2FARBPROC glad_glUniform2fARB; +#define glUniform2fARB glad_glUniform2fARB +GLAD_API_CALL PFNGLUNIFORM2FVPROC glad_glUniform2fv; +#define glUniform2fv glad_glUniform2fv +GLAD_API_CALL PFNGLUNIFORM2FVARBPROC glad_glUniform2fvARB; +#define glUniform2fvARB glad_glUniform2fvARB +GLAD_API_CALL PFNGLUNIFORM2IPROC glad_glUniform2i; +#define glUniform2i glad_glUniform2i +GLAD_API_CALL PFNGLUNIFORM2IARBPROC glad_glUniform2iARB; +#define glUniform2iARB glad_glUniform2iARB +GLAD_API_CALL PFNGLUNIFORM2IVPROC glad_glUniform2iv; +#define glUniform2iv glad_glUniform2iv +GLAD_API_CALL PFNGLUNIFORM2IVARBPROC glad_glUniform2ivARB; +#define glUniform2ivARB glad_glUniform2ivARB +GLAD_API_CALL PFNGLUNIFORM2UIPROC glad_glUniform2ui; +#define glUniform2ui glad_glUniform2ui +GLAD_API_CALL PFNGLUNIFORM2UIEXTPROC glad_glUniform2uiEXT; +#define glUniform2uiEXT glad_glUniform2uiEXT +GLAD_API_CALL PFNGLUNIFORM2UIVPROC glad_glUniform2uiv; +#define glUniform2uiv glad_glUniform2uiv +GLAD_API_CALL PFNGLUNIFORM2UIVEXTPROC glad_glUniform2uivEXT; +#define glUniform2uivEXT glad_glUniform2uivEXT +GLAD_API_CALL PFNGLUNIFORM3DPROC glad_glUniform3d; +#define glUniform3d glad_glUniform3d +GLAD_API_CALL PFNGLUNIFORM3DVPROC glad_glUniform3dv; +#define glUniform3dv glad_glUniform3dv +GLAD_API_CALL PFNGLUNIFORM3FPROC glad_glUniform3f; +#define glUniform3f glad_glUniform3f +GLAD_API_CALL PFNGLUNIFORM3FARBPROC glad_glUniform3fARB; +#define glUniform3fARB glad_glUniform3fARB +GLAD_API_CALL PFNGLUNIFORM3FVPROC glad_glUniform3fv; +#define glUniform3fv glad_glUniform3fv +GLAD_API_CALL PFNGLUNIFORM3FVARBPROC glad_glUniform3fvARB; +#define glUniform3fvARB glad_glUniform3fvARB +GLAD_API_CALL PFNGLUNIFORM3IPROC glad_glUniform3i; +#define glUniform3i glad_glUniform3i +GLAD_API_CALL PFNGLUNIFORM3IARBPROC glad_glUniform3iARB; +#define glUniform3iARB glad_glUniform3iARB +GLAD_API_CALL PFNGLUNIFORM3IVPROC glad_glUniform3iv; +#define glUniform3iv glad_glUniform3iv +GLAD_API_CALL PFNGLUNIFORM3IVARBPROC glad_glUniform3ivARB; +#define glUniform3ivARB glad_glUniform3ivARB +GLAD_API_CALL PFNGLUNIFORM3UIPROC glad_glUniform3ui; +#define glUniform3ui glad_glUniform3ui +GLAD_API_CALL PFNGLUNIFORM3UIEXTPROC glad_glUniform3uiEXT; +#define glUniform3uiEXT glad_glUniform3uiEXT +GLAD_API_CALL PFNGLUNIFORM3UIVPROC glad_glUniform3uiv; +#define glUniform3uiv glad_glUniform3uiv +GLAD_API_CALL PFNGLUNIFORM3UIVEXTPROC glad_glUniform3uivEXT; +#define glUniform3uivEXT glad_glUniform3uivEXT +GLAD_API_CALL PFNGLUNIFORM4DPROC glad_glUniform4d; +#define glUniform4d glad_glUniform4d +GLAD_API_CALL PFNGLUNIFORM4DVPROC glad_glUniform4dv; +#define glUniform4dv glad_glUniform4dv +GLAD_API_CALL PFNGLUNIFORM4FPROC glad_glUniform4f; +#define glUniform4f glad_glUniform4f +GLAD_API_CALL PFNGLUNIFORM4FARBPROC glad_glUniform4fARB; +#define glUniform4fARB glad_glUniform4fARB +GLAD_API_CALL PFNGLUNIFORM4FVPROC glad_glUniform4fv; +#define glUniform4fv glad_glUniform4fv +GLAD_API_CALL PFNGLUNIFORM4FVARBPROC glad_glUniform4fvARB; +#define glUniform4fvARB glad_glUniform4fvARB +GLAD_API_CALL PFNGLUNIFORM4IPROC glad_glUniform4i; +#define glUniform4i glad_glUniform4i +GLAD_API_CALL PFNGLUNIFORM4IARBPROC glad_glUniform4iARB; +#define glUniform4iARB glad_glUniform4iARB +GLAD_API_CALL PFNGLUNIFORM4IVPROC glad_glUniform4iv; +#define glUniform4iv glad_glUniform4iv +GLAD_API_CALL PFNGLUNIFORM4IVARBPROC glad_glUniform4ivARB; +#define glUniform4ivARB glad_glUniform4ivARB +GLAD_API_CALL PFNGLUNIFORM4UIPROC glad_glUniform4ui; +#define glUniform4ui glad_glUniform4ui +GLAD_API_CALL PFNGLUNIFORM4UIEXTPROC glad_glUniform4uiEXT; +#define glUniform4uiEXT glad_glUniform4uiEXT +GLAD_API_CALL PFNGLUNIFORM4UIVPROC glad_glUniform4uiv; +#define glUniform4uiv glad_glUniform4uiv +GLAD_API_CALL PFNGLUNIFORM4UIVEXTPROC glad_glUniform4uivEXT; +#define glUniform4uivEXT glad_glUniform4uivEXT +GLAD_API_CALL PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding; +#define glUniformBlockBinding glad_glUniformBlockBinding +GLAD_API_CALL PFNGLUNIFORMMATRIX2DVPROC glad_glUniformMatrix2dv; +#define glUniformMatrix2dv glad_glUniformMatrix2dv +GLAD_API_CALL PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv; +#define glUniformMatrix2fv glad_glUniformMatrix2fv +GLAD_API_CALL PFNGLUNIFORMMATRIX2FVARBPROC glad_glUniformMatrix2fvARB; +#define glUniformMatrix2fvARB glad_glUniformMatrix2fvARB +GLAD_API_CALL PFNGLUNIFORMMATRIX2X3DVPROC glad_glUniformMatrix2x3dv; +#define glUniformMatrix2x3dv glad_glUniformMatrix2x3dv +GLAD_API_CALL PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv; +#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv +GLAD_API_CALL PFNGLUNIFORMMATRIX2X4DVPROC glad_glUniformMatrix2x4dv; +#define glUniformMatrix2x4dv glad_glUniformMatrix2x4dv +GLAD_API_CALL PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv; +#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv +GLAD_API_CALL PFNGLUNIFORMMATRIX3DVPROC glad_glUniformMatrix3dv; +#define glUniformMatrix3dv glad_glUniformMatrix3dv +GLAD_API_CALL PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv; +#define glUniformMatrix3fv glad_glUniformMatrix3fv +GLAD_API_CALL PFNGLUNIFORMMATRIX3FVARBPROC glad_glUniformMatrix3fvARB; +#define glUniformMatrix3fvARB glad_glUniformMatrix3fvARB +GLAD_API_CALL PFNGLUNIFORMMATRIX3X2DVPROC glad_glUniformMatrix3x2dv; +#define glUniformMatrix3x2dv glad_glUniformMatrix3x2dv +GLAD_API_CALL PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv; +#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv +GLAD_API_CALL PFNGLUNIFORMMATRIX3X4DVPROC glad_glUniformMatrix3x4dv; +#define glUniformMatrix3x4dv glad_glUniformMatrix3x4dv +GLAD_API_CALL PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv; +#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv +GLAD_API_CALL PFNGLUNIFORMMATRIX4DVPROC glad_glUniformMatrix4dv; +#define glUniformMatrix4dv glad_glUniformMatrix4dv +GLAD_API_CALL PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv; +#define glUniformMatrix4fv glad_glUniformMatrix4fv +GLAD_API_CALL PFNGLUNIFORMMATRIX4FVARBPROC glad_glUniformMatrix4fvARB; +#define glUniformMatrix4fvARB glad_glUniformMatrix4fvARB +GLAD_API_CALL PFNGLUNIFORMMATRIX4X2DVPROC glad_glUniformMatrix4x2dv; +#define glUniformMatrix4x2dv glad_glUniformMatrix4x2dv +GLAD_API_CALL PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv; +#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv +GLAD_API_CALL PFNGLUNIFORMMATRIX4X3DVPROC glad_glUniformMatrix4x3dv; +#define glUniformMatrix4x3dv glad_glUniformMatrix4x3dv +GLAD_API_CALL PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv; +#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv +GLAD_API_CALL PFNGLUNIFORMSUBROUTINESUIVPROC glad_glUniformSubroutinesuiv; +#define glUniformSubroutinesuiv glad_glUniformSubroutinesuiv +GLAD_API_CALL PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer; +#define glUnmapBuffer glad_glUnmapBuffer +GLAD_API_CALL PFNGLUNMAPBUFFERARBPROC glad_glUnmapBufferARB; +#define glUnmapBufferARB glad_glUnmapBufferARB +GLAD_API_CALL PFNGLUNMAPNAMEDBUFFERPROC glad_glUnmapNamedBuffer; +#define glUnmapNamedBuffer glad_glUnmapNamedBuffer +GLAD_API_CALL PFNGLUNMAPNAMEDBUFFEREXTPROC glad_glUnmapNamedBufferEXT; +#define glUnmapNamedBufferEXT glad_glUnmapNamedBufferEXT +GLAD_API_CALL PFNGLUSEPROGRAMPROC glad_glUseProgram; +#define glUseProgram glad_glUseProgram +GLAD_API_CALL PFNGLUSEPROGRAMOBJECTARBPROC glad_glUseProgramObjectARB; +#define glUseProgramObjectARB glad_glUseProgramObjectARB +GLAD_API_CALL PFNGLUSEPROGRAMSTAGESPROC glad_glUseProgramStages; +#define glUseProgramStages glad_glUseProgramStages +GLAD_API_CALL PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram; +#define glValidateProgram glad_glValidateProgram +GLAD_API_CALL PFNGLVALIDATEPROGRAMARBPROC glad_glValidateProgramARB; +#define glValidateProgramARB glad_glValidateProgramARB +GLAD_API_CALL PFNGLVALIDATEPROGRAMPIPELINEPROC glad_glValidateProgramPipeline; +#define glValidateProgramPipeline glad_glValidateProgramPipeline +GLAD_API_CALL PFNGLVERTEX2DPROC glad_glVertex2d; +#define glVertex2d glad_glVertex2d +GLAD_API_CALL PFNGLVERTEX2DVPROC glad_glVertex2dv; +#define glVertex2dv glad_glVertex2dv +GLAD_API_CALL PFNGLVERTEX2FPROC glad_glVertex2f; +#define glVertex2f glad_glVertex2f +GLAD_API_CALL PFNGLVERTEX2FVPROC glad_glVertex2fv; +#define glVertex2fv glad_glVertex2fv +GLAD_API_CALL PFNGLVERTEX2IPROC glad_glVertex2i; +#define glVertex2i glad_glVertex2i +GLAD_API_CALL PFNGLVERTEX2IVPROC glad_glVertex2iv; +#define glVertex2iv glad_glVertex2iv +GLAD_API_CALL PFNGLVERTEX2SPROC glad_glVertex2s; +#define glVertex2s glad_glVertex2s +GLAD_API_CALL PFNGLVERTEX2SVPROC glad_glVertex2sv; +#define glVertex2sv glad_glVertex2sv +GLAD_API_CALL PFNGLVERTEX3DPROC glad_glVertex3d; +#define glVertex3d glad_glVertex3d +GLAD_API_CALL PFNGLVERTEX3DVPROC glad_glVertex3dv; +#define glVertex3dv glad_glVertex3dv +GLAD_API_CALL PFNGLVERTEX3FPROC glad_glVertex3f; +#define glVertex3f glad_glVertex3f +GLAD_API_CALL PFNGLVERTEX3FVPROC glad_glVertex3fv; +#define glVertex3fv glad_glVertex3fv +GLAD_API_CALL PFNGLVERTEX3IPROC glad_glVertex3i; +#define glVertex3i glad_glVertex3i +GLAD_API_CALL PFNGLVERTEX3IVPROC glad_glVertex3iv; +#define glVertex3iv glad_glVertex3iv +GLAD_API_CALL PFNGLVERTEX3SPROC glad_glVertex3s; +#define glVertex3s glad_glVertex3s +GLAD_API_CALL PFNGLVERTEX3SVPROC glad_glVertex3sv; +#define glVertex3sv glad_glVertex3sv +GLAD_API_CALL PFNGLVERTEX4DPROC glad_glVertex4d; +#define glVertex4d glad_glVertex4d +GLAD_API_CALL PFNGLVERTEX4DVPROC glad_glVertex4dv; +#define glVertex4dv glad_glVertex4dv +GLAD_API_CALL PFNGLVERTEX4FPROC glad_glVertex4f; +#define glVertex4f glad_glVertex4f +GLAD_API_CALL PFNGLVERTEX4FVPROC glad_glVertex4fv; +#define glVertex4fv glad_glVertex4fv +GLAD_API_CALL PFNGLVERTEX4IPROC glad_glVertex4i; +#define glVertex4i glad_glVertex4i +GLAD_API_CALL PFNGLVERTEX4IVPROC glad_glVertex4iv; +#define glVertex4iv glad_glVertex4iv +GLAD_API_CALL PFNGLVERTEX4SPROC glad_glVertex4s; +#define glVertex4s glad_glVertex4s +GLAD_API_CALL PFNGLVERTEX4SVPROC glad_glVertex4sv; +#define glVertex4sv glad_glVertex4sv +GLAD_API_CALL PFNGLVERTEXARRAYATTRIBBINDINGPROC glad_glVertexArrayAttribBinding; +#define glVertexArrayAttribBinding glad_glVertexArrayAttribBinding +GLAD_API_CALL PFNGLVERTEXARRAYATTRIBFORMATPROC glad_glVertexArrayAttribFormat; +#define glVertexArrayAttribFormat glad_glVertexArrayAttribFormat +GLAD_API_CALL PFNGLVERTEXARRAYATTRIBIFORMATPROC glad_glVertexArrayAttribIFormat; +#define glVertexArrayAttribIFormat glad_glVertexArrayAttribIFormat +GLAD_API_CALL PFNGLVERTEXARRAYATTRIBLFORMATPROC glad_glVertexArrayAttribLFormat; +#define glVertexArrayAttribLFormat glad_glVertexArrayAttribLFormat +GLAD_API_CALL PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC glad_glVertexArrayBindVertexBufferEXT; +#define glVertexArrayBindVertexBufferEXT glad_glVertexArrayBindVertexBufferEXT +GLAD_API_CALL PFNGLVERTEXARRAYBINDINGDIVISORPROC glad_glVertexArrayBindingDivisor; +#define glVertexArrayBindingDivisor glad_glVertexArrayBindingDivisor +GLAD_API_CALL PFNGLVERTEXARRAYCOLOROFFSETEXTPROC glad_glVertexArrayColorOffsetEXT; +#define glVertexArrayColorOffsetEXT glad_glVertexArrayColorOffsetEXT +GLAD_API_CALL PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC glad_glVertexArrayEdgeFlagOffsetEXT; +#define glVertexArrayEdgeFlagOffsetEXT glad_glVertexArrayEdgeFlagOffsetEXT +GLAD_API_CALL PFNGLVERTEXARRAYELEMENTBUFFERPROC glad_glVertexArrayElementBuffer; +#define glVertexArrayElementBuffer glad_glVertexArrayElementBuffer +GLAD_API_CALL PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC glad_glVertexArrayFogCoordOffsetEXT; +#define glVertexArrayFogCoordOffsetEXT glad_glVertexArrayFogCoordOffsetEXT +GLAD_API_CALL PFNGLVERTEXARRAYINDEXOFFSETEXTPROC glad_glVertexArrayIndexOffsetEXT; +#define glVertexArrayIndexOffsetEXT glad_glVertexArrayIndexOffsetEXT +GLAD_API_CALL PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC glad_glVertexArrayMultiTexCoordOffsetEXT; +#define glVertexArrayMultiTexCoordOffsetEXT glad_glVertexArrayMultiTexCoordOffsetEXT +GLAD_API_CALL PFNGLVERTEXARRAYNORMALOFFSETEXTPROC glad_glVertexArrayNormalOffsetEXT; +#define glVertexArrayNormalOffsetEXT glad_glVertexArrayNormalOffsetEXT +GLAD_API_CALL PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC glad_glVertexArraySecondaryColorOffsetEXT; +#define glVertexArraySecondaryColorOffsetEXT glad_glVertexArraySecondaryColorOffsetEXT +GLAD_API_CALL PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC glad_glVertexArrayTexCoordOffsetEXT; +#define glVertexArrayTexCoordOffsetEXT glad_glVertexArrayTexCoordOffsetEXT +GLAD_API_CALL PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC glad_glVertexArrayVertexAttribBindingEXT; +#define glVertexArrayVertexAttribBindingEXT glad_glVertexArrayVertexAttribBindingEXT +GLAD_API_CALL PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC glad_glVertexArrayVertexAttribDivisorEXT; +#define glVertexArrayVertexAttribDivisorEXT glad_glVertexArrayVertexAttribDivisorEXT +GLAD_API_CALL PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC glad_glVertexArrayVertexAttribFormatEXT; +#define glVertexArrayVertexAttribFormatEXT glad_glVertexArrayVertexAttribFormatEXT +GLAD_API_CALL PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC glad_glVertexArrayVertexAttribIFormatEXT; +#define glVertexArrayVertexAttribIFormatEXT glad_glVertexArrayVertexAttribIFormatEXT +GLAD_API_CALL PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC glad_glVertexArrayVertexAttribIOffsetEXT; +#define glVertexArrayVertexAttribIOffsetEXT glad_glVertexArrayVertexAttribIOffsetEXT +GLAD_API_CALL PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC glad_glVertexArrayVertexAttribLFormatEXT; +#define glVertexArrayVertexAttribLFormatEXT glad_glVertexArrayVertexAttribLFormatEXT +GLAD_API_CALL PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC glad_glVertexArrayVertexAttribLOffsetEXT; +#define glVertexArrayVertexAttribLOffsetEXT glad_glVertexArrayVertexAttribLOffsetEXT +GLAD_API_CALL PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC glad_glVertexArrayVertexAttribOffsetEXT; +#define glVertexArrayVertexAttribOffsetEXT glad_glVertexArrayVertexAttribOffsetEXT +GLAD_API_CALL PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC glad_glVertexArrayVertexBindingDivisorEXT; +#define glVertexArrayVertexBindingDivisorEXT glad_glVertexArrayVertexBindingDivisorEXT +GLAD_API_CALL PFNGLVERTEXARRAYVERTEXBUFFERPROC glad_glVertexArrayVertexBuffer; +#define glVertexArrayVertexBuffer glad_glVertexArrayVertexBuffer +GLAD_API_CALL PFNGLVERTEXARRAYVERTEXBUFFERSPROC glad_glVertexArrayVertexBuffers; +#define glVertexArrayVertexBuffers glad_glVertexArrayVertexBuffers +GLAD_API_CALL PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC glad_glVertexArrayVertexOffsetEXT; +#define glVertexArrayVertexOffsetEXT glad_glVertexArrayVertexOffsetEXT +GLAD_API_CALL PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d; +#define glVertexAttrib1d glad_glVertexAttrib1d +GLAD_API_CALL PFNGLVERTEXATTRIB1DARBPROC glad_glVertexAttrib1dARB; +#define glVertexAttrib1dARB glad_glVertexAttrib1dARB +GLAD_API_CALL PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv; +#define glVertexAttrib1dv glad_glVertexAttrib1dv +GLAD_API_CALL PFNGLVERTEXATTRIB1DVARBPROC glad_glVertexAttrib1dvARB; +#define glVertexAttrib1dvARB glad_glVertexAttrib1dvARB +GLAD_API_CALL PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f; +#define glVertexAttrib1f glad_glVertexAttrib1f +GLAD_API_CALL PFNGLVERTEXATTRIB1FARBPROC glad_glVertexAttrib1fARB; +#define glVertexAttrib1fARB glad_glVertexAttrib1fARB +GLAD_API_CALL PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv; +#define glVertexAttrib1fv glad_glVertexAttrib1fv +GLAD_API_CALL PFNGLVERTEXATTRIB1FVARBPROC glad_glVertexAttrib1fvARB; +#define glVertexAttrib1fvARB glad_glVertexAttrib1fvARB +GLAD_API_CALL PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s; +#define glVertexAttrib1s glad_glVertexAttrib1s +GLAD_API_CALL PFNGLVERTEXATTRIB1SARBPROC glad_glVertexAttrib1sARB; +#define glVertexAttrib1sARB glad_glVertexAttrib1sARB +GLAD_API_CALL PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv; +#define glVertexAttrib1sv glad_glVertexAttrib1sv +GLAD_API_CALL PFNGLVERTEXATTRIB1SVARBPROC glad_glVertexAttrib1svARB; +#define glVertexAttrib1svARB glad_glVertexAttrib1svARB +GLAD_API_CALL PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d; +#define glVertexAttrib2d glad_glVertexAttrib2d +GLAD_API_CALL PFNGLVERTEXATTRIB2DARBPROC glad_glVertexAttrib2dARB; +#define glVertexAttrib2dARB glad_glVertexAttrib2dARB +GLAD_API_CALL PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv; +#define glVertexAttrib2dv glad_glVertexAttrib2dv +GLAD_API_CALL PFNGLVERTEXATTRIB2DVARBPROC glad_glVertexAttrib2dvARB; +#define glVertexAttrib2dvARB glad_glVertexAttrib2dvARB +GLAD_API_CALL PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f; +#define glVertexAttrib2f glad_glVertexAttrib2f +GLAD_API_CALL PFNGLVERTEXATTRIB2FARBPROC glad_glVertexAttrib2fARB; +#define glVertexAttrib2fARB glad_glVertexAttrib2fARB +GLAD_API_CALL PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv; +#define glVertexAttrib2fv glad_glVertexAttrib2fv +GLAD_API_CALL PFNGLVERTEXATTRIB2FVARBPROC glad_glVertexAttrib2fvARB; +#define glVertexAttrib2fvARB glad_glVertexAttrib2fvARB +GLAD_API_CALL PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s; +#define glVertexAttrib2s glad_glVertexAttrib2s +GLAD_API_CALL PFNGLVERTEXATTRIB2SARBPROC glad_glVertexAttrib2sARB; +#define glVertexAttrib2sARB glad_glVertexAttrib2sARB +GLAD_API_CALL PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv; +#define glVertexAttrib2sv glad_glVertexAttrib2sv +GLAD_API_CALL PFNGLVERTEXATTRIB2SVARBPROC glad_glVertexAttrib2svARB; +#define glVertexAttrib2svARB glad_glVertexAttrib2svARB +GLAD_API_CALL PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d; +#define glVertexAttrib3d glad_glVertexAttrib3d +GLAD_API_CALL PFNGLVERTEXATTRIB3DARBPROC glad_glVertexAttrib3dARB; +#define glVertexAttrib3dARB glad_glVertexAttrib3dARB +GLAD_API_CALL PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv; +#define glVertexAttrib3dv glad_glVertexAttrib3dv +GLAD_API_CALL PFNGLVERTEXATTRIB3DVARBPROC glad_glVertexAttrib3dvARB; +#define glVertexAttrib3dvARB glad_glVertexAttrib3dvARB +GLAD_API_CALL PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f; +#define glVertexAttrib3f glad_glVertexAttrib3f +GLAD_API_CALL PFNGLVERTEXATTRIB3FARBPROC glad_glVertexAttrib3fARB; +#define glVertexAttrib3fARB glad_glVertexAttrib3fARB +GLAD_API_CALL PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv; +#define glVertexAttrib3fv glad_glVertexAttrib3fv +GLAD_API_CALL PFNGLVERTEXATTRIB3FVARBPROC glad_glVertexAttrib3fvARB; +#define glVertexAttrib3fvARB glad_glVertexAttrib3fvARB +GLAD_API_CALL PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s; +#define glVertexAttrib3s glad_glVertexAttrib3s +GLAD_API_CALL PFNGLVERTEXATTRIB3SARBPROC glad_glVertexAttrib3sARB; +#define glVertexAttrib3sARB glad_glVertexAttrib3sARB +GLAD_API_CALL PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv; +#define glVertexAttrib3sv glad_glVertexAttrib3sv +GLAD_API_CALL PFNGLVERTEXATTRIB3SVARBPROC glad_glVertexAttrib3svARB; +#define glVertexAttrib3svARB glad_glVertexAttrib3svARB +GLAD_API_CALL PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv; +#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv +GLAD_API_CALL PFNGLVERTEXATTRIB4NBVARBPROC glad_glVertexAttrib4NbvARB; +#define glVertexAttrib4NbvARB glad_glVertexAttrib4NbvARB +GLAD_API_CALL PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv; +#define glVertexAttrib4Niv glad_glVertexAttrib4Niv +GLAD_API_CALL PFNGLVERTEXATTRIB4NIVARBPROC glad_glVertexAttrib4NivARB; +#define glVertexAttrib4NivARB glad_glVertexAttrib4NivARB +GLAD_API_CALL PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv; +#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv +GLAD_API_CALL PFNGLVERTEXATTRIB4NSVARBPROC glad_glVertexAttrib4NsvARB; +#define glVertexAttrib4NsvARB glad_glVertexAttrib4NsvARB +GLAD_API_CALL PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub; +#define glVertexAttrib4Nub glad_glVertexAttrib4Nub +GLAD_API_CALL PFNGLVERTEXATTRIB4NUBARBPROC glad_glVertexAttrib4NubARB; +#define glVertexAttrib4NubARB glad_glVertexAttrib4NubARB +GLAD_API_CALL PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv; +#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv +GLAD_API_CALL PFNGLVERTEXATTRIB4NUBVARBPROC glad_glVertexAttrib4NubvARB; +#define glVertexAttrib4NubvARB glad_glVertexAttrib4NubvARB +GLAD_API_CALL PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv; +#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv +GLAD_API_CALL PFNGLVERTEXATTRIB4NUIVARBPROC glad_glVertexAttrib4NuivARB; +#define glVertexAttrib4NuivARB glad_glVertexAttrib4NuivARB +GLAD_API_CALL PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv; +#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv +GLAD_API_CALL PFNGLVERTEXATTRIB4NUSVARBPROC glad_glVertexAttrib4NusvARB; +#define glVertexAttrib4NusvARB glad_glVertexAttrib4NusvARB +GLAD_API_CALL PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv; +#define glVertexAttrib4bv glad_glVertexAttrib4bv +GLAD_API_CALL PFNGLVERTEXATTRIB4BVARBPROC glad_glVertexAttrib4bvARB; +#define glVertexAttrib4bvARB glad_glVertexAttrib4bvARB +GLAD_API_CALL PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d; +#define glVertexAttrib4d glad_glVertexAttrib4d +GLAD_API_CALL PFNGLVERTEXATTRIB4DARBPROC glad_glVertexAttrib4dARB; +#define glVertexAttrib4dARB glad_glVertexAttrib4dARB +GLAD_API_CALL PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv; +#define glVertexAttrib4dv glad_glVertexAttrib4dv +GLAD_API_CALL PFNGLVERTEXATTRIB4DVARBPROC glad_glVertexAttrib4dvARB; +#define glVertexAttrib4dvARB glad_glVertexAttrib4dvARB +GLAD_API_CALL PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f; +#define glVertexAttrib4f glad_glVertexAttrib4f +GLAD_API_CALL PFNGLVERTEXATTRIB4FARBPROC glad_glVertexAttrib4fARB; +#define glVertexAttrib4fARB glad_glVertexAttrib4fARB +GLAD_API_CALL PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv; +#define glVertexAttrib4fv glad_glVertexAttrib4fv +GLAD_API_CALL PFNGLVERTEXATTRIB4FVARBPROC glad_glVertexAttrib4fvARB; +#define glVertexAttrib4fvARB glad_glVertexAttrib4fvARB +GLAD_API_CALL PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv; +#define glVertexAttrib4iv glad_glVertexAttrib4iv +GLAD_API_CALL PFNGLVERTEXATTRIB4IVARBPROC glad_glVertexAttrib4ivARB; +#define glVertexAttrib4ivARB glad_glVertexAttrib4ivARB +GLAD_API_CALL PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s; +#define glVertexAttrib4s glad_glVertexAttrib4s +GLAD_API_CALL PFNGLVERTEXATTRIB4SARBPROC glad_glVertexAttrib4sARB; +#define glVertexAttrib4sARB glad_glVertexAttrib4sARB +GLAD_API_CALL PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv; +#define glVertexAttrib4sv glad_glVertexAttrib4sv +GLAD_API_CALL PFNGLVERTEXATTRIB4SVARBPROC glad_glVertexAttrib4svARB; +#define glVertexAttrib4svARB glad_glVertexAttrib4svARB +GLAD_API_CALL PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv; +#define glVertexAttrib4ubv glad_glVertexAttrib4ubv +GLAD_API_CALL PFNGLVERTEXATTRIB4UBVARBPROC glad_glVertexAttrib4ubvARB; +#define glVertexAttrib4ubvARB glad_glVertexAttrib4ubvARB +GLAD_API_CALL PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv; +#define glVertexAttrib4uiv glad_glVertexAttrib4uiv +GLAD_API_CALL PFNGLVERTEXATTRIB4UIVARBPROC glad_glVertexAttrib4uivARB; +#define glVertexAttrib4uivARB glad_glVertexAttrib4uivARB +GLAD_API_CALL PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv; +#define glVertexAttrib4usv glad_glVertexAttrib4usv +GLAD_API_CALL PFNGLVERTEXATTRIB4USVARBPROC glad_glVertexAttrib4usvARB; +#define glVertexAttrib4usvARB glad_glVertexAttrib4usvARB +GLAD_API_CALL PFNGLVERTEXATTRIBBINDINGPROC glad_glVertexAttribBinding; +#define glVertexAttribBinding glad_glVertexAttribBinding +GLAD_API_CALL PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor; +#define glVertexAttribDivisor glad_glVertexAttribDivisor +GLAD_API_CALL PFNGLVERTEXATTRIBFORMATPROC glad_glVertexAttribFormat; +#define glVertexAttribFormat glad_glVertexAttribFormat +GLAD_API_CALL PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i; +#define glVertexAttribI1i glad_glVertexAttribI1i +GLAD_API_CALL PFNGLVERTEXATTRIBI1IEXTPROC glad_glVertexAttribI1iEXT; +#define glVertexAttribI1iEXT glad_glVertexAttribI1iEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv; +#define glVertexAttribI1iv glad_glVertexAttribI1iv +GLAD_API_CALL PFNGLVERTEXATTRIBI1IVEXTPROC glad_glVertexAttribI1ivEXT; +#define glVertexAttribI1ivEXT glad_glVertexAttribI1ivEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui; +#define glVertexAttribI1ui glad_glVertexAttribI1ui +GLAD_API_CALL PFNGLVERTEXATTRIBI1UIEXTPROC glad_glVertexAttribI1uiEXT; +#define glVertexAttribI1uiEXT glad_glVertexAttribI1uiEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv; +#define glVertexAttribI1uiv glad_glVertexAttribI1uiv +GLAD_API_CALL PFNGLVERTEXATTRIBI1UIVEXTPROC glad_glVertexAttribI1uivEXT; +#define glVertexAttribI1uivEXT glad_glVertexAttribI1uivEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i; +#define glVertexAttribI2i glad_glVertexAttribI2i +GLAD_API_CALL PFNGLVERTEXATTRIBI2IEXTPROC glad_glVertexAttribI2iEXT; +#define glVertexAttribI2iEXT glad_glVertexAttribI2iEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv; +#define glVertexAttribI2iv glad_glVertexAttribI2iv +GLAD_API_CALL PFNGLVERTEXATTRIBI2IVEXTPROC glad_glVertexAttribI2ivEXT; +#define glVertexAttribI2ivEXT glad_glVertexAttribI2ivEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui; +#define glVertexAttribI2ui glad_glVertexAttribI2ui +GLAD_API_CALL PFNGLVERTEXATTRIBI2UIEXTPROC glad_glVertexAttribI2uiEXT; +#define glVertexAttribI2uiEXT glad_glVertexAttribI2uiEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv; +#define glVertexAttribI2uiv glad_glVertexAttribI2uiv +GLAD_API_CALL PFNGLVERTEXATTRIBI2UIVEXTPROC glad_glVertexAttribI2uivEXT; +#define glVertexAttribI2uivEXT glad_glVertexAttribI2uivEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i; +#define glVertexAttribI3i glad_glVertexAttribI3i +GLAD_API_CALL PFNGLVERTEXATTRIBI3IEXTPROC glad_glVertexAttribI3iEXT; +#define glVertexAttribI3iEXT glad_glVertexAttribI3iEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv; +#define glVertexAttribI3iv glad_glVertexAttribI3iv +GLAD_API_CALL PFNGLVERTEXATTRIBI3IVEXTPROC glad_glVertexAttribI3ivEXT; +#define glVertexAttribI3ivEXT glad_glVertexAttribI3ivEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui; +#define glVertexAttribI3ui glad_glVertexAttribI3ui +GLAD_API_CALL PFNGLVERTEXATTRIBI3UIEXTPROC glad_glVertexAttribI3uiEXT; +#define glVertexAttribI3uiEXT glad_glVertexAttribI3uiEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv; +#define glVertexAttribI3uiv glad_glVertexAttribI3uiv +GLAD_API_CALL PFNGLVERTEXATTRIBI3UIVEXTPROC glad_glVertexAttribI3uivEXT; +#define glVertexAttribI3uivEXT glad_glVertexAttribI3uivEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv; +#define glVertexAttribI4bv glad_glVertexAttribI4bv +GLAD_API_CALL PFNGLVERTEXATTRIBI4BVEXTPROC glad_glVertexAttribI4bvEXT; +#define glVertexAttribI4bvEXT glad_glVertexAttribI4bvEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i; +#define glVertexAttribI4i glad_glVertexAttribI4i +GLAD_API_CALL PFNGLVERTEXATTRIBI4IEXTPROC glad_glVertexAttribI4iEXT; +#define glVertexAttribI4iEXT glad_glVertexAttribI4iEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv; +#define glVertexAttribI4iv glad_glVertexAttribI4iv +GLAD_API_CALL PFNGLVERTEXATTRIBI4IVEXTPROC glad_glVertexAttribI4ivEXT; +#define glVertexAttribI4ivEXT glad_glVertexAttribI4ivEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv; +#define glVertexAttribI4sv glad_glVertexAttribI4sv +GLAD_API_CALL PFNGLVERTEXATTRIBI4SVEXTPROC glad_glVertexAttribI4svEXT; +#define glVertexAttribI4svEXT glad_glVertexAttribI4svEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv; +#define glVertexAttribI4ubv glad_glVertexAttribI4ubv +GLAD_API_CALL PFNGLVERTEXATTRIBI4UBVEXTPROC glad_glVertexAttribI4ubvEXT; +#define glVertexAttribI4ubvEXT glad_glVertexAttribI4ubvEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui; +#define glVertexAttribI4ui glad_glVertexAttribI4ui +GLAD_API_CALL PFNGLVERTEXATTRIBI4UIEXTPROC glad_glVertexAttribI4uiEXT; +#define glVertexAttribI4uiEXT glad_glVertexAttribI4uiEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv; +#define glVertexAttribI4uiv glad_glVertexAttribI4uiv +GLAD_API_CALL PFNGLVERTEXATTRIBI4UIVEXTPROC glad_glVertexAttribI4uivEXT; +#define glVertexAttribI4uivEXT glad_glVertexAttribI4uivEXT +GLAD_API_CALL PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv; +#define glVertexAttribI4usv glad_glVertexAttribI4usv +GLAD_API_CALL PFNGLVERTEXATTRIBI4USVEXTPROC glad_glVertexAttribI4usvEXT; +#define glVertexAttribI4usvEXT glad_glVertexAttribI4usvEXT +GLAD_API_CALL PFNGLVERTEXATTRIBIFORMATPROC glad_glVertexAttribIFormat; +#define glVertexAttribIFormat glad_glVertexAttribIFormat +GLAD_API_CALL PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer; +#define glVertexAttribIPointer glad_glVertexAttribIPointer +GLAD_API_CALL PFNGLVERTEXATTRIBIPOINTEREXTPROC glad_glVertexAttribIPointerEXT; +#define glVertexAttribIPointerEXT glad_glVertexAttribIPointerEXT +GLAD_API_CALL PFNGLVERTEXATTRIBL1DPROC glad_glVertexAttribL1d; +#define glVertexAttribL1d glad_glVertexAttribL1d +GLAD_API_CALL PFNGLVERTEXATTRIBL1DVPROC glad_glVertexAttribL1dv; +#define glVertexAttribL1dv glad_glVertexAttribL1dv +GLAD_API_CALL PFNGLVERTEXATTRIBL2DPROC glad_glVertexAttribL2d; +#define glVertexAttribL2d glad_glVertexAttribL2d +GLAD_API_CALL PFNGLVERTEXATTRIBL2DVPROC glad_glVertexAttribL2dv; +#define glVertexAttribL2dv glad_glVertexAttribL2dv +GLAD_API_CALL PFNGLVERTEXATTRIBL3DPROC glad_glVertexAttribL3d; +#define glVertexAttribL3d glad_glVertexAttribL3d +GLAD_API_CALL PFNGLVERTEXATTRIBL3DVPROC glad_glVertexAttribL3dv; +#define glVertexAttribL3dv glad_glVertexAttribL3dv +GLAD_API_CALL PFNGLVERTEXATTRIBL4DPROC glad_glVertexAttribL4d; +#define glVertexAttribL4d glad_glVertexAttribL4d +GLAD_API_CALL PFNGLVERTEXATTRIBL4DVPROC glad_glVertexAttribL4dv; +#define glVertexAttribL4dv glad_glVertexAttribL4dv +GLAD_API_CALL PFNGLVERTEXATTRIBLFORMATPROC glad_glVertexAttribLFormat; +#define glVertexAttribLFormat glad_glVertexAttribLFormat +GLAD_API_CALL PFNGLVERTEXATTRIBLPOINTERPROC glad_glVertexAttribLPointer; +#define glVertexAttribLPointer glad_glVertexAttribLPointer +GLAD_API_CALL PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui; +#define glVertexAttribP1ui glad_glVertexAttribP1ui +GLAD_API_CALL PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv; +#define glVertexAttribP1uiv glad_glVertexAttribP1uiv +GLAD_API_CALL PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui; +#define glVertexAttribP2ui glad_glVertexAttribP2ui +GLAD_API_CALL PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv; +#define glVertexAttribP2uiv glad_glVertexAttribP2uiv +GLAD_API_CALL PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui; +#define glVertexAttribP3ui glad_glVertexAttribP3ui +GLAD_API_CALL PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv; +#define glVertexAttribP3uiv glad_glVertexAttribP3uiv +GLAD_API_CALL PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui; +#define glVertexAttribP4ui glad_glVertexAttribP4ui +GLAD_API_CALL PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv; +#define glVertexAttribP4uiv glad_glVertexAttribP4uiv +GLAD_API_CALL PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer; +#define glVertexAttribPointer glad_glVertexAttribPointer +GLAD_API_CALL PFNGLVERTEXATTRIBPOINTERARBPROC glad_glVertexAttribPointerARB; +#define glVertexAttribPointerARB glad_glVertexAttribPointerARB +GLAD_API_CALL PFNGLVERTEXBINDINGDIVISORPROC glad_glVertexBindingDivisor; +#define glVertexBindingDivisor glad_glVertexBindingDivisor +GLAD_API_CALL PFNGLVERTEXP2UIPROC glad_glVertexP2ui; +#define glVertexP2ui glad_glVertexP2ui +GLAD_API_CALL PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv; +#define glVertexP2uiv glad_glVertexP2uiv +GLAD_API_CALL PFNGLVERTEXP3UIPROC glad_glVertexP3ui; +#define glVertexP3ui glad_glVertexP3ui +GLAD_API_CALL PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv; +#define glVertexP3uiv glad_glVertexP3uiv +GLAD_API_CALL PFNGLVERTEXP4UIPROC glad_glVertexP4ui; +#define glVertexP4ui glad_glVertexP4ui +GLAD_API_CALL PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv; +#define glVertexP4uiv glad_glVertexP4uiv +GLAD_API_CALL PFNGLVERTEXPOINTERPROC glad_glVertexPointer; +#define glVertexPointer glad_glVertexPointer +GLAD_API_CALL PFNGLVIEWPORTPROC glad_glViewport; +#define glViewport glad_glViewport +GLAD_API_CALL PFNGLVIEWPORTARRAYVPROC glad_glViewportArrayv; +#define glViewportArrayv glad_glViewportArrayv +GLAD_API_CALL PFNGLVIEWPORTINDEXEDFPROC glad_glViewportIndexedf; +#define glViewportIndexedf glad_glViewportIndexedf +GLAD_API_CALL PFNGLVIEWPORTINDEXEDFVPROC glad_glViewportIndexedfv; +#define glViewportIndexedfv glad_glViewportIndexedfv +GLAD_API_CALL PFNGLWAITSYNCPROC glad_glWaitSync; +#define glWaitSync glad_glWaitSync +GLAD_API_CALL PFNGLWINDOWPOS2DPROC glad_glWindowPos2d; +#define glWindowPos2d glad_glWindowPos2d +GLAD_API_CALL PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv; +#define glWindowPos2dv glad_glWindowPos2dv +GLAD_API_CALL PFNGLWINDOWPOS2FPROC glad_glWindowPos2f; +#define glWindowPos2f glad_glWindowPos2f +GLAD_API_CALL PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv; +#define glWindowPos2fv glad_glWindowPos2fv +GLAD_API_CALL PFNGLWINDOWPOS2IPROC glad_glWindowPos2i; +#define glWindowPos2i glad_glWindowPos2i +GLAD_API_CALL PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv; +#define glWindowPos2iv glad_glWindowPos2iv +GLAD_API_CALL PFNGLWINDOWPOS2SPROC glad_glWindowPos2s; +#define glWindowPos2s glad_glWindowPos2s +GLAD_API_CALL PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv; +#define glWindowPos2sv glad_glWindowPos2sv +GLAD_API_CALL PFNGLWINDOWPOS3DPROC glad_glWindowPos3d; +#define glWindowPos3d glad_glWindowPos3d +GLAD_API_CALL PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv; +#define glWindowPos3dv glad_glWindowPos3dv +GLAD_API_CALL PFNGLWINDOWPOS3FPROC glad_glWindowPos3f; +#define glWindowPos3f glad_glWindowPos3f +GLAD_API_CALL PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv; +#define glWindowPos3fv glad_glWindowPos3fv +GLAD_API_CALL PFNGLWINDOWPOS3IPROC glad_glWindowPos3i; +#define glWindowPos3i glad_glWindowPos3i +GLAD_API_CALL PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv; +#define glWindowPos3iv glad_glWindowPos3iv +GLAD_API_CALL PFNGLWINDOWPOS3SPROC glad_glWindowPos3s; +#define glWindowPos3s glad_glWindowPos3s +GLAD_API_CALL PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv; +#define glWindowPos3sv glad_glWindowPos3sv + + + + + +GLAD_API_CALL int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr); +GLAD_API_CALL int gladLoadGL( GLADloadfunc load); + + + +#ifdef __cplusplus +} +#endif +#endif + +/* Source */ +#ifdef GLAD_GL_IMPLEMENTATION +/** + * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 + */ +#include +#include +#include + +#ifndef GLAD_IMPL_UTIL_C_ +#define GLAD_IMPL_UTIL_C_ + +#ifdef _MSC_VER +#define GLAD_IMPL_UTIL_SSCANF sscanf_s +#else +#define GLAD_IMPL_UTIL_SSCANF sscanf +#endif + +#endif /* GLAD_IMPL_UTIL_C_ */ + +#ifdef __cplusplus +extern "C" { +#endif + + + +int GLAD_GL_VERSION_1_0 = 0; +int GLAD_GL_VERSION_1_1 = 0; +int GLAD_GL_VERSION_1_2 = 0; +int GLAD_GL_VERSION_1_3 = 0; +int GLAD_GL_VERSION_1_4 = 0; +int GLAD_GL_VERSION_1_5 = 0; +int GLAD_GL_VERSION_2_0 = 0; +int GLAD_GL_VERSION_2_1 = 0; +int GLAD_GL_VERSION_3_0 = 0; +int GLAD_GL_VERSION_3_1 = 0; +int GLAD_GL_VERSION_3_2 = 0; +int GLAD_GL_VERSION_3_3 = 0; +int GLAD_GL_VERSION_4_0 = 0; +int GLAD_GL_VERSION_4_1 = 0; +int GLAD_GL_VERSION_4_2 = 0; +int GLAD_GL_VERSION_4_3 = 0; +int GLAD_GL_VERSION_4_4 = 0; +int GLAD_GL_VERSION_4_5 = 0; +int GLAD_GL_VERSION_4_6 = 0; +int GLAD_GL_ARB_compatibility = 0; +int GLAD_GL_ARB_debug_output = 0; +int GLAD_GL_ARB_fragment_program = 0; +int GLAD_GL_ARB_fragment_shader = 0; +int GLAD_GL_ARB_framebuffer_sRGB = 0; +int GLAD_GL_ARB_shader_image_load_store = 0; +int GLAD_GL_ARB_shader_image_size = 0; +int GLAD_GL_ARB_shader_objects = 0; +int GLAD_GL_ARB_shader_storage_buffer_object = 0; +int GLAD_GL_ARB_shading_language_100 = 0; +int GLAD_GL_ARB_texture_float = 0; +int GLAD_GL_ARB_texture_rg = 0; +int GLAD_GL_ARB_texture_rgb10_a2ui = 0; +int GLAD_GL_ARB_vertex_buffer_object = 0; +int GLAD_GL_ARB_vertex_program = 0; +int GLAD_GL_ARB_vertex_shader = 0; +int GLAD_GL_ARB_vertex_type_2_10_10_10_rev = 0; +int GLAD_GL_EXT_direct_state_access = 0; +int GLAD_GL_EXT_framebuffer_blit = 0; +int GLAD_GL_EXT_framebuffer_object = 0; +int GLAD_GL_EXT_framebuffer_sRGB = 0; +int GLAD_GL_EXT_geometry_shader4 = 0; +int GLAD_GL_EXT_gpu_shader4 = 0; +int GLAD_GL_EXT_shader_image_load_store = 0; +int GLAD_GL_EXT_texture_array = 0; +int GLAD_GL_EXT_texture_compression_s3tc = 0; +int GLAD_GL_EXT_texture_integer = 0; +int GLAD_GL_EXT_texture_sRGB = 0; +int GLAD_GL_EXT_transform_feedback = 0; +int GLAD_GL_INTEL_conservative_rasterization = 0; +int GLAD_GL_NV_conservative_raster = 0; + + + +PFNGLACCUMPROC glad_glAccum = NULL; +PFNGLACTIVESHADERPROGRAMPROC glad_glActiveShaderProgram = NULL; +PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL; +PFNGLALPHAFUNCPROC glad_glAlphaFunc = NULL; +PFNGLARETEXTURESRESIDENTPROC glad_glAreTexturesResident = NULL; +PFNGLARRAYELEMENTPROC glad_glArrayElement = NULL; +PFNGLATTACHOBJECTARBPROC glad_glAttachObjectARB = NULL; +PFNGLATTACHSHADERPROC glad_glAttachShader = NULL; +PFNGLBEGINPROC glad_glBegin = NULL; +PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL; +PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL; +PFNGLBEGINQUERYINDEXEDPROC glad_glBeginQueryIndexed = NULL; +PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL; +PFNGLBEGINTRANSFORMFEEDBACKEXTPROC glad_glBeginTransformFeedbackEXT = NULL; +PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL; +PFNGLBINDATTRIBLOCATIONARBPROC glad_glBindAttribLocationARB = NULL; +PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL; +PFNGLBINDBUFFERARBPROC glad_glBindBufferARB = NULL; +PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL; +PFNGLBINDBUFFERBASEEXTPROC glad_glBindBufferBaseEXT = NULL; +PFNGLBINDBUFFEROFFSETEXTPROC glad_glBindBufferOffsetEXT = NULL; +PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL; +PFNGLBINDBUFFERRANGEEXTPROC glad_glBindBufferRangeEXT = NULL; +PFNGLBINDBUFFERSBASEPROC glad_glBindBuffersBase = NULL; +PFNGLBINDBUFFERSRANGEPROC glad_glBindBuffersRange = NULL; +PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL; +PFNGLBINDFRAGDATALOCATIONEXTPROC glad_glBindFragDataLocationEXT = NULL; +PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL; +PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL; +PFNGLBINDFRAMEBUFFEREXTPROC glad_glBindFramebufferEXT = NULL; +PFNGLBINDIMAGETEXTUREPROC glad_glBindImageTexture = NULL; +PFNGLBINDIMAGETEXTUREEXTPROC glad_glBindImageTextureEXT = NULL; +PFNGLBINDIMAGETEXTURESPROC glad_glBindImageTextures = NULL; +PFNGLBINDMULTITEXTUREEXTPROC glad_glBindMultiTextureEXT = NULL; +PFNGLBINDPROGRAMARBPROC glad_glBindProgramARB = NULL; +PFNGLBINDPROGRAMPIPELINEPROC glad_glBindProgramPipeline = NULL; +PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL; +PFNGLBINDRENDERBUFFEREXTPROC glad_glBindRenderbufferEXT = NULL; +PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL; +PFNGLBINDSAMPLERSPROC glad_glBindSamplers = NULL; +PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL; +PFNGLBINDTEXTUREUNITPROC glad_glBindTextureUnit = NULL; +PFNGLBINDTEXTURESPROC glad_glBindTextures = NULL; +PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback = NULL; +PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL; +PFNGLBINDVERTEXBUFFERPROC glad_glBindVertexBuffer = NULL; +PFNGLBINDVERTEXBUFFERSPROC glad_glBindVertexBuffers = NULL; +PFNGLBITMAPPROC glad_glBitmap = NULL; +PFNGLBLENDCOLORPROC glad_glBlendColor = NULL; +PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL; +PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL; +PFNGLBLENDEQUATIONSEPARATEIPROC glad_glBlendEquationSeparatei = NULL; +PFNGLBLENDEQUATIONIPROC glad_glBlendEquationi = NULL; +PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL; +PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL; +PFNGLBLENDFUNCSEPARATEIPROC glad_glBlendFuncSeparatei = NULL; +PFNGLBLENDFUNCIPROC glad_glBlendFunci = NULL; +PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL; +PFNGLBLITFRAMEBUFFEREXTPROC glad_glBlitFramebufferEXT = NULL; +PFNGLBLITNAMEDFRAMEBUFFERPROC glad_glBlitNamedFramebuffer = NULL; +PFNGLBUFFERDATAPROC glad_glBufferData = NULL; +PFNGLBUFFERDATAARBPROC glad_glBufferDataARB = NULL; +PFNGLBUFFERSTORAGEPROC glad_glBufferStorage = NULL; +PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL; +PFNGLBUFFERSUBDATAARBPROC glad_glBufferSubDataARB = NULL; +PFNGLCALLLISTPROC glad_glCallList = NULL; +PFNGLCALLLISTSPROC glad_glCallLists = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glad_glCheckFramebufferStatusEXT = NULL; +PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glad_glCheckNamedFramebufferStatus = NULL; +PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC glad_glCheckNamedFramebufferStatusEXT = NULL; +PFNGLCLAMPCOLORPROC glad_glClampColor = NULL; +PFNGLCLEARPROC glad_glClear = NULL; +PFNGLCLEARACCUMPROC glad_glClearAccum = NULL; +PFNGLCLEARBUFFERDATAPROC glad_glClearBufferData = NULL; +PFNGLCLEARBUFFERSUBDATAPROC glad_glClearBufferSubData = NULL; +PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL; +PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL; +PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL; +PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL; +PFNGLCLEARCOLORPROC glad_glClearColor = NULL; +PFNGLCLEARCOLORIIEXTPROC glad_glClearColorIiEXT = NULL; +PFNGLCLEARCOLORIUIEXTPROC glad_glClearColorIuiEXT = NULL; +PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL; +PFNGLCLEARDEPTHFPROC glad_glClearDepthf = NULL; +PFNGLCLEARINDEXPROC glad_glClearIndex = NULL; +PFNGLCLEARNAMEDBUFFERDATAPROC glad_glClearNamedBufferData = NULL; +PFNGLCLEARNAMEDBUFFERDATAEXTPROC glad_glClearNamedBufferDataEXT = NULL; +PFNGLCLEARNAMEDBUFFERSUBDATAPROC glad_glClearNamedBufferSubData = NULL; +PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC glad_glClearNamedBufferSubDataEXT = NULL; +PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glad_glClearNamedFramebufferfi = NULL; +PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glad_glClearNamedFramebufferfv = NULL; +PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glad_glClearNamedFramebufferiv = NULL; +PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glad_glClearNamedFramebufferuiv = NULL; +PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL; +PFNGLCLEARTEXIMAGEPROC glad_glClearTexImage = NULL; +PFNGLCLEARTEXSUBIMAGEPROC glad_glClearTexSubImage = NULL; +PFNGLCLIENTACTIVETEXTUREPROC glad_glClientActiveTexture = NULL; +PFNGLCLIENTATTRIBDEFAULTEXTPROC glad_glClientAttribDefaultEXT = NULL; +PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL; +PFNGLCLIPCONTROLPROC glad_glClipControl = NULL; +PFNGLCLIPPLANEPROC glad_glClipPlane = NULL; +PFNGLCOLOR3BPROC glad_glColor3b = NULL; +PFNGLCOLOR3BVPROC glad_glColor3bv = NULL; +PFNGLCOLOR3DPROC glad_glColor3d = NULL; +PFNGLCOLOR3DVPROC glad_glColor3dv = NULL; +PFNGLCOLOR3FPROC glad_glColor3f = NULL; +PFNGLCOLOR3FVPROC glad_glColor3fv = NULL; +PFNGLCOLOR3IPROC glad_glColor3i = NULL; +PFNGLCOLOR3IVPROC glad_glColor3iv = NULL; +PFNGLCOLOR3SPROC glad_glColor3s = NULL; +PFNGLCOLOR3SVPROC glad_glColor3sv = NULL; +PFNGLCOLOR3UBPROC glad_glColor3ub = NULL; +PFNGLCOLOR3UBVPROC glad_glColor3ubv = NULL; +PFNGLCOLOR3UIPROC glad_glColor3ui = NULL; +PFNGLCOLOR3UIVPROC glad_glColor3uiv = NULL; +PFNGLCOLOR3USPROC glad_glColor3us = NULL; +PFNGLCOLOR3USVPROC glad_glColor3usv = NULL; +PFNGLCOLOR4BPROC glad_glColor4b = NULL; +PFNGLCOLOR4BVPROC glad_glColor4bv = NULL; +PFNGLCOLOR4DPROC glad_glColor4d = NULL; +PFNGLCOLOR4DVPROC glad_glColor4dv = NULL; +PFNGLCOLOR4FPROC glad_glColor4f = NULL; +PFNGLCOLOR4FVPROC glad_glColor4fv = NULL; +PFNGLCOLOR4IPROC glad_glColor4i = NULL; +PFNGLCOLOR4IVPROC glad_glColor4iv = NULL; +PFNGLCOLOR4SPROC glad_glColor4s = NULL; +PFNGLCOLOR4SVPROC glad_glColor4sv = NULL; +PFNGLCOLOR4UBPROC glad_glColor4ub = NULL; +PFNGLCOLOR4UBVPROC glad_glColor4ubv = NULL; +PFNGLCOLOR4UIPROC glad_glColor4ui = NULL; +PFNGLCOLOR4UIVPROC glad_glColor4uiv = NULL; +PFNGLCOLOR4USPROC glad_glColor4us = NULL; +PFNGLCOLOR4USVPROC glad_glColor4usv = NULL; +PFNGLCOLORMASKPROC glad_glColorMask = NULL; +PFNGLCOLORMASKIPROC glad_glColorMaski = NULL; +PFNGLCOLORMATERIALPROC glad_glColorMaterial = NULL; +PFNGLCOLORP3UIPROC glad_glColorP3ui = NULL; +PFNGLCOLORP3UIVPROC glad_glColorP3uiv = NULL; +PFNGLCOLORP4UIPROC glad_glColorP4ui = NULL; +PFNGLCOLORP4UIVPROC glad_glColorP4uiv = NULL; +PFNGLCOLORPOINTERPROC glad_glColorPointer = NULL; +PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL; +PFNGLCOMPILESHADERARBPROC glad_glCompileShaderARB = NULL; +PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC glad_glCompressedMultiTexImage1DEXT = NULL; +PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC glad_glCompressedMultiTexImage2DEXT = NULL; +PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC glad_glCompressedMultiTexImage3DEXT = NULL; +PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC glad_glCompressedMultiTexSubImage1DEXT = NULL; +PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC glad_glCompressedMultiTexSubImage2DEXT = NULL; +PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC glad_glCompressedMultiTexSubImage3DEXT = NULL; +PFNGLCOMPRESSEDTEXIMAGE1DPROC glad_glCompressedTexImage1D = NULL; +PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL; +PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL; +PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC glad_glCompressedTextureImage1DEXT = NULL; +PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC glad_glCompressedTextureImage2DEXT = NULL; +PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC glad_glCompressedTextureImage3DEXT = NULL; +PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glad_glCompressedTextureSubImage1D = NULL; +PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC glad_glCompressedTextureSubImage1DEXT = NULL; +PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glad_glCompressedTextureSubImage2D = NULL; +PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC glad_glCompressedTextureSubImage2DEXT = NULL; +PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glad_glCompressedTextureSubImage3D = NULL; +PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC glad_glCompressedTextureSubImage3DEXT = NULL; +PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL; +PFNGLCOPYIMAGESUBDATAPROC glad_glCopyImageSubData = NULL; +PFNGLCOPYMULTITEXIMAGE1DEXTPROC glad_glCopyMultiTexImage1DEXT = NULL; +PFNGLCOPYMULTITEXIMAGE2DEXTPROC glad_glCopyMultiTexImage2DEXT = NULL; +PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC glad_glCopyMultiTexSubImage1DEXT = NULL; +PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC glad_glCopyMultiTexSubImage2DEXT = NULL; +PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC glad_glCopyMultiTexSubImage3DEXT = NULL; +PFNGLCOPYNAMEDBUFFERSUBDATAPROC glad_glCopyNamedBufferSubData = NULL; +PFNGLCOPYPIXELSPROC glad_glCopyPixels = NULL; +PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL; +PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL; +PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL; +PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL; +PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL; +PFNGLCOPYTEXTUREIMAGE1DEXTPROC glad_glCopyTextureImage1DEXT = NULL; +PFNGLCOPYTEXTUREIMAGE2DEXTPROC glad_glCopyTextureImage2DEXT = NULL; +PFNGLCOPYTEXTURESUBIMAGE1DPROC glad_glCopyTextureSubImage1D = NULL; +PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC glad_glCopyTextureSubImage1DEXT = NULL; +PFNGLCOPYTEXTURESUBIMAGE2DPROC glad_glCopyTextureSubImage2D = NULL; +PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC glad_glCopyTextureSubImage2DEXT = NULL; +PFNGLCOPYTEXTURESUBIMAGE3DPROC glad_glCopyTextureSubImage3D = NULL; +PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC glad_glCopyTextureSubImage3DEXT = NULL; +PFNGLCREATEBUFFERSPROC glad_glCreateBuffers = NULL; +PFNGLCREATEFRAMEBUFFERSPROC glad_glCreateFramebuffers = NULL; +PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL; +PFNGLCREATEPROGRAMOBJECTARBPROC glad_glCreateProgramObjectARB = NULL; +PFNGLCREATEPROGRAMPIPELINESPROC glad_glCreateProgramPipelines = NULL; +PFNGLCREATEQUERIESPROC glad_glCreateQueries = NULL; +PFNGLCREATERENDERBUFFERSPROC glad_glCreateRenderbuffers = NULL; +PFNGLCREATESAMPLERSPROC glad_glCreateSamplers = NULL; +PFNGLCREATESHADERPROC glad_glCreateShader = NULL; +PFNGLCREATESHADEROBJECTARBPROC glad_glCreateShaderObjectARB = NULL; +PFNGLCREATESHADERPROGRAMVPROC glad_glCreateShaderProgramv = NULL; +PFNGLCREATETEXTURESPROC glad_glCreateTextures = NULL; +PFNGLCREATETRANSFORMFEEDBACKSPROC glad_glCreateTransformFeedbacks = NULL; +PFNGLCREATEVERTEXARRAYSPROC glad_glCreateVertexArrays = NULL; +PFNGLCULLFACEPROC glad_glCullFace = NULL; +PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback = NULL; +PFNGLDEBUGMESSAGECALLBACKARBPROC glad_glDebugMessageCallbackARB = NULL; +PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl = NULL; +PFNGLDEBUGMESSAGECONTROLARBPROC glad_glDebugMessageControlARB = NULL; +PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert = NULL; +PFNGLDEBUGMESSAGEINSERTARBPROC glad_glDebugMessageInsertARB = NULL; +PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL; +PFNGLDELETEBUFFERSARBPROC glad_glDeleteBuffersARB = NULL; +PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL; +PFNGLDELETEFRAMEBUFFERSEXTPROC glad_glDeleteFramebuffersEXT = NULL; +PFNGLDELETELISTSPROC glad_glDeleteLists = NULL; +PFNGLDELETEOBJECTARBPROC glad_glDeleteObjectARB = NULL; +PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL; +PFNGLDELETEPROGRAMPIPELINESPROC glad_glDeleteProgramPipelines = NULL; +PFNGLDELETEPROGRAMSARBPROC glad_glDeleteProgramsARB = NULL; +PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL; +PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL; +PFNGLDELETERENDERBUFFERSEXTPROC glad_glDeleteRenderbuffersEXT = NULL; +PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL; +PFNGLDELETESHADERPROC glad_glDeleteShader = NULL; +PFNGLDELETESYNCPROC glad_glDeleteSync = NULL; +PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL; +PFNGLDELETETRANSFORMFEEDBACKSPROC glad_glDeleteTransformFeedbacks = NULL; +PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL; +PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL; +PFNGLDEPTHMASKPROC glad_glDepthMask = NULL; +PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL; +PFNGLDEPTHRANGEARRAYVPROC glad_glDepthRangeArrayv = NULL; +PFNGLDEPTHRANGEINDEXEDPROC glad_glDepthRangeIndexed = NULL; +PFNGLDEPTHRANGEFPROC glad_glDepthRangef = NULL; +PFNGLDETACHOBJECTARBPROC glad_glDetachObjectARB = NULL; +PFNGLDETACHSHADERPROC glad_glDetachShader = NULL; +PFNGLDISABLEPROC glad_glDisable = NULL; +PFNGLDISABLECLIENTSTATEPROC glad_glDisableClientState = NULL; +PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC glad_glDisableClientStateIndexedEXT = NULL; +PFNGLDISABLECLIENTSTATEIEXTPROC glad_glDisableClientStateiEXT = NULL; +PFNGLDISABLEINDEXEDEXTPROC glad_glDisableIndexedEXT = NULL; +PFNGLDISABLEVERTEXARRAYATTRIBPROC glad_glDisableVertexArrayAttrib = NULL; +PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC glad_glDisableVertexArrayAttribEXT = NULL; +PFNGLDISABLEVERTEXARRAYEXTPROC glad_glDisableVertexArrayEXT = NULL; +PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL; +PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glad_glDisableVertexAttribArrayARB = NULL; +PFNGLDISABLEIPROC glad_glDisablei = NULL; +PFNGLDISPATCHCOMPUTEPROC glad_glDispatchCompute = NULL; +PFNGLDISPATCHCOMPUTEINDIRECTPROC glad_glDispatchComputeIndirect = NULL; +PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL; +PFNGLDRAWARRAYSINDIRECTPROC glad_glDrawArraysIndirect = NULL; +PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL; +PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC glad_glDrawArraysInstancedBaseInstance = NULL; +PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL; +PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL; +PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL; +PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL; +PFNGLDRAWELEMENTSINDIRECTPROC glad_glDrawElementsIndirect = NULL; +PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL; +PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC glad_glDrawElementsInstancedBaseInstance = NULL; +PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL; +PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC glad_glDrawElementsInstancedBaseVertexBaseInstance = NULL; +PFNGLDRAWPIXELSPROC glad_glDrawPixels = NULL; +PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL; +PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL; +PFNGLDRAWTRANSFORMFEEDBACKPROC glad_glDrawTransformFeedback = NULL; +PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC glad_glDrawTransformFeedbackInstanced = NULL; +PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC glad_glDrawTransformFeedbackStream = NULL; +PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC glad_glDrawTransformFeedbackStreamInstanced = NULL; +PFNGLEDGEFLAGPROC glad_glEdgeFlag = NULL; +PFNGLEDGEFLAGPOINTERPROC glad_glEdgeFlagPointer = NULL; +PFNGLEDGEFLAGVPROC glad_glEdgeFlagv = NULL; +PFNGLENABLEPROC glad_glEnable = NULL; +PFNGLENABLECLIENTSTATEPROC glad_glEnableClientState = NULL; +PFNGLENABLECLIENTSTATEINDEXEDEXTPROC glad_glEnableClientStateIndexedEXT = NULL; +PFNGLENABLECLIENTSTATEIEXTPROC glad_glEnableClientStateiEXT = NULL; +PFNGLENABLEINDEXEDEXTPROC glad_glEnableIndexedEXT = NULL; +PFNGLENABLEVERTEXARRAYATTRIBPROC glad_glEnableVertexArrayAttrib = NULL; +PFNGLENABLEVERTEXARRAYATTRIBEXTPROC glad_glEnableVertexArrayAttribEXT = NULL; +PFNGLENABLEVERTEXARRAYEXTPROC glad_glEnableVertexArrayEXT = NULL; +PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL; +PFNGLENABLEVERTEXATTRIBARRAYARBPROC glad_glEnableVertexAttribArrayARB = NULL; +PFNGLENABLEIPROC glad_glEnablei = NULL; +PFNGLENDPROC glad_glEnd = NULL; +PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL; +PFNGLENDLISTPROC glad_glEndList = NULL; +PFNGLENDQUERYPROC glad_glEndQuery = NULL; +PFNGLENDQUERYINDEXEDPROC glad_glEndQueryIndexed = NULL; +PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL; +PFNGLENDTRANSFORMFEEDBACKEXTPROC glad_glEndTransformFeedbackEXT = NULL; +PFNGLEVALCOORD1DPROC glad_glEvalCoord1d = NULL; +PFNGLEVALCOORD1DVPROC glad_glEvalCoord1dv = NULL; +PFNGLEVALCOORD1FPROC glad_glEvalCoord1f = NULL; +PFNGLEVALCOORD1FVPROC glad_glEvalCoord1fv = NULL; +PFNGLEVALCOORD2DPROC glad_glEvalCoord2d = NULL; +PFNGLEVALCOORD2DVPROC glad_glEvalCoord2dv = NULL; +PFNGLEVALCOORD2FPROC glad_glEvalCoord2f = NULL; +PFNGLEVALCOORD2FVPROC glad_glEvalCoord2fv = NULL; +PFNGLEVALMESH1PROC glad_glEvalMesh1 = NULL; +PFNGLEVALMESH2PROC glad_glEvalMesh2 = NULL; +PFNGLEVALPOINT1PROC glad_glEvalPoint1 = NULL; +PFNGLEVALPOINT2PROC glad_glEvalPoint2 = NULL; +PFNGLFEEDBACKBUFFERPROC glad_glFeedbackBuffer = NULL; +PFNGLFENCESYNCPROC glad_glFenceSync = NULL; +PFNGLFINISHPROC glad_glFinish = NULL; +PFNGLFLUSHPROC glad_glFlush = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL; +PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glad_glFlushMappedNamedBufferRange = NULL; +PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC glad_glFlushMappedNamedBufferRangeEXT = NULL; +PFNGLFOGCOORDPOINTERPROC glad_glFogCoordPointer = NULL; +PFNGLFOGCOORDDPROC glad_glFogCoordd = NULL; +PFNGLFOGCOORDDVPROC glad_glFogCoorddv = NULL; +PFNGLFOGCOORDFPROC glad_glFogCoordf = NULL; +PFNGLFOGCOORDFVPROC glad_glFogCoordfv = NULL; +PFNGLFOGFPROC glad_glFogf = NULL; +PFNGLFOGFVPROC glad_glFogfv = NULL; +PFNGLFOGIPROC glad_glFogi = NULL; +PFNGLFOGIVPROC glad_glFogiv = NULL; +PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC glad_glFramebufferDrawBufferEXT = NULL; +PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC glad_glFramebufferDrawBuffersEXT = NULL; +PFNGLFRAMEBUFFERPARAMETERIPROC glad_glFramebufferParameteri = NULL; +PFNGLFRAMEBUFFERREADBUFFEREXTPROC glad_glFramebufferReadBufferEXT = NULL; +PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL; +PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glad_glFramebufferRenderbufferEXT = NULL; +PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL; +PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL; +PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glad_glFramebufferTexture1DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL; +PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glad_glFramebufferTexture2DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL; +PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glad_glFramebufferTexture3DEXT = NULL; +PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL; +PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glad_glFramebufferTextureLayerEXT = NULL; +PFNGLFRONTFACEPROC glad_glFrontFace = NULL; +PFNGLFRUSTUMPROC glad_glFrustum = NULL; +PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL; +PFNGLGENBUFFERSARBPROC glad_glGenBuffersARB = NULL; +PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL; +PFNGLGENFRAMEBUFFERSEXTPROC glad_glGenFramebuffersEXT = NULL; +PFNGLGENLISTSPROC glad_glGenLists = NULL; +PFNGLGENPROGRAMPIPELINESPROC glad_glGenProgramPipelines = NULL; +PFNGLGENPROGRAMSARBPROC glad_glGenProgramsARB = NULL; +PFNGLGENQUERIESPROC glad_glGenQueries = NULL; +PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL; +PFNGLGENRENDERBUFFERSEXTPROC glad_glGenRenderbuffersEXT = NULL; +PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL; +PFNGLGENTEXTURESPROC glad_glGenTextures = NULL; +PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks = NULL; +PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL; +PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL; +PFNGLGENERATEMIPMAPEXTPROC glad_glGenerateMipmapEXT = NULL; +PFNGLGENERATEMULTITEXMIPMAPEXTPROC glad_glGenerateMultiTexMipmapEXT = NULL; +PFNGLGENERATETEXTUREMIPMAPPROC glad_glGenerateTextureMipmap = NULL; +PFNGLGENERATETEXTUREMIPMAPEXTPROC glad_glGenerateTextureMipmapEXT = NULL; +PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC glad_glGetActiveAtomicCounterBufferiv = NULL; +PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL; +PFNGLGETACTIVEATTRIBARBPROC glad_glGetActiveAttribARB = NULL; +PFNGLGETACTIVESUBROUTINENAMEPROC glad_glGetActiveSubroutineName = NULL; +PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC glad_glGetActiveSubroutineUniformName = NULL; +PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC glad_glGetActiveSubroutineUniformiv = NULL; +PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL; +PFNGLGETACTIVEUNIFORMARBPROC glad_glGetActiveUniformARB = NULL; +PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL; +PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL; +PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL; +PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL; +PFNGLGETATTACHEDOBJECTSARBPROC glad_glGetAttachedObjectsARB = NULL; +PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL; +PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL; +PFNGLGETATTRIBLOCATIONARBPROC glad_glGetAttribLocationARB = NULL; +PFNGLGETBOOLEANINDEXEDVEXTPROC glad_glGetBooleanIndexedvEXT = NULL; +PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL; +PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL; +PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL; +PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL; +PFNGLGETBUFFERPARAMETERIVARBPROC glad_glGetBufferParameterivARB = NULL; +PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL; +PFNGLGETBUFFERPOINTERVARBPROC glad_glGetBufferPointervARB = NULL; +PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL; +PFNGLGETBUFFERSUBDATAARBPROC glad_glGetBufferSubDataARB = NULL; +PFNGLGETCLIPPLANEPROC glad_glGetClipPlane = NULL; +PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC glad_glGetCompressedMultiTexImageEXT = NULL; +PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL; +PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glad_glGetCompressedTextureImage = NULL; +PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC glad_glGetCompressedTextureImageEXT = NULL; +PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glad_glGetCompressedTextureSubImage = NULL; +PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog = NULL; +PFNGLGETDEBUGMESSAGELOGARBPROC glad_glGetDebugMessageLogARB = NULL; +PFNGLGETDOUBLEINDEXEDVEXTPROC glad_glGetDoubleIndexedvEXT = NULL; +PFNGLGETDOUBLEI_VPROC glad_glGetDoublei_v = NULL; +PFNGLGETDOUBLEI_VEXTPROC glad_glGetDoublei_vEXT = NULL; +PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL; +PFNGLGETERRORPROC glad_glGetError = NULL; +PFNGLGETFLOATINDEXEDVEXTPROC glad_glGetFloatIndexedvEXT = NULL; +PFNGLGETFLOATI_VPROC glad_glGetFloati_v = NULL; +PFNGLGETFLOATI_VEXTPROC glad_glGetFloati_vEXT = NULL; +PFNGLGETFLOATVPROC glad_glGetFloatv = NULL; +PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL; +PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL; +PFNGLGETFRAGDATALOCATIONEXTPROC glad_glGetFragDataLocationEXT = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetFramebufferAttachmentParameterivEXT = NULL; +PFNGLGETFRAMEBUFFERPARAMETERIVPROC glad_glGetFramebufferParameteriv = NULL; +PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC glad_glGetFramebufferParameterivEXT = NULL; +PFNGLGETGRAPHICSRESETSTATUSPROC glad_glGetGraphicsResetStatus = NULL; +PFNGLGETHANDLEARBPROC glad_glGetHandleARB = NULL; +PFNGLGETINFOLOGARBPROC glad_glGetInfoLogARB = NULL; +PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL; +PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL; +PFNGLGETINTEGERINDEXEDVEXTPROC glad_glGetIntegerIndexedvEXT = NULL; +PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL; +PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL; +PFNGLGETINTERNALFORMATI64VPROC glad_glGetInternalformati64v = NULL; +PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ = NULL; +PFNGLGETLIGHTFVPROC glad_glGetLightfv = NULL; +PFNGLGETLIGHTIVPROC glad_glGetLightiv = NULL; +PFNGLGETMAPDVPROC glad_glGetMapdv = NULL; +PFNGLGETMAPFVPROC glad_glGetMapfv = NULL; +PFNGLGETMAPIVPROC glad_glGetMapiv = NULL; +PFNGLGETMATERIALFVPROC glad_glGetMaterialfv = NULL; +PFNGLGETMATERIALIVPROC glad_glGetMaterialiv = NULL; +PFNGLGETMULTITEXENVFVEXTPROC glad_glGetMultiTexEnvfvEXT = NULL; +PFNGLGETMULTITEXENVIVEXTPROC glad_glGetMultiTexEnvivEXT = NULL; +PFNGLGETMULTITEXGENDVEXTPROC glad_glGetMultiTexGendvEXT = NULL; +PFNGLGETMULTITEXGENFVEXTPROC glad_glGetMultiTexGenfvEXT = NULL; +PFNGLGETMULTITEXGENIVEXTPROC glad_glGetMultiTexGenivEXT = NULL; +PFNGLGETMULTITEXIMAGEEXTPROC glad_glGetMultiTexImageEXT = NULL; +PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC glad_glGetMultiTexLevelParameterfvEXT = NULL; +PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC glad_glGetMultiTexLevelParameterivEXT = NULL; +PFNGLGETMULTITEXPARAMETERIIVEXTPROC glad_glGetMultiTexParameterIivEXT = NULL; +PFNGLGETMULTITEXPARAMETERIUIVEXTPROC glad_glGetMultiTexParameterIuivEXT = NULL; +PFNGLGETMULTITEXPARAMETERFVEXTPROC glad_glGetMultiTexParameterfvEXT = NULL; +PFNGLGETMULTITEXPARAMETERIVEXTPROC glad_glGetMultiTexParameterivEXT = NULL; +PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL; +PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glad_glGetNamedBufferParameteri64v = NULL; +PFNGLGETNAMEDBUFFERPARAMETERIVPROC glad_glGetNamedBufferParameteriv = NULL; +PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC glad_glGetNamedBufferParameterivEXT = NULL; +PFNGLGETNAMEDBUFFERPOINTERVPROC glad_glGetNamedBufferPointerv = NULL; +PFNGLGETNAMEDBUFFERPOINTERVEXTPROC glad_glGetNamedBufferPointervEXT = NULL; +PFNGLGETNAMEDBUFFERSUBDATAPROC glad_glGetNamedBufferSubData = NULL; +PFNGLGETNAMEDBUFFERSUBDATAEXTPROC glad_glGetNamedBufferSubDataEXT = NULL; +PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetNamedFramebufferAttachmentParameteriv = NULL; +PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glad_glGetNamedFramebufferAttachmentParameterivEXT = NULL; +PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glad_glGetNamedFramebufferParameteriv = NULL; +PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC glad_glGetNamedFramebufferParameterivEXT = NULL; +PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC glad_glGetNamedProgramLocalParameterIivEXT = NULL; +PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC glad_glGetNamedProgramLocalParameterIuivEXT = NULL; +PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC glad_glGetNamedProgramLocalParameterdvEXT = NULL; +PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC glad_glGetNamedProgramLocalParameterfvEXT = NULL; +PFNGLGETNAMEDPROGRAMSTRINGEXTPROC glad_glGetNamedProgramStringEXT = NULL; +PFNGLGETNAMEDPROGRAMIVEXTPROC glad_glGetNamedProgramivEXT = NULL; +PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glad_glGetNamedRenderbufferParameteriv = NULL; +PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC glad_glGetNamedRenderbufferParameterivEXT = NULL; +PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel = NULL; +PFNGLGETOBJECTPARAMETERFVARBPROC glad_glGetObjectParameterfvARB = NULL; +PFNGLGETOBJECTPARAMETERIVARBPROC glad_glGetObjectParameterivARB = NULL; +PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel = NULL; +PFNGLGETPIXELMAPFVPROC glad_glGetPixelMapfv = NULL; +PFNGLGETPIXELMAPUIVPROC glad_glGetPixelMapuiv = NULL; +PFNGLGETPIXELMAPUSVPROC glad_glGetPixelMapusv = NULL; +PFNGLGETPOINTERINDEXEDVEXTPROC glad_glGetPointerIndexedvEXT = NULL; +PFNGLGETPOINTERI_VEXTPROC glad_glGetPointeri_vEXT = NULL; +PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL; +PFNGLGETPOLYGONSTIPPLEPROC glad_glGetPolygonStipple = NULL; +PFNGLGETPROGRAMBINARYPROC glad_glGetProgramBinary = NULL; +PFNGLGETPROGRAMENVPARAMETERDVARBPROC glad_glGetProgramEnvParameterdvARB = NULL; +PFNGLGETPROGRAMENVPARAMETERFVARBPROC glad_glGetProgramEnvParameterfvARB = NULL; +PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL; +PFNGLGETPROGRAMINTERFACEIVPROC glad_glGetProgramInterfaceiv = NULL; +PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glad_glGetProgramLocalParameterdvARB = NULL; +PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glad_glGetProgramLocalParameterfvARB = NULL; +PFNGLGETPROGRAMPIPELINEINFOLOGPROC glad_glGetProgramPipelineInfoLog = NULL; +PFNGLGETPROGRAMPIPELINEIVPROC glad_glGetProgramPipelineiv = NULL; +PFNGLGETPROGRAMRESOURCEINDEXPROC glad_glGetProgramResourceIndex = NULL; +PFNGLGETPROGRAMRESOURCELOCATIONPROC glad_glGetProgramResourceLocation = NULL; +PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC glad_glGetProgramResourceLocationIndex = NULL; +PFNGLGETPROGRAMRESOURCENAMEPROC glad_glGetProgramResourceName = NULL; +PFNGLGETPROGRAMRESOURCEIVPROC glad_glGetProgramResourceiv = NULL; +PFNGLGETPROGRAMSTAGEIVPROC glad_glGetProgramStageiv = NULL; +PFNGLGETPROGRAMSTRINGARBPROC glad_glGetProgramStringARB = NULL; +PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL; +PFNGLGETPROGRAMIVARBPROC glad_glGetProgramivARB = NULL; +PFNGLGETQUERYBUFFEROBJECTI64VPROC glad_glGetQueryBufferObjecti64v = NULL; +PFNGLGETQUERYBUFFEROBJECTIVPROC glad_glGetQueryBufferObjectiv = NULL; +PFNGLGETQUERYBUFFEROBJECTUI64VPROC glad_glGetQueryBufferObjectui64v = NULL; +PFNGLGETQUERYBUFFEROBJECTUIVPROC glad_glGetQueryBufferObjectuiv = NULL; +PFNGLGETQUERYINDEXEDIVPROC glad_glGetQueryIndexediv = NULL; +PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL; +PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL; +PFNGLGETQUERYOBJECTUI64VPROC glad_glGetQueryObjectui64v = NULL; +PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL; +PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glad_glGetRenderbufferParameterivEXT = NULL; +PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL; +PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL; +PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL; +PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL; +PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL; +PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat = NULL; +PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL; +PFNGLGETSHADERSOURCEARBPROC glad_glGetShaderSourceARB = NULL; +PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL; +PFNGLGETSTRINGPROC glad_glGetString = NULL; +PFNGLGETSTRINGIPROC glad_glGetStringi = NULL; +PFNGLGETSUBROUTINEINDEXPROC glad_glGetSubroutineIndex = NULL; +PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC glad_glGetSubroutineUniformLocation = NULL; +PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL; +PFNGLGETTEXENVFVPROC glad_glGetTexEnvfv = NULL; +PFNGLGETTEXENVIVPROC glad_glGetTexEnviv = NULL; +PFNGLGETTEXGENDVPROC glad_glGetTexGendv = NULL; +PFNGLGETTEXGENFVPROC glad_glGetTexGenfv = NULL; +PFNGLGETTEXGENIVPROC glad_glGetTexGeniv = NULL; +PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL; +PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL; +PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL; +PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL; +PFNGLGETTEXPARAMETERIIVEXTPROC glad_glGetTexParameterIivEXT = NULL; +PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL; +PFNGLGETTEXPARAMETERIUIVEXTPROC glad_glGetTexParameterIuivEXT = NULL; +PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL; +PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL; +PFNGLGETTEXTUREIMAGEPROC glad_glGetTextureImage = NULL; +PFNGLGETTEXTUREIMAGEEXTPROC glad_glGetTextureImageEXT = NULL; +PFNGLGETTEXTURELEVELPARAMETERFVPROC glad_glGetTextureLevelParameterfv = NULL; +PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC glad_glGetTextureLevelParameterfvEXT = NULL; +PFNGLGETTEXTURELEVELPARAMETERIVPROC glad_glGetTextureLevelParameteriv = NULL; +PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC glad_glGetTextureLevelParameterivEXT = NULL; +PFNGLGETTEXTUREPARAMETERIIVPROC glad_glGetTextureParameterIiv = NULL; +PFNGLGETTEXTUREPARAMETERIIVEXTPROC glad_glGetTextureParameterIivEXT = NULL; +PFNGLGETTEXTUREPARAMETERIUIVPROC glad_glGetTextureParameterIuiv = NULL; +PFNGLGETTEXTUREPARAMETERIUIVEXTPROC glad_glGetTextureParameterIuivEXT = NULL; +PFNGLGETTEXTUREPARAMETERFVPROC glad_glGetTextureParameterfv = NULL; +PFNGLGETTEXTUREPARAMETERFVEXTPROC glad_glGetTextureParameterfvEXT = NULL; +PFNGLGETTEXTUREPARAMETERIVPROC glad_glGetTextureParameteriv = NULL; +PFNGLGETTEXTUREPARAMETERIVEXTPROC glad_glGetTextureParameterivEXT = NULL; +PFNGLGETTEXTURESUBIMAGEPROC glad_glGetTextureSubImage = NULL; +PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL; +PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC glad_glGetTransformFeedbackVaryingEXT = NULL; +PFNGLGETTRANSFORMFEEDBACKI64_VPROC glad_glGetTransformFeedbacki64_v = NULL; +PFNGLGETTRANSFORMFEEDBACKI_VPROC glad_glGetTransformFeedbacki_v = NULL; +PFNGLGETTRANSFORMFEEDBACKIVPROC glad_glGetTransformFeedbackiv = NULL; +PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL; +PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL; +PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL; +PFNGLGETUNIFORMLOCATIONARBPROC glad_glGetUniformLocationARB = NULL; +PFNGLGETUNIFORMSUBROUTINEUIVPROC glad_glGetUniformSubroutineuiv = NULL; +PFNGLGETUNIFORMDVPROC glad_glGetUniformdv = NULL; +PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL; +PFNGLGETUNIFORMFVARBPROC glad_glGetUniformfvARB = NULL; +PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL; +PFNGLGETUNIFORMIVARBPROC glad_glGetUniformivARB = NULL; +PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL; +PFNGLGETUNIFORMUIVEXTPROC glad_glGetUniformuivEXT = NULL; +PFNGLGETVERTEXARRAYINDEXED64IVPROC glad_glGetVertexArrayIndexed64iv = NULL; +PFNGLGETVERTEXARRAYINDEXEDIVPROC glad_glGetVertexArrayIndexediv = NULL; +PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC glad_glGetVertexArrayIntegeri_vEXT = NULL; +PFNGLGETVERTEXARRAYINTEGERVEXTPROC glad_glGetVertexArrayIntegervEXT = NULL; +PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC glad_glGetVertexArrayPointeri_vEXT = NULL; +PFNGLGETVERTEXARRAYPOINTERVEXTPROC glad_glGetVertexArrayPointervEXT = NULL; +PFNGLGETVERTEXARRAYIVPROC glad_glGetVertexArrayiv = NULL; +PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL; +PFNGLGETVERTEXATTRIBIIVEXTPROC glad_glGetVertexAttribIivEXT = NULL; +PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL; +PFNGLGETVERTEXATTRIBIUIVEXTPROC glad_glGetVertexAttribIuivEXT = NULL; +PFNGLGETVERTEXATTRIBLDVPROC glad_glGetVertexAttribLdv = NULL; +PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL; +PFNGLGETVERTEXATTRIBPOINTERVARBPROC glad_glGetVertexAttribPointervARB = NULL; +PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL; +PFNGLGETVERTEXATTRIBDVARBPROC glad_glGetVertexAttribdvARB = NULL; +PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL; +PFNGLGETVERTEXATTRIBFVARBPROC glad_glGetVertexAttribfvARB = NULL; +PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL; +PFNGLGETVERTEXATTRIBIVARBPROC glad_glGetVertexAttribivARB = NULL; +PFNGLGETNCOLORTABLEPROC glad_glGetnColorTable = NULL; +PFNGLGETNCOMPRESSEDTEXIMAGEPROC glad_glGetnCompressedTexImage = NULL; +PFNGLGETNCONVOLUTIONFILTERPROC glad_glGetnConvolutionFilter = NULL; +PFNGLGETNHISTOGRAMPROC glad_glGetnHistogram = NULL; +PFNGLGETNMAPDVPROC glad_glGetnMapdv = NULL; +PFNGLGETNMAPFVPROC glad_glGetnMapfv = NULL; +PFNGLGETNMAPIVPROC glad_glGetnMapiv = NULL; +PFNGLGETNMINMAXPROC glad_glGetnMinmax = NULL; +PFNGLGETNPIXELMAPFVPROC glad_glGetnPixelMapfv = NULL; +PFNGLGETNPIXELMAPUIVPROC glad_glGetnPixelMapuiv = NULL; +PFNGLGETNPIXELMAPUSVPROC glad_glGetnPixelMapusv = NULL; +PFNGLGETNPOLYGONSTIPPLEPROC glad_glGetnPolygonStipple = NULL; +PFNGLGETNSEPARABLEFILTERPROC glad_glGetnSeparableFilter = NULL; +PFNGLGETNTEXIMAGEPROC glad_glGetnTexImage = NULL; +PFNGLGETNUNIFORMDVPROC glad_glGetnUniformdv = NULL; +PFNGLGETNUNIFORMFVPROC glad_glGetnUniformfv = NULL; +PFNGLGETNUNIFORMIVPROC glad_glGetnUniformiv = NULL; +PFNGLGETNUNIFORMUIVPROC glad_glGetnUniformuiv = NULL; +PFNGLHINTPROC glad_glHint = NULL; +PFNGLINDEXMASKPROC glad_glIndexMask = NULL; +PFNGLINDEXPOINTERPROC glad_glIndexPointer = NULL; +PFNGLINDEXDPROC glad_glIndexd = NULL; +PFNGLINDEXDVPROC glad_glIndexdv = NULL; +PFNGLINDEXFPROC glad_glIndexf = NULL; +PFNGLINDEXFVPROC glad_glIndexfv = NULL; +PFNGLINDEXIPROC glad_glIndexi = NULL; +PFNGLINDEXIVPROC glad_glIndexiv = NULL; +PFNGLINDEXSPROC glad_glIndexs = NULL; +PFNGLINDEXSVPROC glad_glIndexsv = NULL; +PFNGLINDEXUBPROC glad_glIndexub = NULL; +PFNGLINDEXUBVPROC glad_glIndexubv = NULL; +PFNGLINITNAMESPROC glad_glInitNames = NULL; +PFNGLINTERLEAVEDARRAYSPROC glad_glInterleavedArrays = NULL; +PFNGLINVALIDATEBUFFERDATAPROC glad_glInvalidateBufferData = NULL; +PFNGLINVALIDATEBUFFERSUBDATAPROC glad_glInvalidateBufferSubData = NULL; +PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer = NULL; +PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glad_glInvalidateNamedFramebufferData = NULL; +PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glad_glInvalidateNamedFramebufferSubData = NULL; +PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer = NULL; +PFNGLINVALIDATETEXIMAGEPROC glad_glInvalidateTexImage = NULL; +PFNGLINVALIDATETEXSUBIMAGEPROC glad_glInvalidateTexSubImage = NULL; +PFNGLISBUFFERPROC glad_glIsBuffer = NULL; +PFNGLISBUFFERARBPROC glad_glIsBufferARB = NULL; +PFNGLISENABLEDPROC glad_glIsEnabled = NULL; +PFNGLISENABLEDINDEXEDEXTPROC glad_glIsEnabledIndexedEXT = NULL; +PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL; +PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL; +PFNGLISFRAMEBUFFEREXTPROC glad_glIsFramebufferEXT = NULL; +PFNGLISLISTPROC glad_glIsList = NULL; +PFNGLISPROGRAMPROC glad_glIsProgram = NULL; +PFNGLISPROGRAMARBPROC glad_glIsProgramARB = NULL; +PFNGLISPROGRAMPIPELINEPROC glad_glIsProgramPipeline = NULL; +PFNGLISQUERYPROC glad_glIsQuery = NULL; +PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL; +PFNGLISRENDERBUFFEREXTPROC glad_glIsRenderbufferEXT = NULL; +PFNGLISSAMPLERPROC glad_glIsSampler = NULL; +PFNGLISSHADERPROC glad_glIsShader = NULL; +PFNGLISSYNCPROC glad_glIsSync = NULL; +PFNGLISTEXTUREPROC glad_glIsTexture = NULL; +PFNGLISTRANSFORMFEEDBACKPROC glad_glIsTransformFeedback = NULL; +PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL; +PFNGLLIGHTMODELFPROC glad_glLightModelf = NULL; +PFNGLLIGHTMODELFVPROC glad_glLightModelfv = NULL; +PFNGLLIGHTMODELIPROC glad_glLightModeli = NULL; +PFNGLLIGHTMODELIVPROC glad_glLightModeliv = NULL; +PFNGLLIGHTFPROC glad_glLightf = NULL; +PFNGLLIGHTFVPROC glad_glLightfv = NULL; +PFNGLLIGHTIPROC glad_glLighti = NULL; +PFNGLLIGHTIVPROC glad_glLightiv = NULL; +PFNGLLINESTIPPLEPROC glad_glLineStipple = NULL; +PFNGLLINEWIDTHPROC glad_glLineWidth = NULL; +PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL; +PFNGLLINKPROGRAMARBPROC glad_glLinkProgramARB = NULL; +PFNGLLISTBASEPROC glad_glListBase = NULL; +PFNGLLOADIDENTITYPROC glad_glLoadIdentity = NULL; +PFNGLLOADMATRIXDPROC glad_glLoadMatrixd = NULL; +PFNGLLOADMATRIXFPROC glad_glLoadMatrixf = NULL; +PFNGLLOADNAMEPROC glad_glLoadName = NULL; +PFNGLLOADTRANSPOSEMATRIXDPROC glad_glLoadTransposeMatrixd = NULL; +PFNGLLOADTRANSPOSEMATRIXFPROC glad_glLoadTransposeMatrixf = NULL; +PFNGLLOGICOPPROC glad_glLogicOp = NULL; +PFNGLMAP1DPROC glad_glMap1d = NULL; +PFNGLMAP1FPROC glad_glMap1f = NULL; +PFNGLMAP2DPROC glad_glMap2d = NULL; +PFNGLMAP2FPROC glad_glMap2f = NULL; +PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL; +PFNGLMAPBUFFERARBPROC glad_glMapBufferARB = NULL; +PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL; +PFNGLMAPGRID1DPROC glad_glMapGrid1d = NULL; +PFNGLMAPGRID1FPROC glad_glMapGrid1f = NULL; +PFNGLMAPGRID2DPROC glad_glMapGrid2d = NULL; +PFNGLMAPGRID2FPROC glad_glMapGrid2f = NULL; +PFNGLMAPNAMEDBUFFERPROC glad_glMapNamedBuffer = NULL; +PFNGLMAPNAMEDBUFFEREXTPROC glad_glMapNamedBufferEXT = NULL; +PFNGLMAPNAMEDBUFFERRANGEPROC glad_glMapNamedBufferRange = NULL; +PFNGLMAPNAMEDBUFFERRANGEEXTPROC glad_glMapNamedBufferRangeEXT = NULL; +PFNGLMATERIALFPROC glad_glMaterialf = NULL; +PFNGLMATERIALFVPROC glad_glMaterialfv = NULL; +PFNGLMATERIALIPROC glad_glMateriali = NULL; +PFNGLMATERIALIVPROC glad_glMaterialiv = NULL; +PFNGLMATRIXFRUSTUMEXTPROC glad_glMatrixFrustumEXT = NULL; +PFNGLMATRIXLOADIDENTITYEXTPROC glad_glMatrixLoadIdentityEXT = NULL; +PFNGLMATRIXLOADTRANSPOSEDEXTPROC glad_glMatrixLoadTransposedEXT = NULL; +PFNGLMATRIXLOADTRANSPOSEFEXTPROC glad_glMatrixLoadTransposefEXT = NULL; +PFNGLMATRIXLOADDEXTPROC glad_glMatrixLoaddEXT = NULL; +PFNGLMATRIXLOADFEXTPROC glad_glMatrixLoadfEXT = NULL; +PFNGLMATRIXMODEPROC glad_glMatrixMode = NULL; +PFNGLMATRIXMULTTRANSPOSEDEXTPROC glad_glMatrixMultTransposedEXT = NULL; +PFNGLMATRIXMULTTRANSPOSEFEXTPROC glad_glMatrixMultTransposefEXT = NULL; +PFNGLMATRIXMULTDEXTPROC glad_glMatrixMultdEXT = NULL; +PFNGLMATRIXMULTFEXTPROC glad_glMatrixMultfEXT = NULL; +PFNGLMATRIXORTHOEXTPROC glad_glMatrixOrthoEXT = NULL; +PFNGLMATRIXPOPEXTPROC glad_glMatrixPopEXT = NULL; +PFNGLMATRIXPUSHEXTPROC glad_glMatrixPushEXT = NULL; +PFNGLMATRIXROTATEDEXTPROC glad_glMatrixRotatedEXT = NULL; +PFNGLMATRIXROTATEFEXTPROC glad_glMatrixRotatefEXT = NULL; +PFNGLMATRIXSCALEDEXTPROC glad_glMatrixScaledEXT = NULL; +PFNGLMATRIXSCALEFEXTPROC glad_glMatrixScalefEXT = NULL; +PFNGLMATRIXTRANSLATEDEXTPROC glad_glMatrixTranslatedEXT = NULL; +PFNGLMATRIXTRANSLATEFEXTPROC glad_glMatrixTranslatefEXT = NULL; +PFNGLMEMORYBARRIERPROC glad_glMemoryBarrier = NULL; +PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion = NULL; +PFNGLMEMORYBARRIEREXTPROC glad_glMemoryBarrierEXT = NULL; +PFNGLMINSAMPLESHADINGPROC glad_glMinSampleShading = NULL; +PFNGLMULTMATRIXDPROC glad_glMultMatrixd = NULL; +PFNGLMULTMATRIXFPROC glad_glMultMatrixf = NULL; +PFNGLMULTTRANSPOSEMATRIXDPROC glad_glMultTransposeMatrixd = NULL; +PFNGLMULTTRANSPOSEMATRIXFPROC glad_glMultTransposeMatrixf = NULL; +PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL; +PFNGLMULTIDRAWARRAYSINDIRECTPROC glad_glMultiDrawArraysIndirect = NULL; +PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC glad_glMultiDrawArraysIndirectCount = NULL; +PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL; +PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL; +PFNGLMULTIDRAWELEMENTSINDIRECTPROC glad_glMultiDrawElementsIndirect = NULL; +PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC glad_glMultiDrawElementsIndirectCount = NULL; +PFNGLMULTITEXBUFFEREXTPROC glad_glMultiTexBufferEXT = NULL; +PFNGLMULTITEXCOORD1DPROC glad_glMultiTexCoord1d = NULL; +PFNGLMULTITEXCOORD1DVPROC glad_glMultiTexCoord1dv = NULL; +PFNGLMULTITEXCOORD1FPROC glad_glMultiTexCoord1f = NULL; +PFNGLMULTITEXCOORD1FVPROC glad_glMultiTexCoord1fv = NULL; +PFNGLMULTITEXCOORD1IPROC glad_glMultiTexCoord1i = NULL; +PFNGLMULTITEXCOORD1IVPROC glad_glMultiTexCoord1iv = NULL; +PFNGLMULTITEXCOORD1SPROC glad_glMultiTexCoord1s = NULL; +PFNGLMULTITEXCOORD1SVPROC glad_glMultiTexCoord1sv = NULL; +PFNGLMULTITEXCOORD2DPROC glad_glMultiTexCoord2d = NULL; +PFNGLMULTITEXCOORD2DVPROC glad_glMultiTexCoord2dv = NULL; +PFNGLMULTITEXCOORD2FPROC glad_glMultiTexCoord2f = NULL; +PFNGLMULTITEXCOORD2FVPROC glad_glMultiTexCoord2fv = NULL; +PFNGLMULTITEXCOORD2IPROC glad_glMultiTexCoord2i = NULL; +PFNGLMULTITEXCOORD2IVPROC glad_glMultiTexCoord2iv = NULL; +PFNGLMULTITEXCOORD2SPROC glad_glMultiTexCoord2s = NULL; +PFNGLMULTITEXCOORD2SVPROC glad_glMultiTexCoord2sv = NULL; +PFNGLMULTITEXCOORD3DPROC glad_glMultiTexCoord3d = NULL; +PFNGLMULTITEXCOORD3DVPROC glad_glMultiTexCoord3dv = NULL; +PFNGLMULTITEXCOORD3FPROC glad_glMultiTexCoord3f = NULL; +PFNGLMULTITEXCOORD3FVPROC glad_glMultiTexCoord3fv = NULL; +PFNGLMULTITEXCOORD3IPROC glad_glMultiTexCoord3i = NULL; +PFNGLMULTITEXCOORD3IVPROC glad_glMultiTexCoord3iv = NULL; +PFNGLMULTITEXCOORD3SPROC glad_glMultiTexCoord3s = NULL; +PFNGLMULTITEXCOORD3SVPROC glad_glMultiTexCoord3sv = NULL; +PFNGLMULTITEXCOORD4DPROC glad_glMultiTexCoord4d = NULL; +PFNGLMULTITEXCOORD4DVPROC glad_glMultiTexCoord4dv = NULL; +PFNGLMULTITEXCOORD4FPROC glad_glMultiTexCoord4f = NULL; +PFNGLMULTITEXCOORD4FVPROC glad_glMultiTexCoord4fv = NULL; +PFNGLMULTITEXCOORD4IPROC glad_glMultiTexCoord4i = NULL; +PFNGLMULTITEXCOORD4IVPROC glad_glMultiTexCoord4iv = NULL; +PFNGLMULTITEXCOORD4SPROC glad_glMultiTexCoord4s = NULL; +PFNGLMULTITEXCOORD4SVPROC glad_glMultiTexCoord4sv = NULL; +PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui = NULL; +PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv = NULL; +PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui = NULL; +PFNGLMULTITEXCOORDP2UIVPROC glad_glMultiTexCoordP2uiv = NULL; +PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL; +PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL; +PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL; +PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL; +PFNGLMULTITEXCOORDPOINTEREXTPROC glad_glMultiTexCoordPointerEXT = NULL; +PFNGLMULTITEXENVFEXTPROC glad_glMultiTexEnvfEXT = NULL; +PFNGLMULTITEXENVFVEXTPROC glad_glMultiTexEnvfvEXT = NULL; +PFNGLMULTITEXENVIEXTPROC glad_glMultiTexEnviEXT = NULL; +PFNGLMULTITEXENVIVEXTPROC glad_glMultiTexEnvivEXT = NULL; +PFNGLMULTITEXGENDEXTPROC glad_glMultiTexGendEXT = NULL; +PFNGLMULTITEXGENDVEXTPROC glad_glMultiTexGendvEXT = NULL; +PFNGLMULTITEXGENFEXTPROC glad_glMultiTexGenfEXT = NULL; +PFNGLMULTITEXGENFVEXTPROC glad_glMultiTexGenfvEXT = NULL; +PFNGLMULTITEXGENIEXTPROC glad_glMultiTexGeniEXT = NULL; +PFNGLMULTITEXGENIVEXTPROC glad_glMultiTexGenivEXT = NULL; +PFNGLMULTITEXIMAGE1DEXTPROC glad_glMultiTexImage1DEXT = NULL; +PFNGLMULTITEXIMAGE2DEXTPROC glad_glMultiTexImage2DEXT = NULL; +PFNGLMULTITEXIMAGE3DEXTPROC glad_glMultiTexImage3DEXT = NULL; +PFNGLMULTITEXPARAMETERIIVEXTPROC glad_glMultiTexParameterIivEXT = NULL; +PFNGLMULTITEXPARAMETERIUIVEXTPROC glad_glMultiTexParameterIuivEXT = NULL; +PFNGLMULTITEXPARAMETERFEXTPROC glad_glMultiTexParameterfEXT = NULL; +PFNGLMULTITEXPARAMETERFVEXTPROC glad_glMultiTexParameterfvEXT = NULL; +PFNGLMULTITEXPARAMETERIEXTPROC glad_glMultiTexParameteriEXT = NULL; +PFNGLMULTITEXPARAMETERIVEXTPROC glad_glMultiTexParameterivEXT = NULL; +PFNGLMULTITEXRENDERBUFFEREXTPROC glad_glMultiTexRenderbufferEXT = NULL; +PFNGLMULTITEXSUBIMAGE1DEXTPROC glad_glMultiTexSubImage1DEXT = NULL; +PFNGLMULTITEXSUBIMAGE2DEXTPROC glad_glMultiTexSubImage2DEXT = NULL; +PFNGLMULTITEXSUBIMAGE3DEXTPROC glad_glMultiTexSubImage3DEXT = NULL; +PFNGLNAMEDBUFFERDATAPROC glad_glNamedBufferData = NULL; +PFNGLNAMEDBUFFERDATAEXTPROC glad_glNamedBufferDataEXT = NULL; +PFNGLNAMEDBUFFERSTORAGEPROC glad_glNamedBufferStorage = NULL; +PFNGLNAMEDBUFFERSTORAGEEXTPROC glad_glNamedBufferStorageEXT = NULL; +PFNGLNAMEDBUFFERSUBDATAPROC glad_glNamedBufferSubData = NULL; +PFNGLNAMEDBUFFERSUBDATAEXTPROC glad_glNamedBufferSubDataEXT = NULL; +PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC glad_glNamedCopyBufferSubDataEXT = NULL; +PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glad_glNamedFramebufferDrawBuffer = NULL; +PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glad_glNamedFramebufferDrawBuffers = NULL; +PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glad_glNamedFramebufferParameteri = NULL; +PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC glad_glNamedFramebufferParameteriEXT = NULL; +PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glad_glNamedFramebufferReadBuffer = NULL; +PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glad_glNamedFramebufferRenderbuffer = NULL; +PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC glad_glNamedFramebufferRenderbufferEXT = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glad_glNamedFramebufferTexture = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC glad_glNamedFramebufferTexture1DEXT = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC glad_glNamedFramebufferTexture2DEXT = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC glad_glNamedFramebufferTexture3DEXT = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC glad_glNamedFramebufferTextureEXT = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC glad_glNamedFramebufferTextureFaceEXT = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glad_glNamedFramebufferTextureLayer = NULL; +PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC glad_glNamedFramebufferTextureLayerEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC glad_glNamedProgramLocalParameter4dEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC glad_glNamedProgramLocalParameter4dvEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC glad_glNamedProgramLocalParameter4fEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC glad_glNamedProgramLocalParameter4fvEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC glad_glNamedProgramLocalParameterI4iEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC glad_glNamedProgramLocalParameterI4ivEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC glad_glNamedProgramLocalParameterI4uiEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC glad_glNamedProgramLocalParameterI4uivEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC glad_glNamedProgramLocalParameters4fvEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC glad_glNamedProgramLocalParametersI4ivEXT = NULL; +PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC glad_glNamedProgramLocalParametersI4uivEXT = NULL; +PFNGLNAMEDPROGRAMSTRINGEXTPROC glad_glNamedProgramStringEXT = NULL; +PFNGLNAMEDRENDERBUFFERSTORAGEPROC glad_glNamedRenderbufferStorage = NULL; +PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC glad_glNamedRenderbufferStorageEXT = NULL; +PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glNamedRenderbufferStorageMultisample = NULL; +PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC glad_glNamedRenderbufferStorageMultisampleCoverageEXT = NULL; +PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glad_glNamedRenderbufferStorageMultisampleEXT = NULL; +PFNGLNEWLISTPROC glad_glNewList = NULL; +PFNGLNORMAL3BPROC glad_glNormal3b = NULL; +PFNGLNORMAL3BVPROC glad_glNormal3bv = NULL; +PFNGLNORMAL3DPROC glad_glNormal3d = NULL; +PFNGLNORMAL3DVPROC glad_glNormal3dv = NULL; +PFNGLNORMAL3FPROC glad_glNormal3f = NULL; +PFNGLNORMAL3FVPROC glad_glNormal3fv = NULL; +PFNGLNORMAL3IPROC glad_glNormal3i = NULL; +PFNGLNORMAL3IVPROC glad_glNormal3iv = NULL; +PFNGLNORMAL3SPROC glad_glNormal3s = NULL; +PFNGLNORMAL3SVPROC glad_glNormal3sv = NULL; +PFNGLNORMALP3UIPROC glad_glNormalP3ui = NULL; +PFNGLNORMALP3UIVPROC glad_glNormalP3uiv = NULL; +PFNGLNORMALPOINTERPROC glad_glNormalPointer = NULL; +PFNGLOBJECTLABELPROC glad_glObjectLabel = NULL; +PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel = NULL; +PFNGLORTHOPROC glad_glOrtho = NULL; +PFNGLPASSTHROUGHPROC glad_glPassThrough = NULL; +PFNGLPATCHPARAMETERFVPROC glad_glPatchParameterfv = NULL; +PFNGLPATCHPARAMETERIPROC glad_glPatchParameteri = NULL; +PFNGLPAUSETRANSFORMFEEDBACKPROC glad_glPauseTransformFeedback = NULL; +PFNGLPIXELMAPFVPROC glad_glPixelMapfv = NULL; +PFNGLPIXELMAPUIVPROC glad_glPixelMapuiv = NULL; +PFNGLPIXELMAPUSVPROC glad_glPixelMapusv = NULL; +PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL; +PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL; +PFNGLPIXELTRANSFERFPROC glad_glPixelTransferf = NULL; +PFNGLPIXELTRANSFERIPROC glad_glPixelTransferi = NULL; +PFNGLPIXELZOOMPROC glad_glPixelZoom = NULL; +PFNGLPOINTPARAMETERFPROC glad_glPointParameterf = NULL; +PFNGLPOINTPARAMETERFVPROC glad_glPointParameterfv = NULL; +PFNGLPOINTPARAMETERIPROC glad_glPointParameteri = NULL; +PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL; +PFNGLPOINTSIZEPROC glad_glPointSize = NULL; +PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL; +PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL; +PFNGLPOLYGONOFFSETCLAMPPROC glad_glPolygonOffsetClamp = NULL; +PFNGLPOLYGONSTIPPLEPROC glad_glPolygonStipple = NULL; +PFNGLPOPATTRIBPROC glad_glPopAttrib = NULL; +PFNGLPOPCLIENTATTRIBPROC glad_glPopClientAttrib = NULL; +PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup = NULL; +PFNGLPOPMATRIXPROC glad_glPopMatrix = NULL; +PFNGLPOPNAMEPROC glad_glPopName = NULL; +PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL; +PFNGLPRIORITIZETEXTURESPROC glad_glPrioritizeTextures = NULL; +PFNGLPROGRAMBINARYPROC glad_glProgramBinary = NULL; +PFNGLPROGRAMENVPARAMETER4DARBPROC glad_glProgramEnvParameter4dARB = NULL; +PFNGLPROGRAMENVPARAMETER4DVARBPROC glad_glProgramEnvParameter4dvARB = NULL; +PFNGLPROGRAMENVPARAMETER4FARBPROC glad_glProgramEnvParameter4fARB = NULL; +PFNGLPROGRAMENVPARAMETER4FVARBPROC glad_glProgramEnvParameter4fvARB = NULL; +PFNGLPROGRAMLOCALPARAMETER4DARBPROC glad_glProgramLocalParameter4dARB = NULL; +PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glad_glProgramLocalParameter4dvARB = NULL; +PFNGLPROGRAMLOCALPARAMETER4FARBPROC glad_glProgramLocalParameter4fARB = NULL; +PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glad_glProgramLocalParameter4fvARB = NULL; +PFNGLPROGRAMPARAMETERIPROC glad_glProgramParameteri = NULL; +PFNGLPROGRAMPARAMETERIEXTPROC glad_glProgramParameteriEXT = NULL; +PFNGLPROGRAMSTRINGARBPROC glad_glProgramStringARB = NULL; +PFNGLPROGRAMUNIFORM1DPROC glad_glProgramUniform1d = NULL; +PFNGLPROGRAMUNIFORM1DEXTPROC glad_glProgramUniform1dEXT = NULL; +PFNGLPROGRAMUNIFORM1DVPROC glad_glProgramUniform1dv = NULL; +PFNGLPROGRAMUNIFORM1DVEXTPROC glad_glProgramUniform1dvEXT = NULL; +PFNGLPROGRAMUNIFORM1FPROC glad_glProgramUniform1f = NULL; +PFNGLPROGRAMUNIFORM1FEXTPROC glad_glProgramUniform1fEXT = NULL; +PFNGLPROGRAMUNIFORM1FVPROC glad_glProgramUniform1fv = NULL; +PFNGLPROGRAMUNIFORM1FVEXTPROC glad_glProgramUniform1fvEXT = NULL; +PFNGLPROGRAMUNIFORM1IPROC glad_glProgramUniform1i = NULL; +PFNGLPROGRAMUNIFORM1IEXTPROC glad_glProgramUniform1iEXT = NULL; +PFNGLPROGRAMUNIFORM1IVPROC glad_glProgramUniform1iv = NULL; +PFNGLPROGRAMUNIFORM1IVEXTPROC glad_glProgramUniform1ivEXT = NULL; +PFNGLPROGRAMUNIFORM1UIPROC glad_glProgramUniform1ui = NULL; +PFNGLPROGRAMUNIFORM1UIEXTPROC glad_glProgramUniform1uiEXT = NULL; +PFNGLPROGRAMUNIFORM1UIVPROC glad_glProgramUniform1uiv = NULL; +PFNGLPROGRAMUNIFORM1UIVEXTPROC glad_glProgramUniform1uivEXT = NULL; +PFNGLPROGRAMUNIFORM2DPROC glad_glProgramUniform2d = NULL; +PFNGLPROGRAMUNIFORM2DEXTPROC glad_glProgramUniform2dEXT = NULL; +PFNGLPROGRAMUNIFORM2DVPROC glad_glProgramUniform2dv = NULL; +PFNGLPROGRAMUNIFORM2DVEXTPROC glad_glProgramUniform2dvEXT = NULL; +PFNGLPROGRAMUNIFORM2FPROC glad_glProgramUniform2f = NULL; +PFNGLPROGRAMUNIFORM2FEXTPROC glad_glProgramUniform2fEXT = NULL; +PFNGLPROGRAMUNIFORM2FVPROC glad_glProgramUniform2fv = NULL; +PFNGLPROGRAMUNIFORM2FVEXTPROC glad_glProgramUniform2fvEXT = NULL; +PFNGLPROGRAMUNIFORM2IPROC glad_glProgramUniform2i = NULL; +PFNGLPROGRAMUNIFORM2IEXTPROC glad_glProgramUniform2iEXT = NULL; +PFNGLPROGRAMUNIFORM2IVPROC glad_glProgramUniform2iv = NULL; +PFNGLPROGRAMUNIFORM2IVEXTPROC glad_glProgramUniform2ivEXT = NULL; +PFNGLPROGRAMUNIFORM2UIPROC glad_glProgramUniform2ui = NULL; +PFNGLPROGRAMUNIFORM2UIEXTPROC glad_glProgramUniform2uiEXT = NULL; +PFNGLPROGRAMUNIFORM2UIVPROC glad_glProgramUniform2uiv = NULL; +PFNGLPROGRAMUNIFORM2UIVEXTPROC glad_glProgramUniform2uivEXT = NULL; +PFNGLPROGRAMUNIFORM3DPROC glad_glProgramUniform3d = NULL; +PFNGLPROGRAMUNIFORM3DEXTPROC glad_glProgramUniform3dEXT = NULL; +PFNGLPROGRAMUNIFORM3DVPROC glad_glProgramUniform3dv = NULL; +PFNGLPROGRAMUNIFORM3DVEXTPROC glad_glProgramUniform3dvEXT = NULL; +PFNGLPROGRAMUNIFORM3FPROC glad_glProgramUniform3f = NULL; +PFNGLPROGRAMUNIFORM3FEXTPROC glad_glProgramUniform3fEXT = NULL; +PFNGLPROGRAMUNIFORM3FVPROC glad_glProgramUniform3fv = NULL; +PFNGLPROGRAMUNIFORM3FVEXTPROC glad_glProgramUniform3fvEXT = NULL; +PFNGLPROGRAMUNIFORM3IPROC glad_glProgramUniform3i = NULL; +PFNGLPROGRAMUNIFORM3IEXTPROC glad_glProgramUniform3iEXT = NULL; +PFNGLPROGRAMUNIFORM3IVPROC glad_glProgramUniform3iv = NULL; +PFNGLPROGRAMUNIFORM3IVEXTPROC glad_glProgramUniform3ivEXT = NULL; +PFNGLPROGRAMUNIFORM3UIPROC glad_glProgramUniform3ui = NULL; +PFNGLPROGRAMUNIFORM3UIEXTPROC glad_glProgramUniform3uiEXT = NULL; +PFNGLPROGRAMUNIFORM3UIVPROC glad_glProgramUniform3uiv = NULL; +PFNGLPROGRAMUNIFORM3UIVEXTPROC glad_glProgramUniform3uivEXT = NULL; +PFNGLPROGRAMUNIFORM4DPROC glad_glProgramUniform4d = NULL; +PFNGLPROGRAMUNIFORM4DEXTPROC glad_glProgramUniform4dEXT = NULL; +PFNGLPROGRAMUNIFORM4DVPROC glad_glProgramUniform4dv = NULL; +PFNGLPROGRAMUNIFORM4DVEXTPROC glad_glProgramUniform4dvEXT = NULL; +PFNGLPROGRAMUNIFORM4FPROC glad_glProgramUniform4f = NULL; +PFNGLPROGRAMUNIFORM4FEXTPROC glad_glProgramUniform4fEXT = NULL; +PFNGLPROGRAMUNIFORM4FVPROC glad_glProgramUniform4fv = NULL; +PFNGLPROGRAMUNIFORM4FVEXTPROC glad_glProgramUniform4fvEXT = NULL; +PFNGLPROGRAMUNIFORM4IPROC glad_glProgramUniform4i = NULL; +PFNGLPROGRAMUNIFORM4IEXTPROC glad_glProgramUniform4iEXT = NULL; +PFNGLPROGRAMUNIFORM4IVPROC glad_glProgramUniform4iv = NULL; +PFNGLPROGRAMUNIFORM4IVEXTPROC glad_glProgramUniform4ivEXT = NULL; +PFNGLPROGRAMUNIFORM4UIPROC glad_glProgramUniform4ui = NULL; +PFNGLPROGRAMUNIFORM4UIEXTPROC glad_glProgramUniform4uiEXT = NULL; +PFNGLPROGRAMUNIFORM4UIVPROC glad_glProgramUniform4uiv = NULL; +PFNGLPROGRAMUNIFORM4UIVEXTPROC glad_glProgramUniform4uivEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX2DVPROC glad_glProgramUniformMatrix2dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC glad_glProgramUniformMatrix2dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX2FVPROC glad_glProgramUniformMatrix2fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC glad_glProgramUniformMatrix2fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC glad_glProgramUniformMatrix2x3dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC glad_glProgramUniformMatrix2x3dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC glad_glProgramUniformMatrix2x3fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC glad_glProgramUniformMatrix2x3fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC glad_glProgramUniformMatrix2x4dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC glad_glProgramUniformMatrix2x4dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC glad_glProgramUniformMatrix2x4fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC glad_glProgramUniformMatrix2x4fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX3DVPROC glad_glProgramUniformMatrix3dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC glad_glProgramUniformMatrix3dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX3FVPROC glad_glProgramUniformMatrix3fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC glad_glProgramUniformMatrix3fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC glad_glProgramUniformMatrix3x2dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC glad_glProgramUniformMatrix3x2dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC glad_glProgramUniformMatrix3x2fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC glad_glProgramUniformMatrix3x2fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC glad_glProgramUniformMatrix3x4dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC glad_glProgramUniformMatrix3x4dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC glad_glProgramUniformMatrix3x4fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC glad_glProgramUniformMatrix3x4fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX4DVPROC glad_glProgramUniformMatrix4dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC glad_glProgramUniformMatrix4dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX4FVPROC glad_glProgramUniformMatrix4fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC glad_glProgramUniformMatrix4fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC glad_glProgramUniformMatrix4x2dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC glad_glProgramUniformMatrix4x2dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC glad_glProgramUniformMatrix4x2fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC glad_glProgramUniformMatrix4x2fvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC glad_glProgramUniformMatrix4x3dv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC glad_glProgramUniformMatrix4x3dvEXT = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC glad_glProgramUniformMatrix4x3fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC glad_glProgramUniformMatrix4x3fvEXT = NULL; +PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL; +PFNGLPUSHATTRIBPROC glad_glPushAttrib = NULL; +PFNGLPUSHCLIENTATTRIBPROC glad_glPushClientAttrib = NULL; +PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC glad_glPushClientAttribDefaultEXT = NULL; +PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup = NULL; +PFNGLPUSHMATRIXPROC glad_glPushMatrix = NULL; +PFNGLPUSHNAMEPROC glad_glPushName = NULL; +PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL; +PFNGLRASTERPOS2DPROC glad_glRasterPos2d = NULL; +PFNGLRASTERPOS2DVPROC glad_glRasterPos2dv = NULL; +PFNGLRASTERPOS2FPROC glad_glRasterPos2f = NULL; +PFNGLRASTERPOS2FVPROC glad_glRasterPos2fv = NULL; +PFNGLRASTERPOS2IPROC glad_glRasterPos2i = NULL; +PFNGLRASTERPOS2IVPROC glad_glRasterPos2iv = NULL; +PFNGLRASTERPOS2SPROC glad_glRasterPos2s = NULL; +PFNGLRASTERPOS2SVPROC glad_glRasterPos2sv = NULL; +PFNGLRASTERPOS3DPROC glad_glRasterPos3d = NULL; +PFNGLRASTERPOS3DVPROC glad_glRasterPos3dv = NULL; +PFNGLRASTERPOS3FPROC glad_glRasterPos3f = NULL; +PFNGLRASTERPOS3FVPROC glad_glRasterPos3fv = NULL; +PFNGLRASTERPOS3IPROC glad_glRasterPos3i = NULL; +PFNGLRASTERPOS3IVPROC glad_glRasterPos3iv = NULL; +PFNGLRASTERPOS3SPROC glad_glRasterPos3s = NULL; +PFNGLRASTERPOS3SVPROC glad_glRasterPos3sv = NULL; +PFNGLRASTERPOS4DPROC glad_glRasterPos4d = NULL; +PFNGLRASTERPOS4DVPROC glad_glRasterPos4dv = NULL; +PFNGLRASTERPOS4FPROC glad_glRasterPos4f = NULL; +PFNGLRASTERPOS4FVPROC glad_glRasterPos4fv = NULL; +PFNGLRASTERPOS4IPROC glad_glRasterPos4i = NULL; +PFNGLRASTERPOS4IVPROC glad_glRasterPos4iv = NULL; +PFNGLRASTERPOS4SPROC glad_glRasterPos4s = NULL; +PFNGLRASTERPOS4SVPROC glad_glRasterPos4sv = NULL; +PFNGLREADBUFFERPROC glad_glReadBuffer = NULL; +PFNGLREADPIXELSPROC glad_glReadPixels = NULL; +PFNGLREADNPIXELSPROC glad_glReadnPixels = NULL; +PFNGLRECTDPROC glad_glRectd = NULL; +PFNGLRECTDVPROC glad_glRectdv = NULL; +PFNGLRECTFPROC glad_glRectf = NULL; +PFNGLRECTFVPROC glad_glRectfv = NULL; +PFNGLRECTIPROC glad_glRecti = NULL; +PFNGLRECTIVPROC glad_glRectiv = NULL; +PFNGLRECTSPROC glad_glRects = NULL; +PFNGLRECTSVPROC glad_glRectsv = NULL; +PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler = NULL; +PFNGLRENDERMODEPROC glad_glRenderMode = NULL; +PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL; +PFNGLRENDERBUFFERSTORAGEEXTPROC glad_glRenderbufferStorageEXT = NULL; +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL; +PFNGLRESUMETRANSFORMFEEDBACKPROC glad_glResumeTransformFeedback = NULL; +PFNGLROTATEDPROC glad_glRotated = NULL; +PFNGLROTATEFPROC glad_glRotatef = NULL; +PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL; +PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL; +PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL; +PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL; +PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL; +PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL; +PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL; +PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL; +PFNGLSCALEDPROC glad_glScaled = NULL; +PFNGLSCALEFPROC glad_glScalef = NULL; +PFNGLSCISSORPROC glad_glScissor = NULL; +PFNGLSCISSORARRAYVPROC glad_glScissorArrayv = NULL; +PFNGLSCISSORINDEXEDPROC glad_glScissorIndexed = NULL; +PFNGLSCISSORINDEXEDVPROC glad_glScissorIndexedv = NULL; +PFNGLSECONDARYCOLOR3BPROC glad_glSecondaryColor3b = NULL; +PFNGLSECONDARYCOLOR3BVPROC glad_glSecondaryColor3bv = NULL; +PFNGLSECONDARYCOLOR3DPROC glad_glSecondaryColor3d = NULL; +PFNGLSECONDARYCOLOR3DVPROC glad_glSecondaryColor3dv = NULL; +PFNGLSECONDARYCOLOR3FPROC glad_glSecondaryColor3f = NULL; +PFNGLSECONDARYCOLOR3FVPROC glad_glSecondaryColor3fv = NULL; +PFNGLSECONDARYCOLOR3IPROC glad_glSecondaryColor3i = NULL; +PFNGLSECONDARYCOLOR3IVPROC glad_glSecondaryColor3iv = NULL; +PFNGLSECONDARYCOLOR3SPROC glad_glSecondaryColor3s = NULL; +PFNGLSECONDARYCOLOR3SVPROC glad_glSecondaryColor3sv = NULL; +PFNGLSECONDARYCOLOR3UBPROC glad_glSecondaryColor3ub = NULL; +PFNGLSECONDARYCOLOR3UBVPROC glad_glSecondaryColor3ubv = NULL; +PFNGLSECONDARYCOLOR3UIPROC glad_glSecondaryColor3ui = NULL; +PFNGLSECONDARYCOLOR3UIVPROC glad_glSecondaryColor3uiv = NULL; +PFNGLSECONDARYCOLOR3USPROC glad_glSecondaryColor3us = NULL; +PFNGLSECONDARYCOLOR3USVPROC glad_glSecondaryColor3usv = NULL; +PFNGLSECONDARYCOLORP3UIPROC glad_glSecondaryColorP3ui = NULL; +PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv = NULL; +PFNGLSECONDARYCOLORPOINTERPROC glad_glSecondaryColorPointer = NULL; +PFNGLSELECTBUFFERPROC glad_glSelectBuffer = NULL; +PFNGLSHADEMODELPROC glad_glShadeModel = NULL; +PFNGLSHADERBINARYPROC glad_glShaderBinary = NULL; +PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL; +PFNGLSHADERSOURCEARBPROC glad_glShaderSourceARB = NULL; +PFNGLSHADERSTORAGEBLOCKBINDINGPROC glad_glShaderStorageBlockBinding = NULL; +PFNGLSPECIALIZESHADERPROC glad_glSpecializeShader = NULL; +PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL; +PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL; +PFNGLSTENCILMASKPROC glad_glStencilMask = NULL; +PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL; +PFNGLSTENCILOPPROC glad_glStencilOp = NULL; +PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL; +PFNGLSUBPIXELPRECISIONBIASNVPROC glad_glSubpixelPrecisionBiasNV = NULL; +PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL; +PFNGLTEXBUFFERRANGEPROC glad_glTexBufferRange = NULL; +PFNGLTEXCOORD1DPROC glad_glTexCoord1d = NULL; +PFNGLTEXCOORD1DVPROC glad_glTexCoord1dv = NULL; +PFNGLTEXCOORD1FPROC glad_glTexCoord1f = NULL; +PFNGLTEXCOORD1FVPROC glad_glTexCoord1fv = NULL; +PFNGLTEXCOORD1IPROC glad_glTexCoord1i = NULL; +PFNGLTEXCOORD1IVPROC glad_glTexCoord1iv = NULL; +PFNGLTEXCOORD1SPROC glad_glTexCoord1s = NULL; +PFNGLTEXCOORD1SVPROC glad_glTexCoord1sv = NULL; +PFNGLTEXCOORD2DPROC glad_glTexCoord2d = NULL; +PFNGLTEXCOORD2DVPROC glad_glTexCoord2dv = NULL; +PFNGLTEXCOORD2FPROC glad_glTexCoord2f = NULL; +PFNGLTEXCOORD2FVPROC glad_glTexCoord2fv = NULL; +PFNGLTEXCOORD2IPROC glad_glTexCoord2i = NULL; +PFNGLTEXCOORD2IVPROC glad_glTexCoord2iv = NULL; +PFNGLTEXCOORD2SPROC glad_glTexCoord2s = NULL; +PFNGLTEXCOORD2SVPROC glad_glTexCoord2sv = NULL; +PFNGLTEXCOORD3DPROC glad_glTexCoord3d = NULL; +PFNGLTEXCOORD3DVPROC glad_glTexCoord3dv = NULL; +PFNGLTEXCOORD3FPROC glad_glTexCoord3f = NULL; +PFNGLTEXCOORD3FVPROC glad_glTexCoord3fv = NULL; +PFNGLTEXCOORD3IPROC glad_glTexCoord3i = NULL; +PFNGLTEXCOORD3IVPROC glad_glTexCoord3iv = NULL; +PFNGLTEXCOORD3SPROC glad_glTexCoord3s = NULL; +PFNGLTEXCOORD3SVPROC glad_glTexCoord3sv = NULL; +PFNGLTEXCOORD4DPROC glad_glTexCoord4d = NULL; +PFNGLTEXCOORD4DVPROC glad_glTexCoord4dv = NULL; +PFNGLTEXCOORD4FPROC glad_glTexCoord4f = NULL; +PFNGLTEXCOORD4FVPROC glad_glTexCoord4fv = NULL; +PFNGLTEXCOORD4IPROC glad_glTexCoord4i = NULL; +PFNGLTEXCOORD4IVPROC glad_glTexCoord4iv = NULL; +PFNGLTEXCOORD4SPROC glad_glTexCoord4s = NULL; +PFNGLTEXCOORD4SVPROC glad_glTexCoord4sv = NULL; +PFNGLTEXCOORDP1UIPROC glad_glTexCoordP1ui = NULL; +PFNGLTEXCOORDP1UIVPROC glad_glTexCoordP1uiv = NULL; +PFNGLTEXCOORDP2UIPROC glad_glTexCoordP2ui = NULL; +PFNGLTEXCOORDP2UIVPROC glad_glTexCoordP2uiv = NULL; +PFNGLTEXCOORDP3UIPROC glad_glTexCoordP3ui = NULL; +PFNGLTEXCOORDP3UIVPROC glad_glTexCoordP3uiv = NULL; +PFNGLTEXCOORDP4UIPROC glad_glTexCoordP4ui = NULL; +PFNGLTEXCOORDP4UIVPROC glad_glTexCoordP4uiv = NULL; +PFNGLTEXCOORDPOINTERPROC glad_glTexCoordPointer = NULL; +PFNGLTEXENVFPROC glad_glTexEnvf = NULL; +PFNGLTEXENVFVPROC glad_glTexEnvfv = NULL; +PFNGLTEXENVIPROC glad_glTexEnvi = NULL; +PFNGLTEXENVIVPROC glad_glTexEnviv = NULL; +PFNGLTEXGENDPROC glad_glTexGend = NULL; +PFNGLTEXGENDVPROC glad_glTexGendv = NULL; +PFNGLTEXGENFPROC glad_glTexGenf = NULL; +PFNGLTEXGENFVPROC glad_glTexGenfv = NULL; +PFNGLTEXGENIPROC glad_glTexGeni = NULL; +PFNGLTEXGENIVPROC glad_glTexGeniv = NULL; +PFNGLTEXIMAGE1DPROC glad_glTexImage1D = NULL; +PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL; +PFNGLTEXIMAGE2DMULTISAMPLEPROC glad_glTexImage2DMultisample = NULL; +PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL; +PFNGLTEXIMAGE3DMULTISAMPLEPROC glad_glTexImage3DMultisample = NULL; +PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL; +PFNGLTEXPARAMETERIIVEXTPROC glad_glTexParameterIivEXT = NULL; +PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL; +PFNGLTEXPARAMETERIUIVEXTPROC glad_glTexParameterIuivEXT = NULL; +PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL; +PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL; +PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL; +PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL; +PFNGLTEXSTORAGE1DPROC glad_glTexStorage1D = NULL; +PFNGLTEXSTORAGE2DPROC glad_glTexStorage2D = NULL; +PFNGLTEXSTORAGE2DMULTISAMPLEPROC glad_glTexStorage2DMultisample = NULL; +PFNGLTEXSTORAGE3DPROC glad_glTexStorage3D = NULL; +PFNGLTEXSTORAGE3DMULTISAMPLEPROC glad_glTexStorage3DMultisample = NULL; +PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL; +PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL; +PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL; +PFNGLTEXTUREBARRIERPROC glad_glTextureBarrier = NULL; +PFNGLTEXTUREBUFFERPROC glad_glTextureBuffer = NULL; +PFNGLTEXTUREBUFFEREXTPROC glad_glTextureBufferEXT = NULL; +PFNGLTEXTUREBUFFERRANGEPROC glad_glTextureBufferRange = NULL; +PFNGLTEXTUREBUFFERRANGEEXTPROC glad_glTextureBufferRangeEXT = NULL; +PFNGLTEXTUREIMAGE1DEXTPROC glad_glTextureImage1DEXT = NULL; +PFNGLTEXTUREIMAGE2DEXTPROC glad_glTextureImage2DEXT = NULL; +PFNGLTEXTUREIMAGE3DEXTPROC glad_glTextureImage3DEXT = NULL; +PFNGLTEXTUREPAGECOMMITMENTEXTPROC glad_glTexturePageCommitmentEXT = NULL; +PFNGLTEXTUREPARAMETERIIVPROC glad_glTextureParameterIiv = NULL; +PFNGLTEXTUREPARAMETERIIVEXTPROC glad_glTextureParameterIivEXT = NULL; +PFNGLTEXTUREPARAMETERIUIVPROC glad_glTextureParameterIuiv = NULL; +PFNGLTEXTUREPARAMETERIUIVEXTPROC glad_glTextureParameterIuivEXT = NULL; +PFNGLTEXTUREPARAMETERFPROC glad_glTextureParameterf = NULL; +PFNGLTEXTUREPARAMETERFEXTPROC glad_glTextureParameterfEXT = NULL; +PFNGLTEXTUREPARAMETERFVPROC glad_glTextureParameterfv = NULL; +PFNGLTEXTUREPARAMETERFVEXTPROC glad_glTextureParameterfvEXT = NULL; +PFNGLTEXTUREPARAMETERIPROC glad_glTextureParameteri = NULL; +PFNGLTEXTUREPARAMETERIEXTPROC glad_glTextureParameteriEXT = NULL; +PFNGLTEXTUREPARAMETERIVPROC glad_glTextureParameteriv = NULL; +PFNGLTEXTUREPARAMETERIVEXTPROC glad_glTextureParameterivEXT = NULL; +PFNGLTEXTURERENDERBUFFEREXTPROC glad_glTextureRenderbufferEXT = NULL; +PFNGLTEXTURESTORAGE1DPROC glad_glTextureStorage1D = NULL; +PFNGLTEXTURESTORAGE1DEXTPROC glad_glTextureStorage1DEXT = NULL; +PFNGLTEXTURESTORAGE2DPROC glad_glTextureStorage2D = NULL; +PFNGLTEXTURESTORAGE2DEXTPROC glad_glTextureStorage2DEXT = NULL; +PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glad_glTextureStorage2DMultisample = NULL; +PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC glad_glTextureStorage2DMultisampleEXT = NULL; +PFNGLTEXTURESTORAGE3DPROC glad_glTextureStorage3D = NULL; +PFNGLTEXTURESTORAGE3DEXTPROC glad_glTextureStorage3DEXT = NULL; +PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glad_glTextureStorage3DMultisample = NULL; +PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC glad_glTextureStorage3DMultisampleEXT = NULL; +PFNGLTEXTURESUBIMAGE1DPROC glad_glTextureSubImage1D = NULL; +PFNGLTEXTURESUBIMAGE1DEXTPROC glad_glTextureSubImage1DEXT = NULL; +PFNGLTEXTURESUBIMAGE2DPROC glad_glTextureSubImage2D = NULL; +PFNGLTEXTURESUBIMAGE2DEXTPROC glad_glTextureSubImage2DEXT = NULL; +PFNGLTEXTURESUBIMAGE3DPROC glad_glTextureSubImage3D = NULL; +PFNGLTEXTURESUBIMAGE3DEXTPROC glad_glTextureSubImage3DEXT = NULL; +PFNGLTEXTUREVIEWPROC glad_glTextureView = NULL; +PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glad_glTransformFeedbackBufferBase = NULL; +PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glad_glTransformFeedbackBufferRange = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC glad_glTransformFeedbackVaryingsEXT = NULL; +PFNGLTRANSLATEDPROC glad_glTranslated = NULL; +PFNGLTRANSLATEFPROC glad_glTranslatef = NULL; +PFNGLUNIFORM1DPROC glad_glUniform1d = NULL; +PFNGLUNIFORM1DVPROC glad_glUniform1dv = NULL; +PFNGLUNIFORM1FPROC glad_glUniform1f = NULL; +PFNGLUNIFORM1FARBPROC glad_glUniform1fARB = NULL; +PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL; +PFNGLUNIFORM1FVARBPROC glad_glUniform1fvARB = NULL; +PFNGLUNIFORM1IPROC glad_glUniform1i = NULL; +PFNGLUNIFORM1IARBPROC glad_glUniform1iARB = NULL; +PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL; +PFNGLUNIFORM1IVARBPROC glad_glUniform1ivARB = NULL; +PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL; +PFNGLUNIFORM1UIEXTPROC glad_glUniform1uiEXT = NULL; +PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL; +PFNGLUNIFORM1UIVEXTPROC glad_glUniform1uivEXT = NULL; +PFNGLUNIFORM2DPROC glad_glUniform2d = NULL; +PFNGLUNIFORM2DVPROC glad_glUniform2dv = NULL; +PFNGLUNIFORM2FPROC glad_glUniform2f = NULL; +PFNGLUNIFORM2FARBPROC glad_glUniform2fARB = NULL; +PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL; +PFNGLUNIFORM2FVARBPROC glad_glUniform2fvARB = NULL; +PFNGLUNIFORM2IPROC glad_glUniform2i = NULL; +PFNGLUNIFORM2IARBPROC glad_glUniform2iARB = NULL; +PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL; +PFNGLUNIFORM2IVARBPROC glad_glUniform2ivARB = NULL; +PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL; +PFNGLUNIFORM2UIEXTPROC glad_glUniform2uiEXT = NULL; +PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL; +PFNGLUNIFORM2UIVEXTPROC glad_glUniform2uivEXT = NULL; +PFNGLUNIFORM3DPROC glad_glUniform3d = NULL; +PFNGLUNIFORM3DVPROC glad_glUniform3dv = NULL; +PFNGLUNIFORM3FPROC glad_glUniform3f = NULL; +PFNGLUNIFORM3FARBPROC glad_glUniform3fARB = NULL; +PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL; +PFNGLUNIFORM3FVARBPROC glad_glUniform3fvARB = NULL; +PFNGLUNIFORM3IPROC glad_glUniform3i = NULL; +PFNGLUNIFORM3IARBPROC glad_glUniform3iARB = NULL; +PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL; +PFNGLUNIFORM3IVARBPROC glad_glUniform3ivARB = NULL; +PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL; +PFNGLUNIFORM3UIEXTPROC glad_glUniform3uiEXT = NULL; +PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL; +PFNGLUNIFORM3UIVEXTPROC glad_glUniform3uivEXT = NULL; +PFNGLUNIFORM4DPROC glad_glUniform4d = NULL; +PFNGLUNIFORM4DVPROC glad_glUniform4dv = NULL; +PFNGLUNIFORM4FPROC glad_glUniform4f = NULL; +PFNGLUNIFORM4FARBPROC glad_glUniform4fARB = NULL; +PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL; +PFNGLUNIFORM4FVARBPROC glad_glUniform4fvARB = NULL; +PFNGLUNIFORM4IPROC glad_glUniform4i = NULL; +PFNGLUNIFORM4IARBPROC glad_glUniform4iARB = NULL; +PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL; +PFNGLUNIFORM4IVARBPROC glad_glUniform4ivARB = NULL; +PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL; +PFNGLUNIFORM4UIEXTPROC glad_glUniform4uiEXT = NULL; +PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL; +PFNGLUNIFORM4UIVEXTPROC glad_glUniform4uivEXT = NULL; +PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL; +PFNGLUNIFORMMATRIX2DVPROC glad_glUniformMatrix2dv = NULL; +PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL; +PFNGLUNIFORMMATRIX2FVARBPROC glad_glUniformMatrix2fvARB = NULL; +PFNGLUNIFORMMATRIX2X3DVPROC glad_glUniformMatrix2x3dv = NULL; +PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL; +PFNGLUNIFORMMATRIX2X4DVPROC glad_glUniformMatrix2x4dv = NULL; +PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL; +PFNGLUNIFORMMATRIX3DVPROC glad_glUniformMatrix3dv = NULL; +PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL; +PFNGLUNIFORMMATRIX3FVARBPROC glad_glUniformMatrix3fvARB = NULL; +PFNGLUNIFORMMATRIX3X2DVPROC glad_glUniformMatrix3x2dv = NULL; +PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL; +PFNGLUNIFORMMATRIX3X4DVPROC glad_glUniformMatrix3x4dv = NULL; +PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL; +PFNGLUNIFORMMATRIX4DVPROC glad_glUniformMatrix4dv = NULL; +PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL; +PFNGLUNIFORMMATRIX4FVARBPROC glad_glUniformMatrix4fvARB = NULL; +PFNGLUNIFORMMATRIX4X2DVPROC glad_glUniformMatrix4x2dv = NULL; +PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL; +PFNGLUNIFORMMATRIX4X3DVPROC glad_glUniformMatrix4x3dv = NULL; +PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL; +PFNGLUNIFORMSUBROUTINESUIVPROC glad_glUniformSubroutinesuiv = NULL; +PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL; +PFNGLUNMAPBUFFERARBPROC glad_glUnmapBufferARB = NULL; +PFNGLUNMAPNAMEDBUFFERPROC glad_glUnmapNamedBuffer = NULL; +PFNGLUNMAPNAMEDBUFFEREXTPROC glad_glUnmapNamedBufferEXT = NULL; +PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL; +PFNGLUSEPROGRAMOBJECTARBPROC glad_glUseProgramObjectARB = NULL; +PFNGLUSEPROGRAMSTAGESPROC glad_glUseProgramStages = NULL; +PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL; +PFNGLVALIDATEPROGRAMARBPROC glad_glValidateProgramARB = NULL; +PFNGLVALIDATEPROGRAMPIPELINEPROC glad_glValidateProgramPipeline = NULL; +PFNGLVERTEX2DPROC glad_glVertex2d = NULL; +PFNGLVERTEX2DVPROC glad_glVertex2dv = NULL; +PFNGLVERTEX2FPROC glad_glVertex2f = NULL; +PFNGLVERTEX2FVPROC glad_glVertex2fv = NULL; +PFNGLVERTEX2IPROC glad_glVertex2i = NULL; +PFNGLVERTEX2IVPROC glad_glVertex2iv = NULL; +PFNGLVERTEX2SPROC glad_glVertex2s = NULL; +PFNGLVERTEX2SVPROC glad_glVertex2sv = NULL; +PFNGLVERTEX3DPROC glad_glVertex3d = NULL; +PFNGLVERTEX3DVPROC glad_glVertex3dv = NULL; +PFNGLVERTEX3FPROC glad_glVertex3f = NULL; +PFNGLVERTEX3FVPROC glad_glVertex3fv = NULL; +PFNGLVERTEX3IPROC glad_glVertex3i = NULL; +PFNGLVERTEX3IVPROC glad_glVertex3iv = NULL; +PFNGLVERTEX3SPROC glad_glVertex3s = NULL; +PFNGLVERTEX3SVPROC glad_glVertex3sv = NULL; +PFNGLVERTEX4DPROC glad_glVertex4d = NULL; +PFNGLVERTEX4DVPROC glad_glVertex4dv = NULL; +PFNGLVERTEX4FPROC glad_glVertex4f = NULL; +PFNGLVERTEX4FVPROC glad_glVertex4fv = NULL; +PFNGLVERTEX4IPROC glad_glVertex4i = NULL; +PFNGLVERTEX4IVPROC glad_glVertex4iv = NULL; +PFNGLVERTEX4SPROC glad_glVertex4s = NULL; +PFNGLVERTEX4SVPROC glad_glVertex4sv = NULL; +PFNGLVERTEXARRAYATTRIBBINDINGPROC glad_glVertexArrayAttribBinding = NULL; +PFNGLVERTEXARRAYATTRIBFORMATPROC glad_glVertexArrayAttribFormat = NULL; +PFNGLVERTEXARRAYATTRIBIFORMATPROC glad_glVertexArrayAttribIFormat = NULL; +PFNGLVERTEXARRAYATTRIBLFORMATPROC glad_glVertexArrayAttribLFormat = NULL; +PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC glad_glVertexArrayBindVertexBufferEXT = NULL; +PFNGLVERTEXARRAYBINDINGDIVISORPROC glad_glVertexArrayBindingDivisor = NULL; +PFNGLVERTEXARRAYCOLOROFFSETEXTPROC glad_glVertexArrayColorOffsetEXT = NULL; +PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC glad_glVertexArrayEdgeFlagOffsetEXT = NULL; +PFNGLVERTEXARRAYELEMENTBUFFERPROC glad_glVertexArrayElementBuffer = NULL; +PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC glad_glVertexArrayFogCoordOffsetEXT = NULL; +PFNGLVERTEXARRAYINDEXOFFSETEXTPROC glad_glVertexArrayIndexOffsetEXT = NULL; +PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC glad_glVertexArrayMultiTexCoordOffsetEXT = NULL; +PFNGLVERTEXARRAYNORMALOFFSETEXTPROC glad_glVertexArrayNormalOffsetEXT = NULL; +PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC glad_glVertexArraySecondaryColorOffsetEXT = NULL; +PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC glad_glVertexArrayTexCoordOffsetEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC glad_glVertexArrayVertexAttribBindingEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC glad_glVertexArrayVertexAttribDivisorEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC glad_glVertexArrayVertexAttribFormatEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC glad_glVertexArrayVertexAttribIFormatEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC glad_glVertexArrayVertexAttribIOffsetEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC glad_glVertexArrayVertexAttribLFormatEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC glad_glVertexArrayVertexAttribLOffsetEXT = NULL; +PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC glad_glVertexArrayVertexAttribOffsetEXT = NULL; +PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC glad_glVertexArrayVertexBindingDivisorEXT = NULL; +PFNGLVERTEXARRAYVERTEXBUFFERPROC glad_glVertexArrayVertexBuffer = NULL; +PFNGLVERTEXARRAYVERTEXBUFFERSPROC glad_glVertexArrayVertexBuffers = NULL; +PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC glad_glVertexArrayVertexOffsetEXT = NULL; +PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL; +PFNGLVERTEXATTRIB1DARBPROC glad_glVertexAttrib1dARB = NULL; +PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL; +PFNGLVERTEXATTRIB1DVARBPROC glad_glVertexAttrib1dvARB = NULL; +PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL; +PFNGLVERTEXATTRIB1FARBPROC glad_glVertexAttrib1fARB = NULL; +PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL; +PFNGLVERTEXATTRIB1FVARBPROC glad_glVertexAttrib1fvARB = NULL; +PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL; +PFNGLVERTEXATTRIB1SARBPROC glad_glVertexAttrib1sARB = NULL; +PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL; +PFNGLVERTEXATTRIB1SVARBPROC glad_glVertexAttrib1svARB = NULL; +PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL; +PFNGLVERTEXATTRIB2DARBPROC glad_glVertexAttrib2dARB = NULL; +PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL; +PFNGLVERTEXATTRIB2DVARBPROC glad_glVertexAttrib2dvARB = NULL; +PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL; +PFNGLVERTEXATTRIB2FARBPROC glad_glVertexAttrib2fARB = NULL; +PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL; +PFNGLVERTEXATTRIB2FVARBPROC glad_glVertexAttrib2fvARB = NULL; +PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL; +PFNGLVERTEXATTRIB2SARBPROC glad_glVertexAttrib2sARB = NULL; +PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL; +PFNGLVERTEXATTRIB2SVARBPROC glad_glVertexAttrib2svARB = NULL; +PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL; +PFNGLVERTEXATTRIB3DARBPROC glad_glVertexAttrib3dARB = NULL; +PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL; +PFNGLVERTEXATTRIB3DVARBPROC glad_glVertexAttrib3dvARB = NULL; +PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL; +PFNGLVERTEXATTRIB3FARBPROC glad_glVertexAttrib3fARB = NULL; +PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL; +PFNGLVERTEXATTRIB3FVARBPROC glad_glVertexAttrib3fvARB = NULL; +PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL; +PFNGLVERTEXATTRIB3SARBPROC glad_glVertexAttrib3sARB = NULL; +PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL; +PFNGLVERTEXATTRIB3SVARBPROC glad_glVertexAttrib3svARB = NULL; +PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL; +PFNGLVERTEXATTRIB4NBVARBPROC glad_glVertexAttrib4NbvARB = NULL; +PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL; +PFNGLVERTEXATTRIB4NIVARBPROC glad_glVertexAttrib4NivARB = NULL; +PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL; +PFNGLVERTEXATTRIB4NSVARBPROC glad_glVertexAttrib4NsvARB = NULL; +PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL; +PFNGLVERTEXATTRIB4NUBARBPROC glad_glVertexAttrib4NubARB = NULL; +PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL; +PFNGLVERTEXATTRIB4NUBVARBPROC glad_glVertexAttrib4NubvARB = NULL; +PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL; +PFNGLVERTEXATTRIB4NUIVARBPROC glad_glVertexAttrib4NuivARB = NULL; +PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL; +PFNGLVERTEXATTRIB4NUSVARBPROC glad_glVertexAttrib4NusvARB = NULL; +PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL; +PFNGLVERTEXATTRIB4BVARBPROC glad_glVertexAttrib4bvARB = NULL; +PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL; +PFNGLVERTEXATTRIB4DARBPROC glad_glVertexAttrib4dARB = NULL; +PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL; +PFNGLVERTEXATTRIB4DVARBPROC glad_glVertexAttrib4dvARB = NULL; +PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL; +PFNGLVERTEXATTRIB4FARBPROC glad_glVertexAttrib4fARB = NULL; +PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL; +PFNGLVERTEXATTRIB4FVARBPROC glad_glVertexAttrib4fvARB = NULL; +PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL; +PFNGLVERTEXATTRIB4IVARBPROC glad_glVertexAttrib4ivARB = NULL; +PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL; +PFNGLVERTEXATTRIB4SARBPROC glad_glVertexAttrib4sARB = NULL; +PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL; +PFNGLVERTEXATTRIB4SVARBPROC glad_glVertexAttrib4svARB = NULL; +PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL; +PFNGLVERTEXATTRIB4UBVARBPROC glad_glVertexAttrib4ubvARB = NULL; +PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL; +PFNGLVERTEXATTRIB4UIVARBPROC glad_glVertexAttrib4uivARB = NULL; +PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL; +PFNGLVERTEXATTRIB4USVARBPROC glad_glVertexAttrib4usvARB = NULL; +PFNGLVERTEXATTRIBBINDINGPROC glad_glVertexAttribBinding = NULL; +PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL; +PFNGLVERTEXATTRIBFORMATPROC glad_glVertexAttribFormat = NULL; +PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL; +PFNGLVERTEXATTRIBI1IEXTPROC glad_glVertexAttribI1iEXT = NULL; +PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL; +PFNGLVERTEXATTRIBI1IVEXTPROC glad_glVertexAttribI1ivEXT = NULL; +PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL; +PFNGLVERTEXATTRIBI1UIEXTPROC glad_glVertexAttribI1uiEXT = NULL; +PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL; +PFNGLVERTEXATTRIBI1UIVEXTPROC glad_glVertexAttribI1uivEXT = NULL; +PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL; +PFNGLVERTEXATTRIBI2IEXTPROC glad_glVertexAttribI2iEXT = NULL; +PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL; +PFNGLVERTEXATTRIBI2IVEXTPROC glad_glVertexAttribI2ivEXT = NULL; +PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL; +PFNGLVERTEXATTRIBI2UIEXTPROC glad_glVertexAttribI2uiEXT = NULL; +PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL; +PFNGLVERTEXATTRIBI2UIVEXTPROC glad_glVertexAttribI2uivEXT = NULL; +PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL; +PFNGLVERTEXATTRIBI3IEXTPROC glad_glVertexAttribI3iEXT = NULL; +PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL; +PFNGLVERTEXATTRIBI3IVEXTPROC glad_glVertexAttribI3ivEXT = NULL; +PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL; +PFNGLVERTEXATTRIBI3UIEXTPROC glad_glVertexAttribI3uiEXT = NULL; +PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL; +PFNGLVERTEXATTRIBI3UIVEXTPROC glad_glVertexAttribI3uivEXT = NULL; +PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL; +PFNGLVERTEXATTRIBI4BVEXTPROC glad_glVertexAttribI4bvEXT = NULL; +PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL; +PFNGLVERTEXATTRIBI4IEXTPROC glad_glVertexAttribI4iEXT = NULL; +PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL; +PFNGLVERTEXATTRIBI4IVEXTPROC glad_glVertexAttribI4ivEXT = NULL; +PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL; +PFNGLVERTEXATTRIBI4SVEXTPROC glad_glVertexAttribI4svEXT = NULL; +PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL; +PFNGLVERTEXATTRIBI4UBVEXTPROC glad_glVertexAttribI4ubvEXT = NULL; +PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL; +PFNGLVERTEXATTRIBI4UIEXTPROC glad_glVertexAttribI4uiEXT = NULL; +PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL; +PFNGLVERTEXATTRIBI4UIVEXTPROC glad_glVertexAttribI4uivEXT = NULL; +PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL; +PFNGLVERTEXATTRIBI4USVEXTPROC glad_glVertexAttribI4usvEXT = NULL; +PFNGLVERTEXATTRIBIFORMATPROC glad_glVertexAttribIFormat = NULL; +PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL; +PFNGLVERTEXATTRIBIPOINTEREXTPROC glad_glVertexAttribIPointerEXT = NULL; +PFNGLVERTEXATTRIBL1DPROC glad_glVertexAttribL1d = NULL; +PFNGLVERTEXATTRIBL1DVPROC glad_glVertexAttribL1dv = NULL; +PFNGLVERTEXATTRIBL2DPROC glad_glVertexAttribL2d = NULL; +PFNGLVERTEXATTRIBL2DVPROC glad_glVertexAttribL2dv = NULL; +PFNGLVERTEXATTRIBL3DPROC glad_glVertexAttribL3d = NULL; +PFNGLVERTEXATTRIBL3DVPROC glad_glVertexAttribL3dv = NULL; +PFNGLVERTEXATTRIBL4DPROC glad_glVertexAttribL4d = NULL; +PFNGLVERTEXATTRIBL4DVPROC glad_glVertexAttribL4dv = NULL; +PFNGLVERTEXATTRIBLFORMATPROC glad_glVertexAttribLFormat = NULL; +PFNGLVERTEXATTRIBLPOINTERPROC glad_glVertexAttribLPointer = NULL; +PFNGLVERTEXATTRIBP1UIPROC glad_glVertexAttribP1ui = NULL; +PFNGLVERTEXATTRIBP1UIVPROC glad_glVertexAttribP1uiv = NULL; +PFNGLVERTEXATTRIBP2UIPROC glad_glVertexAttribP2ui = NULL; +PFNGLVERTEXATTRIBP2UIVPROC glad_glVertexAttribP2uiv = NULL; +PFNGLVERTEXATTRIBP3UIPROC glad_glVertexAttribP3ui = NULL; +PFNGLVERTEXATTRIBP3UIVPROC glad_glVertexAttribP3uiv = NULL; +PFNGLVERTEXATTRIBP4UIPROC glad_glVertexAttribP4ui = NULL; +PFNGLVERTEXATTRIBP4UIVPROC glad_glVertexAttribP4uiv = NULL; +PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL; +PFNGLVERTEXATTRIBPOINTERARBPROC glad_glVertexAttribPointerARB = NULL; +PFNGLVERTEXBINDINGDIVISORPROC glad_glVertexBindingDivisor = NULL; +PFNGLVERTEXP2UIPROC glad_glVertexP2ui = NULL; +PFNGLVERTEXP2UIVPROC glad_glVertexP2uiv = NULL; +PFNGLVERTEXP3UIPROC glad_glVertexP3ui = NULL; +PFNGLVERTEXP3UIVPROC glad_glVertexP3uiv = NULL; +PFNGLVERTEXP4UIPROC glad_glVertexP4ui = NULL; +PFNGLVERTEXP4UIVPROC glad_glVertexP4uiv = NULL; +PFNGLVERTEXPOINTERPROC glad_glVertexPointer = NULL; +PFNGLVIEWPORTPROC glad_glViewport = NULL; +PFNGLVIEWPORTARRAYVPROC glad_glViewportArrayv = NULL; +PFNGLVIEWPORTINDEXEDFPROC glad_glViewportIndexedf = NULL; +PFNGLVIEWPORTINDEXEDFVPROC glad_glViewportIndexedfv = NULL; +PFNGLWAITSYNCPROC glad_glWaitSync = NULL; +PFNGLWINDOWPOS2DPROC glad_glWindowPos2d = NULL; +PFNGLWINDOWPOS2DVPROC glad_glWindowPos2dv = NULL; +PFNGLWINDOWPOS2FPROC glad_glWindowPos2f = NULL; +PFNGLWINDOWPOS2FVPROC glad_glWindowPos2fv = NULL; +PFNGLWINDOWPOS2IPROC glad_glWindowPos2i = NULL; +PFNGLWINDOWPOS2IVPROC glad_glWindowPos2iv = NULL; +PFNGLWINDOWPOS2SPROC glad_glWindowPos2s = NULL; +PFNGLWINDOWPOS2SVPROC glad_glWindowPos2sv = NULL; +PFNGLWINDOWPOS3DPROC glad_glWindowPos3d = NULL; +PFNGLWINDOWPOS3DVPROC glad_glWindowPos3dv = NULL; +PFNGLWINDOWPOS3FPROC glad_glWindowPos3f = NULL; +PFNGLWINDOWPOS3FVPROC glad_glWindowPos3fv = NULL; +PFNGLWINDOWPOS3IPROC glad_glWindowPos3i = NULL; +PFNGLWINDOWPOS3IVPROC glad_glWindowPos3iv = NULL; +PFNGLWINDOWPOS3SPROC glad_glWindowPos3s = NULL; +PFNGLWINDOWPOS3SVPROC glad_glWindowPos3sv = NULL; + + +static void glad_gl_load_GL_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_1_0) return; + glad_glAccum = (PFNGLACCUMPROC) load(userptr, "glAccum"); + glad_glAlphaFunc = (PFNGLALPHAFUNCPROC) load(userptr, "glAlphaFunc"); + glad_glBegin = (PFNGLBEGINPROC) load(userptr, "glBegin"); + glad_glBitmap = (PFNGLBITMAPPROC) load(userptr, "glBitmap"); + glad_glBlendFunc = (PFNGLBLENDFUNCPROC) load(userptr, "glBlendFunc"); + glad_glCallList = (PFNGLCALLLISTPROC) load(userptr, "glCallList"); + glad_glCallLists = (PFNGLCALLLISTSPROC) load(userptr, "glCallLists"); + glad_glClear = (PFNGLCLEARPROC) load(userptr, "glClear"); + glad_glClearAccum = (PFNGLCLEARACCUMPROC) load(userptr, "glClearAccum"); + glad_glClearColor = (PFNGLCLEARCOLORPROC) load(userptr, "glClearColor"); + glad_glClearDepth = (PFNGLCLEARDEPTHPROC) load(userptr, "glClearDepth"); + glad_glClearIndex = (PFNGLCLEARINDEXPROC) load(userptr, "glClearIndex"); + glad_glClearStencil = (PFNGLCLEARSTENCILPROC) load(userptr, "glClearStencil"); + glad_glClipPlane = (PFNGLCLIPPLANEPROC) load(userptr, "glClipPlane"); + glad_glColor3b = (PFNGLCOLOR3BPROC) load(userptr, "glColor3b"); + glad_glColor3bv = (PFNGLCOLOR3BVPROC) load(userptr, "glColor3bv"); + glad_glColor3d = (PFNGLCOLOR3DPROC) load(userptr, "glColor3d"); + glad_glColor3dv = (PFNGLCOLOR3DVPROC) load(userptr, "glColor3dv"); + glad_glColor3f = (PFNGLCOLOR3FPROC) load(userptr, "glColor3f"); + glad_glColor3fv = (PFNGLCOLOR3FVPROC) load(userptr, "glColor3fv"); + glad_glColor3i = (PFNGLCOLOR3IPROC) load(userptr, "glColor3i"); + glad_glColor3iv = (PFNGLCOLOR3IVPROC) load(userptr, "glColor3iv"); + glad_glColor3s = (PFNGLCOLOR3SPROC) load(userptr, "glColor3s"); + glad_glColor3sv = (PFNGLCOLOR3SVPROC) load(userptr, "glColor3sv"); + glad_glColor3ub = (PFNGLCOLOR3UBPROC) load(userptr, "glColor3ub"); + glad_glColor3ubv = (PFNGLCOLOR3UBVPROC) load(userptr, "glColor3ubv"); + glad_glColor3ui = (PFNGLCOLOR3UIPROC) load(userptr, "glColor3ui"); + glad_glColor3uiv = (PFNGLCOLOR3UIVPROC) load(userptr, "glColor3uiv"); + glad_glColor3us = (PFNGLCOLOR3USPROC) load(userptr, "glColor3us"); + glad_glColor3usv = (PFNGLCOLOR3USVPROC) load(userptr, "glColor3usv"); + glad_glColor4b = (PFNGLCOLOR4BPROC) load(userptr, "glColor4b"); + glad_glColor4bv = (PFNGLCOLOR4BVPROC) load(userptr, "glColor4bv"); + glad_glColor4d = (PFNGLCOLOR4DPROC) load(userptr, "glColor4d"); + glad_glColor4dv = (PFNGLCOLOR4DVPROC) load(userptr, "glColor4dv"); + glad_glColor4f = (PFNGLCOLOR4FPROC) load(userptr, "glColor4f"); + glad_glColor4fv = (PFNGLCOLOR4FVPROC) load(userptr, "glColor4fv"); + glad_glColor4i = (PFNGLCOLOR4IPROC) load(userptr, "glColor4i"); + glad_glColor4iv = (PFNGLCOLOR4IVPROC) load(userptr, "glColor4iv"); + glad_glColor4s = (PFNGLCOLOR4SPROC) load(userptr, "glColor4s"); + glad_glColor4sv = (PFNGLCOLOR4SVPROC) load(userptr, "glColor4sv"); + glad_glColor4ub = (PFNGLCOLOR4UBPROC) load(userptr, "glColor4ub"); + glad_glColor4ubv = (PFNGLCOLOR4UBVPROC) load(userptr, "glColor4ubv"); + glad_glColor4ui = (PFNGLCOLOR4UIPROC) load(userptr, "glColor4ui"); + glad_glColor4uiv = (PFNGLCOLOR4UIVPROC) load(userptr, "glColor4uiv"); + glad_glColor4us = (PFNGLCOLOR4USPROC) load(userptr, "glColor4us"); + glad_glColor4usv = (PFNGLCOLOR4USVPROC) load(userptr, "glColor4usv"); + glad_glColorMask = (PFNGLCOLORMASKPROC) load(userptr, "glColorMask"); + glad_glColorMaterial = (PFNGLCOLORMATERIALPROC) load(userptr, "glColorMaterial"); + glad_glCopyPixels = (PFNGLCOPYPIXELSPROC) load(userptr, "glCopyPixels"); + glad_glCullFace = (PFNGLCULLFACEPROC) load(userptr, "glCullFace"); + glad_glDeleteLists = (PFNGLDELETELISTSPROC) load(userptr, "glDeleteLists"); + glad_glDepthFunc = (PFNGLDEPTHFUNCPROC) load(userptr, "glDepthFunc"); + glad_glDepthMask = (PFNGLDEPTHMASKPROC) load(userptr, "glDepthMask"); + glad_glDepthRange = (PFNGLDEPTHRANGEPROC) load(userptr, "glDepthRange"); + glad_glDisable = (PFNGLDISABLEPROC) load(userptr, "glDisable"); + glad_glDrawBuffer = (PFNGLDRAWBUFFERPROC) load(userptr, "glDrawBuffer"); + glad_glDrawPixels = (PFNGLDRAWPIXELSPROC) load(userptr, "glDrawPixels"); + glad_glEdgeFlag = (PFNGLEDGEFLAGPROC) load(userptr, "glEdgeFlag"); + glad_glEdgeFlagv = (PFNGLEDGEFLAGVPROC) load(userptr, "glEdgeFlagv"); + glad_glEnable = (PFNGLENABLEPROC) load(userptr, "glEnable"); + glad_glEnd = (PFNGLENDPROC) load(userptr, "glEnd"); + glad_glEndList = (PFNGLENDLISTPROC) load(userptr, "glEndList"); + glad_glEvalCoord1d = (PFNGLEVALCOORD1DPROC) load(userptr, "glEvalCoord1d"); + glad_glEvalCoord1dv = (PFNGLEVALCOORD1DVPROC) load(userptr, "glEvalCoord1dv"); + glad_glEvalCoord1f = (PFNGLEVALCOORD1FPROC) load(userptr, "glEvalCoord1f"); + glad_glEvalCoord1fv = (PFNGLEVALCOORD1FVPROC) load(userptr, "glEvalCoord1fv"); + glad_glEvalCoord2d = (PFNGLEVALCOORD2DPROC) load(userptr, "glEvalCoord2d"); + glad_glEvalCoord2dv = (PFNGLEVALCOORD2DVPROC) load(userptr, "glEvalCoord2dv"); + glad_glEvalCoord2f = (PFNGLEVALCOORD2FPROC) load(userptr, "glEvalCoord2f"); + glad_glEvalCoord2fv = (PFNGLEVALCOORD2FVPROC) load(userptr, "glEvalCoord2fv"); + glad_glEvalMesh1 = (PFNGLEVALMESH1PROC) load(userptr, "glEvalMesh1"); + glad_glEvalMesh2 = (PFNGLEVALMESH2PROC) load(userptr, "glEvalMesh2"); + glad_glEvalPoint1 = (PFNGLEVALPOINT1PROC) load(userptr, "glEvalPoint1"); + glad_glEvalPoint2 = (PFNGLEVALPOINT2PROC) load(userptr, "glEvalPoint2"); + glad_glFeedbackBuffer = (PFNGLFEEDBACKBUFFERPROC) load(userptr, "glFeedbackBuffer"); + glad_glFinish = (PFNGLFINISHPROC) load(userptr, "glFinish"); + glad_glFlush = (PFNGLFLUSHPROC) load(userptr, "glFlush"); + glad_glFogf = (PFNGLFOGFPROC) load(userptr, "glFogf"); + glad_glFogfv = (PFNGLFOGFVPROC) load(userptr, "glFogfv"); + glad_glFogi = (PFNGLFOGIPROC) load(userptr, "glFogi"); + glad_glFogiv = (PFNGLFOGIVPROC) load(userptr, "glFogiv"); + glad_glFrontFace = (PFNGLFRONTFACEPROC) load(userptr, "glFrontFace"); + glad_glFrustum = (PFNGLFRUSTUMPROC) load(userptr, "glFrustum"); + glad_glGenLists = (PFNGLGENLISTSPROC) load(userptr, "glGenLists"); + glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC) load(userptr, "glGetBooleanv"); + glad_glGetClipPlane = (PFNGLGETCLIPPLANEPROC) load(userptr, "glGetClipPlane"); + glad_glGetDoublev = (PFNGLGETDOUBLEVPROC) load(userptr, "glGetDoublev"); + glad_glGetError = (PFNGLGETERRORPROC) load(userptr, "glGetError"); + glad_glGetFloatv = (PFNGLGETFLOATVPROC) load(userptr, "glGetFloatv"); + glad_glGetIntegerv = (PFNGLGETINTEGERVPROC) load(userptr, "glGetIntegerv"); + glad_glGetLightfv = (PFNGLGETLIGHTFVPROC) load(userptr, "glGetLightfv"); + glad_glGetLightiv = (PFNGLGETLIGHTIVPROC) load(userptr, "glGetLightiv"); + glad_glGetMapdv = (PFNGLGETMAPDVPROC) load(userptr, "glGetMapdv"); + glad_glGetMapfv = (PFNGLGETMAPFVPROC) load(userptr, "glGetMapfv"); + glad_glGetMapiv = (PFNGLGETMAPIVPROC) load(userptr, "glGetMapiv"); + glad_glGetMaterialfv = (PFNGLGETMATERIALFVPROC) load(userptr, "glGetMaterialfv"); + glad_glGetMaterialiv = (PFNGLGETMATERIALIVPROC) load(userptr, "glGetMaterialiv"); + glad_glGetPixelMapfv = (PFNGLGETPIXELMAPFVPROC) load(userptr, "glGetPixelMapfv"); + glad_glGetPixelMapuiv = (PFNGLGETPIXELMAPUIVPROC) load(userptr, "glGetPixelMapuiv"); + glad_glGetPixelMapusv = (PFNGLGETPIXELMAPUSVPROC) load(userptr, "glGetPixelMapusv"); + glad_glGetPolygonStipple = (PFNGLGETPOLYGONSTIPPLEPROC) load(userptr, "glGetPolygonStipple"); + glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString"); + glad_glGetTexEnvfv = (PFNGLGETTEXENVFVPROC) load(userptr, "glGetTexEnvfv"); + glad_glGetTexEnviv = (PFNGLGETTEXENVIVPROC) load(userptr, "glGetTexEnviv"); + glad_glGetTexGendv = (PFNGLGETTEXGENDVPROC) load(userptr, "glGetTexGendv"); + glad_glGetTexGenfv = (PFNGLGETTEXGENFVPROC) load(userptr, "glGetTexGenfv"); + glad_glGetTexGeniv = (PFNGLGETTEXGENIVPROC) load(userptr, "glGetTexGeniv"); + glad_glGetTexImage = (PFNGLGETTEXIMAGEPROC) load(userptr, "glGetTexImage"); + glad_glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC) load(userptr, "glGetTexLevelParameterfv"); + glad_glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC) load(userptr, "glGetTexLevelParameteriv"); + glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load(userptr, "glGetTexParameterfv"); + glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load(userptr, "glGetTexParameteriv"); + glad_glHint = (PFNGLHINTPROC) load(userptr, "glHint"); + glad_glIndexMask = (PFNGLINDEXMASKPROC) load(userptr, "glIndexMask"); + glad_glIndexd = (PFNGLINDEXDPROC) load(userptr, "glIndexd"); + glad_glIndexdv = (PFNGLINDEXDVPROC) load(userptr, "glIndexdv"); + glad_glIndexf = (PFNGLINDEXFPROC) load(userptr, "glIndexf"); + glad_glIndexfv = (PFNGLINDEXFVPROC) load(userptr, "glIndexfv"); + glad_glIndexi = (PFNGLINDEXIPROC) load(userptr, "glIndexi"); + glad_glIndexiv = (PFNGLINDEXIVPROC) load(userptr, "glIndexiv"); + glad_glIndexs = (PFNGLINDEXSPROC) load(userptr, "glIndexs"); + glad_glIndexsv = (PFNGLINDEXSVPROC) load(userptr, "glIndexsv"); + glad_glInitNames = (PFNGLINITNAMESPROC) load(userptr, "glInitNames"); + glad_glIsEnabled = (PFNGLISENABLEDPROC) load(userptr, "glIsEnabled"); + glad_glIsList = (PFNGLISLISTPROC) load(userptr, "glIsList"); + glad_glLightModelf = (PFNGLLIGHTMODELFPROC) load(userptr, "glLightModelf"); + glad_glLightModelfv = (PFNGLLIGHTMODELFVPROC) load(userptr, "glLightModelfv"); + glad_glLightModeli = (PFNGLLIGHTMODELIPROC) load(userptr, "glLightModeli"); + glad_glLightModeliv = (PFNGLLIGHTMODELIVPROC) load(userptr, "glLightModeliv"); + glad_glLightf = (PFNGLLIGHTFPROC) load(userptr, "glLightf"); + glad_glLightfv = (PFNGLLIGHTFVPROC) load(userptr, "glLightfv"); + glad_glLighti = (PFNGLLIGHTIPROC) load(userptr, "glLighti"); + glad_glLightiv = (PFNGLLIGHTIVPROC) load(userptr, "glLightiv"); + glad_glLineStipple = (PFNGLLINESTIPPLEPROC) load(userptr, "glLineStipple"); + glad_glLineWidth = (PFNGLLINEWIDTHPROC) load(userptr, "glLineWidth"); + glad_glListBase = (PFNGLLISTBASEPROC) load(userptr, "glListBase"); + glad_glLoadIdentity = (PFNGLLOADIDENTITYPROC) load(userptr, "glLoadIdentity"); + glad_glLoadMatrixd = (PFNGLLOADMATRIXDPROC) load(userptr, "glLoadMatrixd"); + glad_glLoadMatrixf = (PFNGLLOADMATRIXFPROC) load(userptr, "glLoadMatrixf"); + glad_glLoadName = (PFNGLLOADNAMEPROC) load(userptr, "glLoadName"); + glad_glLogicOp = (PFNGLLOGICOPPROC) load(userptr, "glLogicOp"); + glad_glMap1d = (PFNGLMAP1DPROC) load(userptr, "glMap1d"); + glad_glMap1f = (PFNGLMAP1FPROC) load(userptr, "glMap1f"); + glad_glMap2d = (PFNGLMAP2DPROC) load(userptr, "glMap2d"); + glad_glMap2f = (PFNGLMAP2FPROC) load(userptr, "glMap2f"); + glad_glMapGrid1d = (PFNGLMAPGRID1DPROC) load(userptr, "glMapGrid1d"); + glad_glMapGrid1f = (PFNGLMAPGRID1FPROC) load(userptr, "glMapGrid1f"); + glad_glMapGrid2d = (PFNGLMAPGRID2DPROC) load(userptr, "glMapGrid2d"); + glad_glMapGrid2f = (PFNGLMAPGRID2FPROC) load(userptr, "glMapGrid2f"); + glad_glMaterialf = (PFNGLMATERIALFPROC) load(userptr, "glMaterialf"); + glad_glMaterialfv = (PFNGLMATERIALFVPROC) load(userptr, "glMaterialfv"); + glad_glMateriali = (PFNGLMATERIALIPROC) load(userptr, "glMateriali"); + glad_glMaterialiv = (PFNGLMATERIALIVPROC) load(userptr, "glMaterialiv"); + glad_glMatrixMode = (PFNGLMATRIXMODEPROC) load(userptr, "glMatrixMode"); + glad_glMultMatrixd = (PFNGLMULTMATRIXDPROC) load(userptr, "glMultMatrixd"); + glad_glMultMatrixf = (PFNGLMULTMATRIXFPROC) load(userptr, "glMultMatrixf"); + glad_glNewList = (PFNGLNEWLISTPROC) load(userptr, "glNewList"); + glad_glNormal3b = (PFNGLNORMAL3BPROC) load(userptr, "glNormal3b"); + glad_glNormal3bv = (PFNGLNORMAL3BVPROC) load(userptr, "glNormal3bv"); + glad_glNormal3d = (PFNGLNORMAL3DPROC) load(userptr, "glNormal3d"); + glad_glNormal3dv = (PFNGLNORMAL3DVPROC) load(userptr, "glNormal3dv"); + glad_glNormal3f = (PFNGLNORMAL3FPROC) load(userptr, "glNormal3f"); + glad_glNormal3fv = (PFNGLNORMAL3FVPROC) load(userptr, "glNormal3fv"); + glad_glNormal3i = (PFNGLNORMAL3IPROC) load(userptr, "glNormal3i"); + glad_glNormal3iv = (PFNGLNORMAL3IVPROC) load(userptr, "glNormal3iv"); + glad_glNormal3s = (PFNGLNORMAL3SPROC) load(userptr, "glNormal3s"); + glad_glNormal3sv = (PFNGLNORMAL3SVPROC) load(userptr, "glNormal3sv"); + glad_glOrtho = (PFNGLORTHOPROC) load(userptr, "glOrtho"); + glad_glPassThrough = (PFNGLPASSTHROUGHPROC) load(userptr, "glPassThrough"); + glad_glPixelMapfv = (PFNGLPIXELMAPFVPROC) load(userptr, "glPixelMapfv"); + glad_glPixelMapuiv = (PFNGLPIXELMAPUIVPROC) load(userptr, "glPixelMapuiv"); + glad_glPixelMapusv = (PFNGLPIXELMAPUSVPROC) load(userptr, "glPixelMapusv"); + glad_glPixelStoref = (PFNGLPIXELSTOREFPROC) load(userptr, "glPixelStoref"); + glad_glPixelStorei = (PFNGLPIXELSTOREIPROC) load(userptr, "glPixelStorei"); + glad_glPixelTransferf = (PFNGLPIXELTRANSFERFPROC) load(userptr, "glPixelTransferf"); + glad_glPixelTransferi = (PFNGLPIXELTRANSFERIPROC) load(userptr, "glPixelTransferi"); + glad_glPixelZoom = (PFNGLPIXELZOOMPROC) load(userptr, "glPixelZoom"); + glad_glPointSize = (PFNGLPOINTSIZEPROC) load(userptr, "glPointSize"); + glad_glPolygonMode = (PFNGLPOLYGONMODEPROC) load(userptr, "glPolygonMode"); + glad_glPolygonStipple = (PFNGLPOLYGONSTIPPLEPROC) load(userptr, "glPolygonStipple"); + glad_glPopAttrib = (PFNGLPOPATTRIBPROC) load(userptr, "glPopAttrib"); + glad_glPopMatrix = (PFNGLPOPMATRIXPROC) load(userptr, "glPopMatrix"); + glad_glPopName = (PFNGLPOPNAMEPROC) load(userptr, "glPopName"); + glad_glPushAttrib = (PFNGLPUSHATTRIBPROC) load(userptr, "glPushAttrib"); + glad_glPushMatrix = (PFNGLPUSHMATRIXPROC) load(userptr, "glPushMatrix"); + glad_glPushName = (PFNGLPUSHNAMEPROC) load(userptr, "glPushName"); + glad_glRasterPos2d = (PFNGLRASTERPOS2DPROC) load(userptr, "glRasterPos2d"); + glad_glRasterPos2dv = (PFNGLRASTERPOS2DVPROC) load(userptr, "glRasterPos2dv"); + glad_glRasterPos2f = (PFNGLRASTERPOS2FPROC) load(userptr, "glRasterPos2f"); + glad_glRasterPos2fv = (PFNGLRASTERPOS2FVPROC) load(userptr, "glRasterPos2fv"); + glad_glRasterPos2i = (PFNGLRASTERPOS2IPROC) load(userptr, "glRasterPos2i"); + glad_glRasterPos2iv = (PFNGLRASTERPOS2IVPROC) load(userptr, "glRasterPos2iv"); + glad_glRasterPos2s = (PFNGLRASTERPOS2SPROC) load(userptr, "glRasterPos2s"); + glad_glRasterPos2sv = (PFNGLRASTERPOS2SVPROC) load(userptr, "glRasterPos2sv"); + glad_glRasterPos3d = (PFNGLRASTERPOS3DPROC) load(userptr, "glRasterPos3d"); + glad_glRasterPos3dv = (PFNGLRASTERPOS3DVPROC) load(userptr, "glRasterPos3dv"); + glad_glRasterPos3f = (PFNGLRASTERPOS3FPROC) load(userptr, "glRasterPos3f"); + glad_glRasterPos3fv = (PFNGLRASTERPOS3FVPROC) load(userptr, "glRasterPos3fv"); + glad_glRasterPos3i = (PFNGLRASTERPOS3IPROC) load(userptr, "glRasterPos3i"); + glad_glRasterPos3iv = (PFNGLRASTERPOS3IVPROC) load(userptr, "glRasterPos3iv"); + glad_glRasterPos3s = (PFNGLRASTERPOS3SPROC) load(userptr, "glRasterPos3s"); + glad_glRasterPos3sv = (PFNGLRASTERPOS3SVPROC) load(userptr, "glRasterPos3sv"); + glad_glRasterPos4d = (PFNGLRASTERPOS4DPROC) load(userptr, "glRasterPos4d"); + glad_glRasterPos4dv = (PFNGLRASTERPOS4DVPROC) load(userptr, "glRasterPos4dv"); + glad_glRasterPos4f = (PFNGLRASTERPOS4FPROC) load(userptr, "glRasterPos4f"); + glad_glRasterPos4fv = (PFNGLRASTERPOS4FVPROC) load(userptr, "glRasterPos4fv"); + glad_glRasterPos4i = (PFNGLRASTERPOS4IPROC) load(userptr, "glRasterPos4i"); + glad_glRasterPos4iv = (PFNGLRASTERPOS4IVPROC) load(userptr, "glRasterPos4iv"); + glad_glRasterPos4s = (PFNGLRASTERPOS4SPROC) load(userptr, "glRasterPos4s"); + glad_glRasterPos4sv = (PFNGLRASTERPOS4SVPROC) load(userptr, "glRasterPos4sv"); + glad_glReadBuffer = (PFNGLREADBUFFERPROC) load(userptr, "glReadBuffer"); + glad_glReadPixels = (PFNGLREADPIXELSPROC) load(userptr, "glReadPixels"); + glad_glRectd = (PFNGLRECTDPROC) load(userptr, "glRectd"); + glad_glRectdv = (PFNGLRECTDVPROC) load(userptr, "glRectdv"); + glad_glRectf = (PFNGLRECTFPROC) load(userptr, "glRectf"); + glad_glRectfv = (PFNGLRECTFVPROC) load(userptr, "glRectfv"); + glad_glRecti = (PFNGLRECTIPROC) load(userptr, "glRecti"); + glad_glRectiv = (PFNGLRECTIVPROC) load(userptr, "glRectiv"); + glad_glRects = (PFNGLRECTSPROC) load(userptr, "glRects"); + glad_glRectsv = (PFNGLRECTSVPROC) load(userptr, "glRectsv"); + glad_glRenderMode = (PFNGLRENDERMODEPROC) load(userptr, "glRenderMode"); + glad_glRotated = (PFNGLROTATEDPROC) load(userptr, "glRotated"); + glad_glRotatef = (PFNGLROTATEFPROC) load(userptr, "glRotatef"); + glad_glScaled = (PFNGLSCALEDPROC) load(userptr, "glScaled"); + glad_glScalef = (PFNGLSCALEFPROC) load(userptr, "glScalef"); + glad_glScissor = (PFNGLSCISSORPROC) load(userptr, "glScissor"); + glad_glSelectBuffer = (PFNGLSELECTBUFFERPROC) load(userptr, "glSelectBuffer"); + glad_glShadeModel = (PFNGLSHADEMODELPROC) load(userptr, "glShadeModel"); + glad_glStencilFunc = (PFNGLSTENCILFUNCPROC) load(userptr, "glStencilFunc"); + glad_glStencilMask = (PFNGLSTENCILMASKPROC) load(userptr, "glStencilMask"); + glad_glStencilOp = (PFNGLSTENCILOPPROC) load(userptr, "glStencilOp"); + glad_glTexCoord1d = (PFNGLTEXCOORD1DPROC) load(userptr, "glTexCoord1d"); + glad_glTexCoord1dv = (PFNGLTEXCOORD1DVPROC) load(userptr, "glTexCoord1dv"); + glad_glTexCoord1f = (PFNGLTEXCOORD1FPROC) load(userptr, "glTexCoord1f"); + glad_glTexCoord1fv = (PFNGLTEXCOORD1FVPROC) load(userptr, "glTexCoord1fv"); + glad_glTexCoord1i = (PFNGLTEXCOORD1IPROC) load(userptr, "glTexCoord1i"); + glad_glTexCoord1iv = (PFNGLTEXCOORD1IVPROC) load(userptr, "glTexCoord1iv"); + glad_glTexCoord1s = (PFNGLTEXCOORD1SPROC) load(userptr, "glTexCoord1s"); + glad_glTexCoord1sv = (PFNGLTEXCOORD1SVPROC) load(userptr, "glTexCoord1sv"); + glad_glTexCoord2d = (PFNGLTEXCOORD2DPROC) load(userptr, "glTexCoord2d"); + glad_glTexCoord2dv = (PFNGLTEXCOORD2DVPROC) load(userptr, "glTexCoord2dv"); + glad_glTexCoord2f = (PFNGLTEXCOORD2FPROC) load(userptr, "glTexCoord2f"); + glad_glTexCoord2fv = (PFNGLTEXCOORD2FVPROC) load(userptr, "glTexCoord2fv"); + glad_glTexCoord2i = (PFNGLTEXCOORD2IPROC) load(userptr, "glTexCoord2i"); + glad_glTexCoord2iv = (PFNGLTEXCOORD2IVPROC) load(userptr, "glTexCoord2iv"); + glad_glTexCoord2s = (PFNGLTEXCOORD2SPROC) load(userptr, "glTexCoord2s"); + glad_glTexCoord2sv = (PFNGLTEXCOORD2SVPROC) load(userptr, "glTexCoord2sv"); + glad_glTexCoord3d = (PFNGLTEXCOORD3DPROC) load(userptr, "glTexCoord3d"); + glad_glTexCoord3dv = (PFNGLTEXCOORD3DVPROC) load(userptr, "glTexCoord3dv"); + glad_glTexCoord3f = (PFNGLTEXCOORD3FPROC) load(userptr, "glTexCoord3f"); + glad_glTexCoord3fv = (PFNGLTEXCOORD3FVPROC) load(userptr, "glTexCoord3fv"); + glad_glTexCoord3i = (PFNGLTEXCOORD3IPROC) load(userptr, "glTexCoord3i"); + glad_glTexCoord3iv = (PFNGLTEXCOORD3IVPROC) load(userptr, "glTexCoord3iv"); + glad_glTexCoord3s = (PFNGLTEXCOORD3SPROC) load(userptr, "glTexCoord3s"); + glad_glTexCoord3sv = (PFNGLTEXCOORD3SVPROC) load(userptr, "glTexCoord3sv"); + glad_glTexCoord4d = (PFNGLTEXCOORD4DPROC) load(userptr, "glTexCoord4d"); + glad_glTexCoord4dv = (PFNGLTEXCOORD4DVPROC) load(userptr, "glTexCoord4dv"); + glad_glTexCoord4f = (PFNGLTEXCOORD4FPROC) load(userptr, "glTexCoord4f"); + glad_glTexCoord4fv = (PFNGLTEXCOORD4FVPROC) load(userptr, "glTexCoord4fv"); + glad_glTexCoord4i = (PFNGLTEXCOORD4IPROC) load(userptr, "glTexCoord4i"); + glad_glTexCoord4iv = (PFNGLTEXCOORD4IVPROC) load(userptr, "glTexCoord4iv"); + glad_glTexCoord4s = (PFNGLTEXCOORD4SPROC) load(userptr, "glTexCoord4s"); + glad_glTexCoord4sv = (PFNGLTEXCOORD4SVPROC) load(userptr, "glTexCoord4sv"); + glad_glTexEnvf = (PFNGLTEXENVFPROC) load(userptr, "glTexEnvf"); + glad_glTexEnvfv = (PFNGLTEXENVFVPROC) load(userptr, "glTexEnvfv"); + glad_glTexEnvi = (PFNGLTEXENVIPROC) load(userptr, "glTexEnvi"); + glad_glTexEnviv = (PFNGLTEXENVIVPROC) load(userptr, "glTexEnviv"); + glad_glTexGend = (PFNGLTEXGENDPROC) load(userptr, "glTexGend"); + glad_glTexGendv = (PFNGLTEXGENDVPROC) load(userptr, "glTexGendv"); + glad_glTexGenf = (PFNGLTEXGENFPROC) load(userptr, "glTexGenf"); + glad_glTexGenfv = (PFNGLTEXGENFVPROC) load(userptr, "glTexGenfv"); + glad_glTexGeni = (PFNGLTEXGENIPROC) load(userptr, "glTexGeni"); + glad_glTexGeniv = (PFNGLTEXGENIVPROC) load(userptr, "glTexGeniv"); + glad_glTexImage1D = (PFNGLTEXIMAGE1DPROC) load(userptr, "glTexImage1D"); + glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC) load(userptr, "glTexImage2D"); + glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC) load(userptr, "glTexParameterf"); + glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC) load(userptr, "glTexParameterfv"); + glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC) load(userptr, "glTexParameteri"); + glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC) load(userptr, "glTexParameteriv"); + glad_glTranslated = (PFNGLTRANSLATEDPROC) load(userptr, "glTranslated"); + glad_glTranslatef = (PFNGLTRANSLATEFPROC) load(userptr, "glTranslatef"); + glad_glVertex2d = (PFNGLVERTEX2DPROC) load(userptr, "glVertex2d"); + glad_glVertex2dv = (PFNGLVERTEX2DVPROC) load(userptr, "glVertex2dv"); + glad_glVertex2f = (PFNGLVERTEX2FPROC) load(userptr, "glVertex2f"); + glad_glVertex2fv = (PFNGLVERTEX2FVPROC) load(userptr, "glVertex2fv"); + glad_glVertex2i = (PFNGLVERTEX2IPROC) load(userptr, "glVertex2i"); + glad_glVertex2iv = (PFNGLVERTEX2IVPROC) load(userptr, "glVertex2iv"); + glad_glVertex2s = (PFNGLVERTEX2SPROC) load(userptr, "glVertex2s"); + glad_glVertex2sv = (PFNGLVERTEX2SVPROC) load(userptr, "glVertex2sv"); + glad_glVertex3d = (PFNGLVERTEX3DPROC) load(userptr, "glVertex3d"); + glad_glVertex3dv = (PFNGLVERTEX3DVPROC) load(userptr, "glVertex3dv"); + glad_glVertex3f = (PFNGLVERTEX3FPROC) load(userptr, "glVertex3f"); + glad_glVertex3fv = (PFNGLVERTEX3FVPROC) load(userptr, "glVertex3fv"); + glad_glVertex3i = (PFNGLVERTEX3IPROC) load(userptr, "glVertex3i"); + glad_glVertex3iv = (PFNGLVERTEX3IVPROC) load(userptr, "glVertex3iv"); + glad_glVertex3s = (PFNGLVERTEX3SPROC) load(userptr, "glVertex3s"); + glad_glVertex3sv = (PFNGLVERTEX3SVPROC) load(userptr, "glVertex3sv"); + glad_glVertex4d = (PFNGLVERTEX4DPROC) load(userptr, "glVertex4d"); + glad_glVertex4dv = (PFNGLVERTEX4DVPROC) load(userptr, "glVertex4dv"); + glad_glVertex4f = (PFNGLVERTEX4FPROC) load(userptr, "glVertex4f"); + glad_glVertex4fv = (PFNGLVERTEX4FVPROC) load(userptr, "glVertex4fv"); + glad_glVertex4i = (PFNGLVERTEX4IPROC) load(userptr, "glVertex4i"); + glad_glVertex4iv = (PFNGLVERTEX4IVPROC) load(userptr, "glVertex4iv"); + glad_glVertex4s = (PFNGLVERTEX4SPROC) load(userptr, "glVertex4s"); + glad_glVertex4sv = (PFNGLVERTEX4SVPROC) load(userptr, "glVertex4sv"); + glad_glViewport = (PFNGLVIEWPORTPROC) load(userptr, "glViewport"); +} +static void glad_gl_load_GL_VERSION_1_1( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_1_1) return; + glad_glAreTexturesResident = (PFNGLARETEXTURESRESIDENTPROC) load(userptr, "glAreTexturesResident"); + glad_glArrayElement = (PFNGLARRAYELEMENTPROC) load(userptr, "glArrayElement"); + glad_glBindTexture = (PFNGLBINDTEXTUREPROC) load(userptr, "glBindTexture"); + glad_glColorPointer = (PFNGLCOLORPOINTERPROC) load(userptr, "glColorPointer"); + glad_glCopyTexImage1D = (PFNGLCOPYTEXIMAGE1DPROC) load(userptr, "glCopyTexImage1D"); + glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load(userptr, "glCopyTexImage2D"); + glad_glCopyTexSubImage1D = (PFNGLCOPYTEXSUBIMAGE1DPROC) load(userptr, "glCopyTexSubImage1D"); + glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load(userptr, "glCopyTexSubImage2D"); + glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC) load(userptr, "glDeleteTextures"); + glad_glDisableClientState = (PFNGLDISABLECLIENTSTATEPROC) load(userptr, "glDisableClientState"); + glad_glDrawArrays = (PFNGLDRAWARRAYSPROC) load(userptr, "glDrawArrays"); + glad_glDrawElements = (PFNGLDRAWELEMENTSPROC) load(userptr, "glDrawElements"); + glad_glEdgeFlagPointer = (PFNGLEDGEFLAGPOINTERPROC) load(userptr, "glEdgeFlagPointer"); + glad_glEnableClientState = (PFNGLENABLECLIENTSTATEPROC) load(userptr, "glEnableClientState"); + glad_glGenTextures = (PFNGLGENTEXTURESPROC) load(userptr, "glGenTextures"); + glad_glGetPointerv = (PFNGLGETPOINTERVPROC) load(userptr, "glGetPointerv"); + glad_glIndexPointer = (PFNGLINDEXPOINTERPROC) load(userptr, "glIndexPointer"); + glad_glIndexub = (PFNGLINDEXUBPROC) load(userptr, "glIndexub"); + glad_glIndexubv = (PFNGLINDEXUBVPROC) load(userptr, "glIndexubv"); + glad_glInterleavedArrays = (PFNGLINTERLEAVEDARRAYSPROC) load(userptr, "glInterleavedArrays"); + glad_glIsTexture = (PFNGLISTEXTUREPROC) load(userptr, "glIsTexture"); + glad_glNormalPointer = (PFNGLNORMALPOINTERPROC) load(userptr, "glNormalPointer"); + glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load(userptr, "glPolygonOffset"); + glad_glPopClientAttrib = (PFNGLPOPCLIENTATTRIBPROC) load(userptr, "glPopClientAttrib"); + glad_glPrioritizeTextures = (PFNGLPRIORITIZETEXTURESPROC) load(userptr, "glPrioritizeTextures"); + glad_glPushClientAttrib = (PFNGLPUSHCLIENTATTRIBPROC) load(userptr, "glPushClientAttrib"); + glad_glTexCoordPointer = (PFNGLTEXCOORDPOINTERPROC) load(userptr, "glTexCoordPointer"); + glad_glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC) load(userptr, "glTexSubImage1D"); + glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load(userptr, "glTexSubImage2D"); + glad_glVertexPointer = (PFNGLVERTEXPOINTERPROC) load(userptr, "glVertexPointer"); +} +static void glad_gl_load_GL_VERSION_1_2( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_1_2) return; + glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) load(userptr, "glCopyTexSubImage3D"); + glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) load(userptr, "glDrawRangeElements"); + glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC) load(userptr, "glTexImage3D"); + glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) load(userptr, "glTexSubImage3D"); +} +static void glad_gl_load_GL_VERSION_1_3( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_1_3) return; + glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC) load(userptr, "glActiveTexture"); + glad_glClientActiveTexture = (PFNGLCLIENTACTIVETEXTUREPROC) load(userptr, "glClientActiveTexture"); + glad_glCompressedTexImage1D = (PFNGLCOMPRESSEDTEXIMAGE1DPROC) load(userptr, "glCompressedTexImage1D"); + glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load(userptr, "glCompressedTexImage2D"); + glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) load(userptr, "glCompressedTexImage3D"); + glad_glCompressedTexSubImage1D = (PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC) load(userptr, "glCompressedTexSubImage1D"); + glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load(userptr, "glCompressedTexSubImage2D"); + glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) load(userptr, "glCompressedTexSubImage3D"); + glad_glGetCompressedTexImage = (PFNGLGETCOMPRESSEDTEXIMAGEPROC) load(userptr, "glGetCompressedTexImage"); + glad_glLoadTransposeMatrixd = (PFNGLLOADTRANSPOSEMATRIXDPROC) load(userptr, "glLoadTransposeMatrixd"); + glad_glLoadTransposeMatrixf = (PFNGLLOADTRANSPOSEMATRIXFPROC) load(userptr, "glLoadTransposeMatrixf"); + glad_glMultTransposeMatrixd = (PFNGLMULTTRANSPOSEMATRIXDPROC) load(userptr, "glMultTransposeMatrixd"); + glad_glMultTransposeMatrixf = (PFNGLMULTTRANSPOSEMATRIXFPROC) load(userptr, "glMultTransposeMatrixf"); + glad_glMultiTexCoord1d = (PFNGLMULTITEXCOORD1DPROC) load(userptr, "glMultiTexCoord1d"); + glad_glMultiTexCoord1dv = (PFNGLMULTITEXCOORD1DVPROC) load(userptr, "glMultiTexCoord1dv"); + glad_glMultiTexCoord1f = (PFNGLMULTITEXCOORD1FPROC) load(userptr, "glMultiTexCoord1f"); + glad_glMultiTexCoord1fv = (PFNGLMULTITEXCOORD1FVPROC) load(userptr, "glMultiTexCoord1fv"); + glad_glMultiTexCoord1i = (PFNGLMULTITEXCOORD1IPROC) load(userptr, "glMultiTexCoord1i"); + glad_glMultiTexCoord1iv = (PFNGLMULTITEXCOORD1IVPROC) load(userptr, "glMultiTexCoord1iv"); + glad_glMultiTexCoord1s = (PFNGLMULTITEXCOORD1SPROC) load(userptr, "glMultiTexCoord1s"); + glad_glMultiTexCoord1sv = (PFNGLMULTITEXCOORD1SVPROC) load(userptr, "glMultiTexCoord1sv"); + glad_glMultiTexCoord2d = (PFNGLMULTITEXCOORD2DPROC) load(userptr, "glMultiTexCoord2d"); + glad_glMultiTexCoord2dv = (PFNGLMULTITEXCOORD2DVPROC) load(userptr, "glMultiTexCoord2dv"); + glad_glMultiTexCoord2f = (PFNGLMULTITEXCOORD2FPROC) load(userptr, "glMultiTexCoord2f"); + glad_glMultiTexCoord2fv = (PFNGLMULTITEXCOORD2FVPROC) load(userptr, "glMultiTexCoord2fv"); + glad_glMultiTexCoord2i = (PFNGLMULTITEXCOORD2IPROC) load(userptr, "glMultiTexCoord2i"); + glad_glMultiTexCoord2iv = (PFNGLMULTITEXCOORD2IVPROC) load(userptr, "glMultiTexCoord2iv"); + glad_glMultiTexCoord2s = (PFNGLMULTITEXCOORD2SPROC) load(userptr, "glMultiTexCoord2s"); + glad_glMultiTexCoord2sv = (PFNGLMULTITEXCOORD2SVPROC) load(userptr, "glMultiTexCoord2sv"); + glad_glMultiTexCoord3d = (PFNGLMULTITEXCOORD3DPROC) load(userptr, "glMultiTexCoord3d"); + glad_glMultiTexCoord3dv = (PFNGLMULTITEXCOORD3DVPROC) load(userptr, "glMultiTexCoord3dv"); + glad_glMultiTexCoord3f = (PFNGLMULTITEXCOORD3FPROC) load(userptr, "glMultiTexCoord3f"); + glad_glMultiTexCoord3fv = (PFNGLMULTITEXCOORD3FVPROC) load(userptr, "glMultiTexCoord3fv"); + glad_glMultiTexCoord3i = (PFNGLMULTITEXCOORD3IPROC) load(userptr, "glMultiTexCoord3i"); + glad_glMultiTexCoord3iv = (PFNGLMULTITEXCOORD3IVPROC) load(userptr, "glMultiTexCoord3iv"); + glad_glMultiTexCoord3s = (PFNGLMULTITEXCOORD3SPROC) load(userptr, "glMultiTexCoord3s"); + glad_glMultiTexCoord3sv = (PFNGLMULTITEXCOORD3SVPROC) load(userptr, "glMultiTexCoord3sv"); + glad_glMultiTexCoord4d = (PFNGLMULTITEXCOORD4DPROC) load(userptr, "glMultiTexCoord4d"); + glad_glMultiTexCoord4dv = (PFNGLMULTITEXCOORD4DVPROC) load(userptr, "glMultiTexCoord4dv"); + glad_glMultiTexCoord4f = (PFNGLMULTITEXCOORD4FPROC) load(userptr, "glMultiTexCoord4f"); + glad_glMultiTexCoord4fv = (PFNGLMULTITEXCOORD4FVPROC) load(userptr, "glMultiTexCoord4fv"); + glad_glMultiTexCoord4i = (PFNGLMULTITEXCOORD4IPROC) load(userptr, "glMultiTexCoord4i"); + glad_glMultiTexCoord4iv = (PFNGLMULTITEXCOORD4IVPROC) load(userptr, "glMultiTexCoord4iv"); + glad_glMultiTexCoord4s = (PFNGLMULTITEXCOORD4SPROC) load(userptr, "glMultiTexCoord4s"); + glad_glMultiTexCoord4sv = (PFNGLMULTITEXCOORD4SVPROC) load(userptr, "glMultiTexCoord4sv"); + glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load(userptr, "glSampleCoverage"); +} +static void glad_gl_load_GL_VERSION_1_4( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_1_4) return; + glad_glBlendColor = (PFNGLBLENDCOLORPROC) load(userptr, "glBlendColor"); + glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC) load(userptr, "glBlendEquation"); + glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load(userptr, "glBlendFuncSeparate"); + glad_glFogCoordPointer = (PFNGLFOGCOORDPOINTERPROC) load(userptr, "glFogCoordPointer"); + glad_glFogCoordd = (PFNGLFOGCOORDDPROC) load(userptr, "glFogCoordd"); + glad_glFogCoorddv = (PFNGLFOGCOORDDVPROC) load(userptr, "glFogCoorddv"); + glad_glFogCoordf = (PFNGLFOGCOORDFPROC) load(userptr, "glFogCoordf"); + glad_glFogCoordfv = (PFNGLFOGCOORDFVPROC) load(userptr, "glFogCoordfv"); + glad_glMultiDrawArrays = (PFNGLMULTIDRAWARRAYSPROC) load(userptr, "glMultiDrawArrays"); + glad_glMultiDrawElements = (PFNGLMULTIDRAWELEMENTSPROC) load(userptr, "glMultiDrawElements"); + glad_glPointParameterf = (PFNGLPOINTPARAMETERFPROC) load(userptr, "glPointParameterf"); + glad_glPointParameterfv = (PFNGLPOINTPARAMETERFVPROC) load(userptr, "glPointParameterfv"); + glad_glPointParameteri = (PFNGLPOINTPARAMETERIPROC) load(userptr, "glPointParameteri"); + glad_glPointParameteriv = (PFNGLPOINTPARAMETERIVPROC) load(userptr, "glPointParameteriv"); + glad_glSecondaryColor3b = (PFNGLSECONDARYCOLOR3BPROC) load(userptr, "glSecondaryColor3b"); + glad_glSecondaryColor3bv = (PFNGLSECONDARYCOLOR3BVPROC) load(userptr, "glSecondaryColor3bv"); + glad_glSecondaryColor3d = (PFNGLSECONDARYCOLOR3DPROC) load(userptr, "glSecondaryColor3d"); + glad_glSecondaryColor3dv = (PFNGLSECONDARYCOLOR3DVPROC) load(userptr, "glSecondaryColor3dv"); + glad_glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC) load(userptr, "glSecondaryColor3f"); + glad_glSecondaryColor3fv = (PFNGLSECONDARYCOLOR3FVPROC) load(userptr, "glSecondaryColor3fv"); + glad_glSecondaryColor3i = (PFNGLSECONDARYCOLOR3IPROC) load(userptr, "glSecondaryColor3i"); + glad_glSecondaryColor3iv = (PFNGLSECONDARYCOLOR3IVPROC) load(userptr, "glSecondaryColor3iv"); + glad_glSecondaryColor3s = (PFNGLSECONDARYCOLOR3SPROC) load(userptr, "glSecondaryColor3s"); + glad_glSecondaryColor3sv = (PFNGLSECONDARYCOLOR3SVPROC) load(userptr, "glSecondaryColor3sv"); + glad_glSecondaryColor3ub = (PFNGLSECONDARYCOLOR3UBPROC) load(userptr, "glSecondaryColor3ub"); + glad_glSecondaryColor3ubv = (PFNGLSECONDARYCOLOR3UBVPROC) load(userptr, "glSecondaryColor3ubv"); + glad_glSecondaryColor3ui = (PFNGLSECONDARYCOLOR3UIPROC) load(userptr, "glSecondaryColor3ui"); + glad_glSecondaryColor3uiv = (PFNGLSECONDARYCOLOR3UIVPROC) load(userptr, "glSecondaryColor3uiv"); + glad_glSecondaryColor3us = (PFNGLSECONDARYCOLOR3USPROC) load(userptr, "glSecondaryColor3us"); + glad_glSecondaryColor3usv = (PFNGLSECONDARYCOLOR3USVPROC) load(userptr, "glSecondaryColor3usv"); + glad_glSecondaryColorPointer = (PFNGLSECONDARYCOLORPOINTERPROC) load(userptr, "glSecondaryColorPointer"); + glad_glWindowPos2d = (PFNGLWINDOWPOS2DPROC) load(userptr, "glWindowPos2d"); + glad_glWindowPos2dv = (PFNGLWINDOWPOS2DVPROC) load(userptr, "glWindowPos2dv"); + glad_glWindowPos2f = (PFNGLWINDOWPOS2FPROC) load(userptr, "glWindowPos2f"); + glad_glWindowPos2fv = (PFNGLWINDOWPOS2FVPROC) load(userptr, "glWindowPos2fv"); + glad_glWindowPos2i = (PFNGLWINDOWPOS2IPROC) load(userptr, "glWindowPos2i"); + glad_glWindowPos2iv = (PFNGLWINDOWPOS2IVPROC) load(userptr, "glWindowPos2iv"); + glad_glWindowPos2s = (PFNGLWINDOWPOS2SPROC) load(userptr, "glWindowPos2s"); + glad_glWindowPos2sv = (PFNGLWINDOWPOS2SVPROC) load(userptr, "glWindowPos2sv"); + glad_glWindowPos3d = (PFNGLWINDOWPOS3DPROC) load(userptr, "glWindowPos3d"); + glad_glWindowPos3dv = (PFNGLWINDOWPOS3DVPROC) load(userptr, "glWindowPos3dv"); + glad_glWindowPos3f = (PFNGLWINDOWPOS3FPROC) load(userptr, "glWindowPos3f"); + glad_glWindowPos3fv = (PFNGLWINDOWPOS3FVPROC) load(userptr, "glWindowPos3fv"); + glad_glWindowPos3i = (PFNGLWINDOWPOS3IPROC) load(userptr, "glWindowPos3i"); + glad_glWindowPos3iv = (PFNGLWINDOWPOS3IVPROC) load(userptr, "glWindowPos3iv"); + glad_glWindowPos3s = (PFNGLWINDOWPOS3SPROC) load(userptr, "glWindowPos3s"); + glad_glWindowPos3sv = (PFNGLWINDOWPOS3SVPROC) load(userptr, "glWindowPos3sv"); +} +static void glad_gl_load_GL_VERSION_1_5( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_1_5) return; + glad_glBeginQuery = (PFNGLBEGINQUERYPROC) load(userptr, "glBeginQuery"); + glad_glBindBuffer = (PFNGLBINDBUFFERPROC) load(userptr, "glBindBuffer"); + glad_glBufferData = (PFNGLBUFFERDATAPROC) load(userptr, "glBufferData"); + glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) load(userptr, "glBufferSubData"); + glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) load(userptr, "glDeleteBuffers"); + glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC) load(userptr, "glDeleteQueries"); + glad_glEndQuery = (PFNGLENDQUERYPROC) load(userptr, "glEndQuery"); + glad_glGenBuffers = (PFNGLGENBUFFERSPROC) load(userptr, "glGenBuffers"); + glad_glGenQueries = (PFNGLGENQUERIESPROC) load(userptr, "glGenQueries"); + glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load(userptr, "glGetBufferParameteriv"); + glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC) load(userptr, "glGetBufferPointerv"); + glad_glGetBufferSubData = (PFNGLGETBUFFERSUBDATAPROC) load(userptr, "glGetBufferSubData"); + glad_glGetQueryObjectiv = (PFNGLGETQUERYOBJECTIVPROC) load(userptr, "glGetQueryObjectiv"); + glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) load(userptr, "glGetQueryObjectuiv"); + glad_glGetQueryiv = (PFNGLGETQUERYIVPROC) load(userptr, "glGetQueryiv"); + glad_glIsBuffer = (PFNGLISBUFFERPROC) load(userptr, "glIsBuffer"); + glad_glIsQuery = (PFNGLISQUERYPROC) load(userptr, "glIsQuery"); + glad_glMapBuffer = (PFNGLMAPBUFFERPROC) load(userptr, "glMapBuffer"); + glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) load(userptr, "glUnmapBuffer"); +} +static void glad_gl_load_GL_VERSION_2_0( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_2_0) return; + glad_glAttachShader = (PFNGLATTACHSHADERPROC) load(userptr, "glAttachShader"); + glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load(userptr, "glBindAttribLocation"); + glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load(userptr, "glBlendEquationSeparate"); + glad_glCompileShader = (PFNGLCOMPILESHADERPROC) load(userptr, "glCompileShader"); + glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC) load(userptr, "glCreateProgram"); + glad_glCreateShader = (PFNGLCREATESHADERPROC) load(userptr, "glCreateShader"); + glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC) load(userptr, "glDeleteProgram"); + glad_glDeleteShader = (PFNGLDELETESHADERPROC) load(userptr, "glDeleteShader"); + glad_glDetachShader = (PFNGLDETACHSHADERPROC) load(userptr, "glDetachShader"); + glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load(userptr, "glDisableVertexAttribArray"); + glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC) load(userptr, "glDrawBuffers"); + glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load(userptr, "glEnableVertexAttribArray"); + glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load(userptr, "glGetActiveAttrib"); + glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load(userptr, "glGetActiveUniform"); + glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load(userptr, "glGetAttachedShaders"); + glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load(userptr, "glGetAttribLocation"); + glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load(userptr, "glGetProgramInfoLog"); + glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC) load(userptr, "glGetProgramiv"); + glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load(userptr, "glGetShaderInfoLog"); + glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC) load(userptr, "glGetShaderSource"); + glad_glGetShaderiv = (PFNGLGETSHADERIVPROC) load(userptr, "glGetShaderiv"); + glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load(userptr, "glGetUniformLocation"); + glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC) load(userptr, "glGetUniformfv"); + glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC) load(userptr, "glGetUniformiv"); + glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load(userptr, "glGetVertexAttribPointerv"); + glad_glGetVertexAttribdv = (PFNGLGETVERTEXATTRIBDVPROC) load(userptr, "glGetVertexAttribdv"); + glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load(userptr, "glGetVertexAttribfv"); + glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load(userptr, "glGetVertexAttribiv"); + glad_glIsProgram = (PFNGLISPROGRAMPROC) load(userptr, "glIsProgram"); + glad_glIsShader = (PFNGLISSHADERPROC) load(userptr, "glIsShader"); + glad_glLinkProgram = (PFNGLLINKPROGRAMPROC) load(userptr, "glLinkProgram"); + glad_glShaderSource = (PFNGLSHADERSOURCEPROC) load(userptr, "glShaderSource"); + glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load(userptr, "glStencilFuncSeparate"); + glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load(userptr, "glStencilMaskSeparate"); + glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load(userptr, "glStencilOpSeparate"); + glad_glUniform1f = (PFNGLUNIFORM1FPROC) load(userptr, "glUniform1f"); + glad_glUniform1fv = (PFNGLUNIFORM1FVPROC) load(userptr, "glUniform1fv"); + glad_glUniform1i = (PFNGLUNIFORM1IPROC) load(userptr, "glUniform1i"); + glad_glUniform1iv = (PFNGLUNIFORM1IVPROC) load(userptr, "glUniform1iv"); + glad_glUniform2f = (PFNGLUNIFORM2FPROC) load(userptr, "glUniform2f"); + glad_glUniform2fv = (PFNGLUNIFORM2FVPROC) load(userptr, "glUniform2fv"); + glad_glUniform2i = (PFNGLUNIFORM2IPROC) load(userptr, "glUniform2i"); + glad_glUniform2iv = (PFNGLUNIFORM2IVPROC) load(userptr, "glUniform2iv"); + glad_glUniform3f = (PFNGLUNIFORM3FPROC) load(userptr, "glUniform3f"); + glad_glUniform3fv = (PFNGLUNIFORM3FVPROC) load(userptr, "glUniform3fv"); + glad_glUniform3i = (PFNGLUNIFORM3IPROC) load(userptr, "glUniform3i"); + glad_glUniform3iv = (PFNGLUNIFORM3IVPROC) load(userptr, "glUniform3iv"); + glad_glUniform4f = (PFNGLUNIFORM4FPROC) load(userptr, "glUniform4f"); + glad_glUniform4fv = (PFNGLUNIFORM4FVPROC) load(userptr, "glUniform4fv"); + glad_glUniform4i = (PFNGLUNIFORM4IPROC) load(userptr, "glUniform4i"); + glad_glUniform4iv = (PFNGLUNIFORM4IVPROC) load(userptr, "glUniform4iv"); + glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load(userptr, "glUniformMatrix2fv"); + glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load(userptr, "glUniformMatrix3fv"); + glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load(userptr, "glUniformMatrix4fv"); + glad_glUseProgram = (PFNGLUSEPROGRAMPROC) load(userptr, "glUseProgram"); + glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load(userptr, "glValidateProgram"); + glad_glVertexAttrib1d = (PFNGLVERTEXATTRIB1DPROC) load(userptr, "glVertexAttrib1d"); + glad_glVertexAttrib1dv = (PFNGLVERTEXATTRIB1DVPROC) load(userptr, "glVertexAttrib1dv"); + glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load(userptr, "glVertexAttrib1f"); + glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load(userptr, "glVertexAttrib1fv"); + glad_glVertexAttrib1s = (PFNGLVERTEXATTRIB1SPROC) load(userptr, "glVertexAttrib1s"); + glad_glVertexAttrib1sv = (PFNGLVERTEXATTRIB1SVPROC) load(userptr, "glVertexAttrib1sv"); + glad_glVertexAttrib2d = (PFNGLVERTEXATTRIB2DPROC) load(userptr, "glVertexAttrib2d"); + glad_glVertexAttrib2dv = (PFNGLVERTEXATTRIB2DVPROC) load(userptr, "glVertexAttrib2dv"); + glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load(userptr, "glVertexAttrib2f"); + glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load(userptr, "glVertexAttrib2fv"); + glad_glVertexAttrib2s = (PFNGLVERTEXATTRIB2SPROC) load(userptr, "glVertexAttrib2s"); + glad_glVertexAttrib2sv = (PFNGLVERTEXATTRIB2SVPROC) load(userptr, "glVertexAttrib2sv"); + glad_glVertexAttrib3d = (PFNGLVERTEXATTRIB3DPROC) load(userptr, "glVertexAttrib3d"); + glad_glVertexAttrib3dv = (PFNGLVERTEXATTRIB3DVPROC) load(userptr, "glVertexAttrib3dv"); + glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load(userptr, "glVertexAttrib3f"); + glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load(userptr, "glVertexAttrib3fv"); + glad_glVertexAttrib3s = (PFNGLVERTEXATTRIB3SPROC) load(userptr, "glVertexAttrib3s"); + glad_glVertexAttrib3sv = (PFNGLVERTEXATTRIB3SVPROC) load(userptr, "glVertexAttrib3sv"); + glad_glVertexAttrib4Nbv = (PFNGLVERTEXATTRIB4NBVPROC) load(userptr, "glVertexAttrib4Nbv"); + glad_glVertexAttrib4Niv = (PFNGLVERTEXATTRIB4NIVPROC) load(userptr, "glVertexAttrib4Niv"); + glad_glVertexAttrib4Nsv = (PFNGLVERTEXATTRIB4NSVPROC) load(userptr, "glVertexAttrib4Nsv"); + glad_glVertexAttrib4Nub = (PFNGLVERTEXATTRIB4NUBPROC) load(userptr, "glVertexAttrib4Nub"); + glad_glVertexAttrib4Nubv = (PFNGLVERTEXATTRIB4NUBVPROC) load(userptr, "glVertexAttrib4Nubv"); + glad_glVertexAttrib4Nuiv = (PFNGLVERTEXATTRIB4NUIVPROC) load(userptr, "glVertexAttrib4Nuiv"); + glad_glVertexAttrib4Nusv = (PFNGLVERTEXATTRIB4NUSVPROC) load(userptr, "glVertexAttrib4Nusv"); + glad_glVertexAttrib4bv = (PFNGLVERTEXATTRIB4BVPROC) load(userptr, "glVertexAttrib4bv"); + glad_glVertexAttrib4d = (PFNGLVERTEXATTRIB4DPROC) load(userptr, "glVertexAttrib4d"); + glad_glVertexAttrib4dv = (PFNGLVERTEXATTRIB4DVPROC) load(userptr, "glVertexAttrib4dv"); + glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load(userptr, "glVertexAttrib4f"); + glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load(userptr, "glVertexAttrib4fv"); + glad_glVertexAttrib4iv = (PFNGLVERTEXATTRIB4IVPROC) load(userptr, "glVertexAttrib4iv"); + glad_glVertexAttrib4s = (PFNGLVERTEXATTRIB4SPROC) load(userptr, "glVertexAttrib4s"); + glad_glVertexAttrib4sv = (PFNGLVERTEXATTRIB4SVPROC) load(userptr, "glVertexAttrib4sv"); + glad_glVertexAttrib4ubv = (PFNGLVERTEXATTRIB4UBVPROC) load(userptr, "glVertexAttrib4ubv"); + glad_glVertexAttrib4uiv = (PFNGLVERTEXATTRIB4UIVPROC) load(userptr, "glVertexAttrib4uiv"); + glad_glVertexAttrib4usv = (PFNGLVERTEXATTRIB4USVPROC) load(userptr, "glVertexAttrib4usv"); + glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load(userptr, "glVertexAttribPointer"); +} +static void glad_gl_load_GL_VERSION_2_1( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_2_1) return; + glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC) load(userptr, "glUniformMatrix2x3fv"); + glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC) load(userptr, "glUniformMatrix2x4fv"); + glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC) load(userptr, "glUniformMatrix3x2fv"); + glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) load(userptr, "glUniformMatrix3x4fv"); + glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC) load(userptr, "glUniformMatrix4x2fv"); + glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC) load(userptr, "glUniformMatrix4x3fv"); +} +static void glad_gl_load_GL_VERSION_3_0( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_3_0) return; + glad_glBeginConditionalRender = (PFNGLBEGINCONDITIONALRENDERPROC) load(userptr, "glBeginConditionalRender"); + glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) load(userptr, "glBeginTransformFeedback"); + glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase"); + glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange"); + glad_glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC) load(userptr, "glBindFragDataLocation"); + glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer"); + glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer"); + glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load(userptr, "glBindVertexArray"); + glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load(userptr, "glBlitFramebuffer"); + glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus"); + glad_glClampColor = (PFNGLCLAMPCOLORPROC) load(userptr, "glClampColor"); + glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC) load(userptr, "glClearBufferfi"); + glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) load(userptr, "glClearBufferfv"); + glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC) load(userptr, "glClearBufferiv"); + glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC) load(userptr, "glClearBufferuiv"); + glad_glColorMaski = (PFNGLCOLORMASKIPROC) load(userptr, "glColorMaski"); + glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers"); + glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers"); + glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load(userptr, "glDeleteVertexArrays"); + glad_glDisablei = (PFNGLDISABLEIPROC) load(userptr, "glDisablei"); + glad_glEnablei = (PFNGLENABLEIPROC) load(userptr, "glEnablei"); + glad_glEndConditionalRender = (PFNGLENDCONDITIONALRENDERPROC) load(userptr, "glEndConditionalRender"); + glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) load(userptr, "glEndTransformFeedback"); + glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load(userptr, "glFlushMappedBufferRange"); + glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer"); + glad_glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) load(userptr, "glFramebufferTexture1D"); + glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D"); + glad_glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) load(userptr, "glFramebufferTexture3D"); + glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glFramebufferTextureLayer"); + glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers"); + glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers"); + glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load(userptr, "glGenVertexArrays"); + glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap"); + glad_glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC) load(userptr, "glGetBooleani_v"); + glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC) load(userptr, "glGetFragDataLocation"); + glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv"); + glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v"); + glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv"); + glad_glGetStringi = (PFNGLGETSTRINGIPROC) load(userptr, "glGetStringi"); + glad_glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC) load(userptr, "glGetTexParameterIiv"); + glad_glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC) load(userptr, "glGetTexParameterIuiv"); + glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) load(userptr, "glGetTransformFeedbackVarying"); + glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC) load(userptr, "glGetUniformuiv"); + glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC) load(userptr, "glGetVertexAttribIiv"); + glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC) load(userptr, "glGetVertexAttribIuiv"); + glad_glIsEnabledi = (PFNGLISENABLEDIPROC) load(userptr, "glIsEnabledi"); + glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer"); + glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer"); + glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC) load(userptr, "glIsVertexArray"); + glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load(userptr, "glMapBufferRange"); + glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage"); + glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glRenderbufferStorageMultisample"); + glad_glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC) load(userptr, "glTexParameterIiv"); + glad_glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC) load(userptr, "glTexParameterIuiv"); + glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) load(userptr, "glTransformFeedbackVaryings"); + glad_glUniform1ui = (PFNGLUNIFORM1UIPROC) load(userptr, "glUniform1ui"); + glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC) load(userptr, "glUniform1uiv"); + glad_glUniform2ui = (PFNGLUNIFORM2UIPROC) load(userptr, "glUniform2ui"); + glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC) load(userptr, "glUniform2uiv"); + glad_glUniform3ui = (PFNGLUNIFORM3UIPROC) load(userptr, "glUniform3ui"); + glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC) load(userptr, "glUniform3uiv"); + glad_glUniform4ui = (PFNGLUNIFORM4UIPROC) load(userptr, "glUniform4ui"); + glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC) load(userptr, "glUniform4uiv"); + glad_glVertexAttribI1i = (PFNGLVERTEXATTRIBI1IPROC) load(userptr, "glVertexAttribI1i"); + glad_glVertexAttribI1iv = (PFNGLVERTEXATTRIBI1IVPROC) load(userptr, "glVertexAttribI1iv"); + glad_glVertexAttribI1ui = (PFNGLVERTEXATTRIBI1UIPROC) load(userptr, "glVertexAttribI1ui"); + glad_glVertexAttribI1uiv = (PFNGLVERTEXATTRIBI1UIVPROC) load(userptr, "glVertexAttribI1uiv"); + glad_glVertexAttribI2i = (PFNGLVERTEXATTRIBI2IPROC) load(userptr, "glVertexAttribI2i"); + glad_glVertexAttribI2iv = (PFNGLVERTEXATTRIBI2IVPROC) load(userptr, "glVertexAttribI2iv"); + glad_glVertexAttribI2ui = (PFNGLVERTEXATTRIBI2UIPROC) load(userptr, "glVertexAttribI2ui"); + glad_glVertexAttribI2uiv = (PFNGLVERTEXATTRIBI2UIVPROC) load(userptr, "glVertexAttribI2uiv"); + glad_glVertexAttribI3i = (PFNGLVERTEXATTRIBI3IPROC) load(userptr, "glVertexAttribI3i"); + glad_glVertexAttribI3iv = (PFNGLVERTEXATTRIBI3IVPROC) load(userptr, "glVertexAttribI3iv"); + glad_glVertexAttribI3ui = (PFNGLVERTEXATTRIBI3UIPROC) load(userptr, "glVertexAttribI3ui"); + glad_glVertexAttribI3uiv = (PFNGLVERTEXATTRIBI3UIVPROC) load(userptr, "glVertexAttribI3uiv"); + glad_glVertexAttribI4bv = (PFNGLVERTEXATTRIBI4BVPROC) load(userptr, "glVertexAttribI4bv"); + glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC) load(userptr, "glVertexAttribI4i"); + glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC) load(userptr, "glVertexAttribI4iv"); + glad_glVertexAttribI4sv = (PFNGLVERTEXATTRIBI4SVPROC) load(userptr, "glVertexAttribI4sv"); + glad_glVertexAttribI4ubv = (PFNGLVERTEXATTRIBI4UBVPROC) load(userptr, "glVertexAttribI4ubv"); + glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) load(userptr, "glVertexAttribI4ui"); + glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC) load(userptr, "glVertexAttribI4uiv"); + glad_glVertexAttribI4usv = (PFNGLVERTEXATTRIBI4USVPROC) load(userptr, "glVertexAttribI4usv"); + glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) load(userptr, "glVertexAttribIPointer"); +} +static void glad_gl_load_GL_VERSION_3_1( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_3_1) return; + glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase"); + glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange"); + glad_glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC) load(userptr, "glCopyBufferSubData"); + glad_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) load(userptr, "glDrawArraysInstanced"); + glad_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) load(userptr, "glDrawElementsInstanced"); + glad_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) load(userptr, "glGetActiveUniformBlockName"); + glad_glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) load(userptr, "glGetActiveUniformBlockiv"); + glad_glGetActiveUniformName = (PFNGLGETACTIVEUNIFORMNAMEPROC) load(userptr, "glGetActiveUniformName"); + glad_glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) load(userptr, "glGetActiveUniformsiv"); + glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v"); + glad_glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) load(userptr, "glGetUniformBlockIndex"); + glad_glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC) load(userptr, "glGetUniformIndices"); + glad_glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC) load(userptr, "glPrimitiveRestartIndex"); + glad_glTexBuffer = (PFNGLTEXBUFFERPROC) load(userptr, "glTexBuffer"); + glad_glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) load(userptr, "glUniformBlockBinding"); +} +static void glad_gl_load_GL_VERSION_3_2( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_3_2) return; + glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) load(userptr, "glClientWaitSync"); + glad_glDeleteSync = (PFNGLDELETESYNCPROC) load(userptr, "glDeleteSync"); + glad_glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glDrawElementsBaseVertex"); + glad_glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) load(userptr, "glDrawElementsInstancedBaseVertex"); + glad_glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) load(userptr, "glDrawRangeElementsBaseVertex"); + glad_glFenceSync = (PFNGLFENCESYNCPROC) load(userptr, "glFenceSync"); + glad_glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC) load(userptr, "glFramebufferTexture"); + glad_glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC) load(userptr, "glGetBufferParameteri64v"); + glad_glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC) load(userptr, "glGetInteger64i_v"); + glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC) load(userptr, "glGetInteger64v"); + glad_glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) load(userptr, "glGetMultisamplefv"); + glad_glGetSynciv = (PFNGLGETSYNCIVPROC) load(userptr, "glGetSynciv"); + glad_glIsSync = (PFNGLISSYNCPROC) load(userptr, "glIsSync"); + glad_glMultiDrawElementsBaseVertex = (PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glMultiDrawElementsBaseVertex"); + glad_glProvokingVertex = (PFNGLPROVOKINGVERTEXPROC) load(userptr, "glProvokingVertex"); + glad_glSampleMaski = (PFNGLSAMPLEMASKIPROC) load(userptr, "glSampleMaski"); + glad_glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) load(userptr, "glTexImage2DMultisample"); + glad_glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) load(userptr, "glTexImage3DMultisample"); + glad_glWaitSync = (PFNGLWAITSYNCPROC) load(userptr, "glWaitSync"); +} +static void glad_gl_load_GL_VERSION_3_3( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_3_3) return; + glad_glBindFragDataLocationIndexed = (PFNGLBINDFRAGDATALOCATIONINDEXEDPROC) load(userptr, "glBindFragDataLocationIndexed"); + glad_glBindSampler = (PFNGLBINDSAMPLERPROC) load(userptr, "glBindSampler"); + glad_glColorP3ui = (PFNGLCOLORP3UIPROC) load(userptr, "glColorP3ui"); + glad_glColorP3uiv = (PFNGLCOLORP3UIVPROC) load(userptr, "glColorP3uiv"); + glad_glColorP4ui = (PFNGLCOLORP4UIPROC) load(userptr, "glColorP4ui"); + glad_glColorP4uiv = (PFNGLCOLORP4UIVPROC) load(userptr, "glColorP4uiv"); + glad_glDeleteSamplers = (PFNGLDELETESAMPLERSPROC) load(userptr, "glDeleteSamplers"); + glad_glGenSamplers = (PFNGLGENSAMPLERSPROC) load(userptr, "glGenSamplers"); + glad_glGetFragDataIndex = (PFNGLGETFRAGDATAINDEXPROC) load(userptr, "glGetFragDataIndex"); + glad_glGetQueryObjecti64v = (PFNGLGETQUERYOBJECTI64VPROC) load(userptr, "glGetQueryObjecti64v"); + glad_glGetQueryObjectui64v = (PFNGLGETQUERYOBJECTUI64VPROC) load(userptr, "glGetQueryObjectui64v"); + glad_glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC) load(userptr, "glGetSamplerParameterIiv"); + glad_glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC) load(userptr, "glGetSamplerParameterIuiv"); + glad_glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC) load(userptr, "glGetSamplerParameterfv"); + glad_glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC) load(userptr, "glGetSamplerParameteriv"); + glad_glIsSampler = (PFNGLISSAMPLERPROC) load(userptr, "glIsSampler"); + glad_glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC) load(userptr, "glMultiTexCoordP1ui"); + glad_glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC) load(userptr, "glMultiTexCoordP1uiv"); + glad_glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC) load(userptr, "glMultiTexCoordP2ui"); + glad_glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC) load(userptr, "glMultiTexCoordP2uiv"); + glad_glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC) load(userptr, "glMultiTexCoordP3ui"); + glad_glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC) load(userptr, "glMultiTexCoordP3uiv"); + glad_glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC) load(userptr, "glMultiTexCoordP4ui"); + glad_glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC) load(userptr, "glMultiTexCoordP4uiv"); + glad_glNormalP3ui = (PFNGLNORMALP3UIPROC) load(userptr, "glNormalP3ui"); + glad_glNormalP3uiv = (PFNGLNORMALP3UIVPROC) load(userptr, "glNormalP3uiv"); + glad_glQueryCounter = (PFNGLQUERYCOUNTERPROC) load(userptr, "glQueryCounter"); + glad_glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC) load(userptr, "glSamplerParameterIiv"); + glad_glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC) load(userptr, "glSamplerParameterIuiv"); + glad_glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC) load(userptr, "glSamplerParameterf"); + glad_glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC) load(userptr, "glSamplerParameterfv"); + glad_glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC) load(userptr, "glSamplerParameteri"); + glad_glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC) load(userptr, "glSamplerParameteriv"); + glad_glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC) load(userptr, "glSecondaryColorP3ui"); + glad_glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC) load(userptr, "glSecondaryColorP3uiv"); + glad_glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC) load(userptr, "glTexCoordP1ui"); + glad_glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC) load(userptr, "glTexCoordP1uiv"); + glad_glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC) load(userptr, "glTexCoordP2ui"); + glad_glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC) load(userptr, "glTexCoordP2uiv"); + glad_glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC) load(userptr, "glTexCoordP3ui"); + glad_glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC) load(userptr, "glTexCoordP3uiv"); + glad_glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC) load(userptr, "glTexCoordP4ui"); + glad_glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC) load(userptr, "glTexCoordP4uiv"); + glad_glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC) load(userptr, "glVertexAttribDivisor"); + glad_glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC) load(userptr, "glVertexAttribP1ui"); + glad_glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC) load(userptr, "glVertexAttribP1uiv"); + glad_glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC) load(userptr, "glVertexAttribP2ui"); + glad_glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC) load(userptr, "glVertexAttribP2uiv"); + glad_glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC) load(userptr, "glVertexAttribP3ui"); + glad_glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC) load(userptr, "glVertexAttribP3uiv"); + glad_glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC) load(userptr, "glVertexAttribP4ui"); + glad_glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC) load(userptr, "glVertexAttribP4uiv"); + glad_glVertexP2ui = (PFNGLVERTEXP2UIPROC) load(userptr, "glVertexP2ui"); + glad_glVertexP2uiv = (PFNGLVERTEXP2UIVPROC) load(userptr, "glVertexP2uiv"); + glad_glVertexP3ui = (PFNGLVERTEXP3UIPROC) load(userptr, "glVertexP3ui"); + glad_glVertexP3uiv = (PFNGLVERTEXP3UIVPROC) load(userptr, "glVertexP3uiv"); + glad_glVertexP4ui = (PFNGLVERTEXP4UIPROC) load(userptr, "glVertexP4ui"); + glad_glVertexP4uiv = (PFNGLVERTEXP4UIVPROC) load(userptr, "glVertexP4uiv"); +} +static void glad_gl_load_GL_VERSION_4_0( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_4_0) return; + glad_glBeginQueryIndexed = (PFNGLBEGINQUERYINDEXEDPROC) load(userptr, "glBeginQueryIndexed"); + glad_glBindTransformFeedback = (PFNGLBINDTRANSFORMFEEDBACKPROC) load(userptr, "glBindTransformFeedback"); + glad_glBlendEquationSeparatei = (PFNGLBLENDEQUATIONSEPARATEIPROC) load(userptr, "glBlendEquationSeparatei"); + glad_glBlendEquationi = (PFNGLBLENDEQUATIONIPROC) load(userptr, "glBlendEquationi"); + glad_glBlendFuncSeparatei = (PFNGLBLENDFUNCSEPARATEIPROC) load(userptr, "glBlendFuncSeparatei"); + glad_glBlendFunci = (PFNGLBLENDFUNCIPROC) load(userptr, "glBlendFunci"); + glad_glDeleteTransformFeedbacks = (PFNGLDELETETRANSFORMFEEDBACKSPROC) load(userptr, "glDeleteTransformFeedbacks"); + glad_glDrawArraysIndirect = (PFNGLDRAWARRAYSINDIRECTPROC) load(userptr, "glDrawArraysIndirect"); + glad_glDrawElementsIndirect = (PFNGLDRAWELEMENTSINDIRECTPROC) load(userptr, "glDrawElementsIndirect"); + glad_glDrawTransformFeedback = (PFNGLDRAWTRANSFORMFEEDBACKPROC) load(userptr, "glDrawTransformFeedback"); + glad_glDrawTransformFeedbackStream = (PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC) load(userptr, "glDrawTransformFeedbackStream"); + glad_glEndQueryIndexed = (PFNGLENDQUERYINDEXEDPROC) load(userptr, "glEndQueryIndexed"); + glad_glGenTransformFeedbacks = (PFNGLGENTRANSFORMFEEDBACKSPROC) load(userptr, "glGenTransformFeedbacks"); + glad_glGetActiveSubroutineName = (PFNGLGETACTIVESUBROUTINENAMEPROC) load(userptr, "glGetActiveSubroutineName"); + glad_glGetActiveSubroutineUniformName = (PFNGLGETACTIVESUBROUTINEUNIFORMNAMEPROC) load(userptr, "glGetActiveSubroutineUniformName"); + glad_glGetActiveSubroutineUniformiv = (PFNGLGETACTIVESUBROUTINEUNIFORMIVPROC) load(userptr, "glGetActiveSubroutineUniformiv"); + glad_glGetProgramStageiv = (PFNGLGETPROGRAMSTAGEIVPROC) load(userptr, "glGetProgramStageiv"); + glad_glGetQueryIndexediv = (PFNGLGETQUERYINDEXEDIVPROC) load(userptr, "glGetQueryIndexediv"); + glad_glGetSubroutineIndex = (PFNGLGETSUBROUTINEINDEXPROC) load(userptr, "glGetSubroutineIndex"); + glad_glGetSubroutineUniformLocation = (PFNGLGETSUBROUTINEUNIFORMLOCATIONPROC) load(userptr, "glGetSubroutineUniformLocation"); + glad_glGetUniformSubroutineuiv = (PFNGLGETUNIFORMSUBROUTINEUIVPROC) load(userptr, "glGetUniformSubroutineuiv"); + glad_glGetUniformdv = (PFNGLGETUNIFORMDVPROC) load(userptr, "glGetUniformdv"); + glad_glIsTransformFeedback = (PFNGLISTRANSFORMFEEDBACKPROC) load(userptr, "glIsTransformFeedback"); + glad_glMinSampleShading = (PFNGLMINSAMPLESHADINGPROC) load(userptr, "glMinSampleShading"); + glad_glPatchParameterfv = (PFNGLPATCHPARAMETERFVPROC) load(userptr, "glPatchParameterfv"); + glad_glPatchParameteri = (PFNGLPATCHPARAMETERIPROC) load(userptr, "glPatchParameteri"); + glad_glPauseTransformFeedback = (PFNGLPAUSETRANSFORMFEEDBACKPROC) load(userptr, "glPauseTransformFeedback"); + glad_glResumeTransformFeedback = (PFNGLRESUMETRANSFORMFEEDBACKPROC) load(userptr, "glResumeTransformFeedback"); + glad_glUniform1d = (PFNGLUNIFORM1DPROC) load(userptr, "glUniform1d"); + glad_glUniform1dv = (PFNGLUNIFORM1DVPROC) load(userptr, "glUniform1dv"); + glad_glUniform2d = (PFNGLUNIFORM2DPROC) load(userptr, "glUniform2d"); + glad_glUniform2dv = (PFNGLUNIFORM2DVPROC) load(userptr, "glUniform2dv"); + glad_glUniform3d = (PFNGLUNIFORM3DPROC) load(userptr, "glUniform3d"); + glad_glUniform3dv = (PFNGLUNIFORM3DVPROC) load(userptr, "glUniform3dv"); + glad_glUniform4d = (PFNGLUNIFORM4DPROC) load(userptr, "glUniform4d"); + glad_glUniform4dv = (PFNGLUNIFORM4DVPROC) load(userptr, "glUniform4dv"); + glad_glUniformMatrix2dv = (PFNGLUNIFORMMATRIX2DVPROC) load(userptr, "glUniformMatrix2dv"); + glad_glUniformMatrix2x3dv = (PFNGLUNIFORMMATRIX2X3DVPROC) load(userptr, "glUniformMatrix2x3dv"); + glad_glUniformMatrix2x4dv = (PFNGLUNIFORMMATRIX2X4DVPROC) load(userptr, "glUniformMatrix2x4dv"); + glad_glUniformMatrix3dv = (PFNGLUNIFORMMATRIX3DVPROC) load(userptr, "glUniformMatrix3dv"); + glad_glUniformMatrix3x2dv = (PFNGLUNIFORMMATRIX3X2DVPROC) load(userptr, "glUniformMatrix3x2dv"); + glad_glUniformMatrix3x4dv = (PFNGLUNIFORMMATRIX3X4DVPROC) load(userptr, "glUniformMatrix3x4dv"); + glad_glUniformMatrix4dv = (PFNGLUNIFORMMATRIX4DVPROC) load(userptr, "glUniformMatrix4dv"); + glad_glUniformMatrix4x2dv = (PFNGLUNIFORMMATRIX4X2DVPROC) load(userptr, "glUniformMatrix4x2dv"); + glad_glUniformMatrix4x3dv = (PFNGLUNIFORMMATRIX4X3DVPROC) load(userptr, "glUniformMatrix4x3dv"); + glad_glUniformSubroutinesuiv = (PFNGLUNIFORMSUBROUTINESUIVPROC) load(userptr, "glUniformSubroutinesuiv"); +} +static void glad_gl_load_GL_VERSION_4_1( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_4_1) return; + glad_glActiveShaderProgram = (PFNGLACTIVESHADERPROGRAMPROC) load(userptr, "glActiveShaderProgram"); + glad_glBindProgramPipeline = (PFNGLBINDPROGRAMPIPELINEPROC) load(userptr, "glBindProgramPipeline"); + glad_glClearDepthf = (PFNGLCLEARDEPTHFPROC) load(userptr, "glClearDepthf"); + glad_glCreateShaderProgramv = (PFNGLCREATESHADERPROGRAMVPROC) load(userptr, "glCreateShaderProgramv"); + glad_glDeleteProgramPipelines = (PFNGLDELETEPROGRAMPIPELINESPROC) load(userptr, "glDeleteProgramPipelines"); + glad_glDepthRangeArrayv = (PFNGLDEPTHRANGEARRAYVPROC) load(userptr, "glDepthRangeArrayv"); + glad_glDepthRangeIndexed = (PFNGLDEPTHRANGEINDEXEDPROC) load(userptr, "glDepthRangeIndexed"); + glad_glDepthRangef = (PFNGLDEPTHRANGEFPROC) load(userptr, "glDepthRangef"); + glad_glGenProgramPipelines = (PFNGLGENPROGRAMPIPELINESPROC) load(userptr, "glGenProgramPipelines"); + glad_glGetDoublei_v = (PFNGLGETDOUBLEI_VPROC) load(userptr, "glGetDoublei_v"); + glad_glGetFloati_v = (PFNGLGETFLOATI_VPROC) load(userptr, "glGetFloati_v"); + glad_glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC) load(userptr, "glGetProgramBinary"); + glad_glGetProgramPipelineInfoLog = (PFNGLGETPROGRAMPIPELINEINFOLOGPROC) load(userptr, "glGetProgramPipelineInfoLog"); + glad_glGetProgramPipelineiv = (PFNGLGETPROGRAMPIPELINEIVPROC) load(userptr, "glGetProgramPipelineiv"); + glad_glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC) load(userptr, "glGetShaderPrecisionFormat"); + glad_glGetVertexAttribLdv = (PFNGLGETVERTEXATTRIBLDVPROC) load(userptr, "glGetVertexAttribLdv"); + glad_glIsProgramPipeline = (PFNGLISPROGRAMPIPELINEPROC) load(userptr, "glIsProgramPipeline"); + glad_glProgramBinary = (PFNGLPROGRAMBINARYPROC) load(userptr, "glProgramBinary"); + glad_glProgramParameteri = (PFNGLPROGRAMPARAMETERIPROC) load(userptr, "glProgramParameteri"); + glad_glProgramUniform1d = (PFNGLPROGRAMUNIFORM1DPROC) load(userptr, "glProgramUniform1d"); + glad_glProgramUniform1dv = (PFNGLPROGRAMUNIFORM1DVPROC) load(userptr, "glProgramUniform1dv"); + glad_glProgramUniform1f = (PFNGLPROGRAMUNIFORM1FPROC) load(userptr, "glProgramUniform1f"); + glad_glProgramUniform1fv = (PFNGLPROGRAMUNIFORM1FVPROC) load(userptr, "glProgramUniform1fv"); + glad_glProgramUniform1i = (PFNGLPROGRAMUNIFORM1IPROC) load(userptr, "glProgramUniform1i"); + glad_glProgramUniform1iv = (PFNGLPROGRAMUNIFORM1IVPROC) load(userptr, "glProgramUniform1iv"); + glad_glProgramUniform1ui = (PFNGLPROGRAMUNIFORM1UIPROC) load(userptr, "glProgramUniform1ui"); + glad_glProgramUniform1uiv = (PFNGLPROGRAMUNIFORM1UIVPROC) load(userptr, "glProgramUniform1uiv"); + glad_glProgramUniform2d = (PFNGLPROGRAMUNIFORM2DPROC) load(userptr, "glProgramUniform2d"); + glad_glProgramUniform2dv = (PFNGLPROGRAMUNIFORM2DVPROC) load(userptr, "glProgramUniform2dv"); + glad_glProgramUniform2f = (PFNGLPROGRAMUNIFORM2FPROC) load(userptr, "glProgramUniform2f"); + glad_glProgramUniform2fv = (PFNGLPROGRAMUNIFORM2FVPROC) load(userptr, "glProgramUniform2fv"); + glad_glProgramUniform2i = (PFNGLPROGRAMUNIFORM2IPROC) load(userptr, "glProgramUniform2i"); + glad_glProgramUniform2iv = (PFNGLPROGRAMUNIFORM2IVPROC) load(userptr, "glProgramUniform2iv"); + glad_glProgramUniform2ui = (PFNGLPROGRAMUNIFORM2UIPROC) load(userptr, "glProgramUniform2ui"); + glad_glProgramUniform2uiv = (PFNGLPROGRAMUNIFORM2UIVPROC) load(userptr, "glProgramUniform2uiv"); + glad_glProgramUniform3d = (PFNGLPROGRAMUNIFORM3DPROC) load(userptr, "glProgramUniform3d"); + glad_glProgramUniform3dv = (PFNGLPROGRAMUNIFORM3DVPROC) load(userptr, "glProgramUniform3dv"); + glad_glProgramUniform3f = (PFNGLPROGRAMUNIFORM3FPROC) load(userptr, "glProgramUniform3f"); + glad_glProgramUniform3fv = (PFNGLPROGRAMUNIFORM3FVPROC) load(userptr, "glProgramUniform3fv"); + glad_glProgramUniform3i = (PFNGLPROGRAMUNIFORM3IPROC) load(userptr, "glProgramUniform3i"); + glad_glProgramUniform3iv = (PFNGLPROGRAMUNIFORM3IVPROC) load(userptr, "glProgramUniform3iv"); + glad_glProgramUniform3ui = (PFNGLPROGRAMUNIFORM3UIPROC) load(userptr, "glProgramUniform3ui"); + glad_glProgramUniform3uiv = (PFNGLPROGRAMUNIFORM3UIVPROC) load(userptr, "glProgramUniform3uiv"); + glad_glProgramUniform4d = (PFNGLPROGRAMUNIFORM4DPROC) load(userptr, "glProgramUniform4d"); + glad_glProgramUniform4dv = (PFNGLPROGRAMUNIFORM4DVPROC) load(userptr, "glProgramUniform4dv"); + glad_glProgramUniform4f = (PFNGLPROGRAMUNIFORM4FPROC) load(userptr, "glProgramUniform4f"); + glad_glProgramUniform4fv = (PFNGLPROGRAMUNIFORM4FVPROC) load(userptr, "glProgramUniform4fv"); + glad_glProgramUniform4i = (PFNGLPROGRAMUNIFORM4IPROC) load(userptr, "glProgramUniform4i"); + glad_glProgramUniform4iv = (PFNGLPROGRAMUNIFORM4IVPROC) load(userptr, "glProgramUniform4iv"); + glad_glProgramUniform4ui = (PFNGLPROGRAMUNIFORM4UIPROC) load(userptr, "glProgramUniform4ui"); + glad_glProgramUniform4uiv = (PFNGLPROGRAMUNIFORM4UIVPROC) load(userptr, "glProgramUniform4uiv"); + glad_glProgramUniformMatrix2dv = (PFNGLPROGRAMUNIFORMMATRIX2DVPROC) load(userptr, "glProgramUniformMatrix2dv"); + glad_glProgramUniformMatrix2fv = (PFNGLPROGRAMUNIFORMMATRIX2FVPROC) load(userptr, "glProgramUniformMatrix2fv"); + glad_glProgramUniformMatrix2x3dv = (PFNGLPROGRAMUNIFORMMATRIX2X3DVPROC) load(userptr, "glProgramUniformMatrix2x3dv"); + glad_glProgramUniformMatrix2x3fv = (PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) load(userptr, "glProgramUniformMatrix2x3fv"); + glad_glProgramUniformMatrix2x4dv = (PFNGLPROGRAMUNIFORMMATRIX2X4DVPROC) load(userptr, "glProgramUniformMatrix2x4dv"); + glad_glProgramUniformMatrix2x4fv = (PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) load(userptr, "glProgramUniformMatrix2x4fv"); + glad_glProgramUniformMatrix3dv = (PFNGLPROGRAMUNIFORMMATRIX3DVPROC) load(userptr, "glProgramUniformMatrix3dv"); + glad_glProgramUniformMatrix3fv = (PFNGLPROGRAMUNIFORMMATRIX3FVPROC) load(userptr, "glProgramUniformMatrix3fv"); + glad_glProgramUniformMatrix3x2dv = (PFNGLPROGRAMUNIFORMMATRIX3X2DVPROC) load(userptr, "glProgramUniformMatrix3x2dv"); + glad_glProgramUniformMatrix3x2fv = (PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) load(userptr, "glProgramUniformMatrix3x2fv"); + glad_glProgramUniformMatrix3x4dv = (PFNGLPROGRAMUNIFORMMATRIX3X4DVPROC) load(userptr, "glProgramUniformMatrix3x4dv"); + glad_glProgramUniformMatrix3x4fv = (PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) load(userptr, "glProgramUniformMatrix3x4fv"); + glad_glProgramUniformMatrix4dv = (PFNGLPROGRAMUNIFORMMATRIX4DVPROC) load(userptr, "glProgramUniformMatrix4dv"); + glad_glProgramUniformMatrix4fv = (PFNGLPROGRAMUNIFORMMATRIX4FVPROC) load(userptr, "glProgramUniformMatrix4fv"); + glad_glProgramUniformMatrix4x2dv = (PFNGLPROGRAMUNIFORMMATRIX4X2DVPROC) load(userptr, "glProgramUniformMatrix4x2dv"); + glad_glProgramUniformMatrix4x2fv = (PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) load(userptr, "glProgramUniformMatrix4x2fv"); + glad_glProgramUniformMatrix4x3dv = (PFNGLPROGRAMUNIFORMMATRIX4X3DVPROC) load(userptr, "glProgramUniformMatrix4x3dv"); + glad_glProgramUniformMatrix4x3fv = (PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) load(userptr, "glProgramUniformMatrix4x3fv"); + glad_glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC) load(userptr, "glReleaseShaderCompiler"); + glad_glScissorArrayv = (PFNGLSCISSORARRAYVPROC) load(userptr, "glScissorArrayv"); + glad_glScissorIndexed = (PFNGLSCISSORINDEXEDPROC) load(userptr, "glScissorIndexed"); + glad_glScissorIndexedv = (PFNGLSCISSORINDEXEDVPROC) load(userptr, "glScissorIndexedv"); + glad_glShaderBinary = (PFNGLSHADERBINARYPROC) load(userptr, "glShaderBinary"); + glad_glUseProgramStages = (PFNGLUSEPROGRAMSTAGESPROC) load(userptr, "glUseProgramStages"); + glad_glValidateProgramPipeline = (PFNGLVALIDATEPROGRAMPIPELINEPROC) load(userptr, "glValidateProgramPipeline"); + glad_glVertexAttribL1d = (PFNGLVERTEXATTRIBL1DPROC) load(userptr, "glVertexAttribL1d"); + glad_glVertexAttribL1dv = (PFNGLVERTEXATTRIBL1DVPROC) load(userptr, "glVertexAttribL1dv"); + glad_glVertexAttribL2d = (PFNGLVERTEXATTRIBL2DPROC) load(userptr, "glVertexAttribL2d"); + glad_glVertexAttribL2dv = (PFNGLVERTEXATTRIBL2DVPROC) load(userptr, "glVertexAttribL2dv"); + glad_glVertexAttribL3d = (PFNGLVERTEXATTRIBL3DPROC) load(userptr, "glVertexAttribL3d"); + glad_glVertexAttribL3dv = (PFNGLVERTEXATTRIBL3DVPROC) load(userptr, "glVertexAttribL3dv"); + glad_glVertexAttribL4d = (PFNGLVERTEXATTRIBL4DPROC) load(userptr, "glVertexAttribL4d"); + glad_glVertexAttribL4dv = (PFNGLVERTEXATTRIBL4DVPROC) load(userptr, "glVertexAttribL4dv"); + glad_glVertexAttribLPointer = (PFNGLVERTEXATTRIBLPOINTERPROC) load(userptr, "glVertexAttribLPointer"); + glad_glViewportArrayv = (PFNGLVIEWPORTARRAYVPROC) load(userptr, "glViewportArrayv"); + glad_glViewportIndexedf = (PFNGLVIEWPORTINDEXEDFPROC) load(userptr, "glViewportIndexedf"); + glad_glViewportIndexedfv = (PFNGLVIEWPORTINDEXEDFVPROC) load(userptr, "glViewportIndexedfv"); +} +static void glad_gl_load_GL_VERSION_4_2( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_4_2) return; + glad_glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC) load(userptr, "glBindImageTexture"); + glad_glDrawArraysInstancedBaseInstance = (PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEPROC) load(userptr, "glDrawArraysInstancedBaseInstance"); + glad_glDrawElementsInstancedBaseInstance = (PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEPROC) load(userptr, "glDrawElementsInstancedBaseInstance"); + glad_glDrawElementsInstancedBaseVertexBaseInstance = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEPROC) load(userptr, "glDrawElementsInstancedBaseVertexBaseInstance"); + glad_glDrawTransformFeedbackInstanced = (PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC) load(userptr, "glDrawTransformFeedbackInstanced"); + glad_glDrawTransformFeedbackStreamInstanced = (PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC) load(userptr, "glDrawTransformFeedbackStreamInstanced"); + glad_glGetActiveAtomicCounterBufferiv = (PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC) load(userptr, "glGetActiveAtomicCounterBufferiv"); + glad_glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC) load(userptr, "glGetInternalformativ"); + glad_glMemoryBarrier = (PFNGLMEMORYBARRIERPROC) load(userptr, "glMemoryBarrier"); + glad_glTexStorage1D = (PFNGLTEXSTORAGE1DPROC) load(userptr, "glTexStorage1D"); + glad_glTexStorage2D = (PFNGLTEXSTORAGE2DPROC) load(userptr, "glTexStorage2D"); + glad_glTexStorage3D = (PFNGLTEXSTORAGE3DPROC) load(userptr, "glTexStorage3D"); +} +static void glad_gl_load_GL_VERSION_4_3( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_4_3) return; + glad_glBindVertexBuffer = (PFNGLBINDVERTEXBUFFERPROC) load(userptr, "glBindVertexBuffer"); + glad_glClearBufferData = (PFNGLCLEARBUFFERDATAPROC) load(userptr, "glClearBufferData"); + glad_glClearBufferSubData = (PFNGLCLEARBUFFERSUBDATAPROC) load(userptr, "glClearBufferSubData"); + glad_glCopyImageSubData = (PFNGLCOPYIMAGESUBDATAPROC) load(userptr, "glCopyImageSubData"); + glad_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) load(userptr, "glDebugMessageCallback"); + glad_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) load(userptr, "glDebugMessageControl"); + glad_glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC) load(userptr, "glDebugMessageInsert"); + glad_glDispatchCompute = (PFNGLDISPATCHCOMPUTEPROC) load(userptr, "glDispatchCompute"); + glad_glDispatchComputeIndirect = (PFNGLDISPATCHCOMPUTEINDIRECTPROC) load(userptr, "glDispatchComputeIndirect"); + glad_glFramebufferParameteri = (PFNGLFRAMEBUFFERPARAMETERIPROC) load(userptr, "glFramebufferParameteri"); + glad_glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC) load(userptr, "glGetDebugMessageLog"); + glad_glGetFramebufferParameteriv = (PFNGLGETFRAMEBUFFERPARAMETERIVPROC) load(userptr, "glGetFramebufferParameteriv"); + glad_glGetInternalformati64v = (PFNGLGETINTERNALFORMATI64VPROC) load(userptr, "glGetInternalformati64v"); + glad_glGetObjectLabel = (PFNGLGETOBJECTLABELPROC) load(userptr, "glGetObjectLabel"); + glad_glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC) load(userptr, "glGetObjectPtrLabel"); + glad_glGetPointerv = (PFNGLGETPOINTERVPROC) load(userptr, "glGetPointerv"); + glad_glGetProgramInterfaceiv = (PFNGLGETPROGRAMINTERFACEIVPROC) load(userptr, "glGetProgramInterfaceiv"); + glad_glGetProgramResourceIndex = (PFNGLGETPROGRAMRESOURCEINDEXPROC) load(userptr, "glGetProgramResourceIndex"); + glad_glGetProgramResourceLocation = (PFNGLGETPROGRAMRESOURCELOCATIONPROC) load(userptr, "glGetProgramResourceLocation"); + glad_glGetProgramResourceLocationIndex = (PFNGLGETPROGRAMRESOURCELOCATIONINDEXPROC) load(userptr, "glGetProgramResourceLocationIndex"); + glad_glGetProgramResourceName = (PFNGLGETPROGRAMRESOURCENAMEPROC) load(userptr, "glGetProgramResourceName"); + glad_glGetProgramResourceiv = (PFNGLGETPROGRAMRESOURCEIVPROC) load(userptr, "glGetProgramResourceiv"); + glad_glInvalidateBufferData = (PFNGLINVALIDATEBUFFERDATAPROC) load(userptr, "glInvalidateBufferData"); + glad_glInvalidateBufferSubData = (PFNGLINVALIDATEBUFFERSUBDATAPROC) load(userptr, "glInvalidateBufferSubData"); + glad_glInvalidateFramebuffer = (PFNGLINVALIDATEFRAMEBUFFERPROC) load(userptr, "glInvalidateFramebuffer"); + glad_glInvalidateSubFramebuffer = (PFNGLINVALIDATESUBFRAMEBUFFERPROC) load(userptr, "glInvalidateSubFramebuffer"); + glad_glInvalidateTexImage = (PFNGLINVALIDATETEXIMAGEPROC) load(userptr, "glInvalidateTexImage"); + glad_glInvalidateTexSubImage = (PFNGLINVALIDATETEXSUBIMAGEPROC) load(userptr, "glInvalidateTexSubImage"); + glad_glMultiDrawArraysIndirect = (PFNGLMULTIDRAWARRAYSINDIRECTPROC) load(userptr, "glMultiDrawArraysIndirect"); + glad_glMultiDrawElementsIndirect = (PFNGLMULTIDRAWELEMENTSINDIRECTPROC) load(userptr, "glMultiDrawElementsIndirect"); + glad_glObjectLabel = (PFNGLOBJECTLABELPROC) load(userptr, "glObjectLabel"); + glad_glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC) load(userptr, "glObjectPtrLabel"); + glad_glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC) load(userptr, "glPopDebugGroup"); + glad_glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC) load(userptr, "glPushDebugGroup"); + glad_glShaderStorageBlockBinding = (PFNGLSHADERSTORAGEBLOCKBINDINGPROC) load(userptr, "glShaderStorageBlockBinding"); + glad_glTexBufferRange = (PFNGLTEXBUFFERRANGEPROC) load(userptr, "glTexBufferRange"); + glad_glTexStorage2DMultisample = (PFNGLTEXSTORAGE2DMULTISAMPLEPROC) load(userptr, "glTexStorage2DMultisample"); + glad_glTexStorage3DMultisample = (PFNGLTEXSTORAGE3DMULTISAMPLEPROC) load(userptr, "glTexStorage3DMultisample"); + glad_glTextureView = (PFNGLTEXTUREVIEWPROC) load(userptr, "glTextureView"); + glad_glVertexAttribBinding = (PFNGLVERTEXATTRIBBINDINGPROC) load(userptr, "glVertexAttribBinding"); + glad_glVertexAttribFormat = (PFNGLVERTEXATTRIBFORMATPROC) load(userptr, "glVertexAttribFormat"); + glad_glVertexAttribIFormat = (PFNGLVERTEXATTRIBIFORMATPROC) load(userptr, "glVertexAttribIFormat"); + glad_glVertexAttribLFormat = (PFNGLVERTEXATTRIBLFORMATPROC) load(userptr, "glVertexAttribLFormat"); + glad_glVertexBindingDivisor = (PFNGLVERTEXBINDINGDIVISORPROC) load(userptr, "glVertexBindingDivisor"); +} +static void glad_gl_load_GL_VERSION_4_4( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_4_4) return; + glad_glBindBuffersBase = (PFNGLBINDBUFFERSBASEPROC) load(userptr, "glBindBuffersBase"); + glad_glBindBuffersRange = (PFNGLBINDBUFFERSRANGEPROC) load(userptr, "glBindBuffersRange"); + glad_glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC) load(userptr, "glBindImageTextures"); + glad_glBindSamplers = (PFNGLBINDSAMPLERSPROC) load(userptr, "glBindSamplers"); + glad_glBindTextures = (PFNGLBINDTEXTURESPROC) load(userptr, "glBindTextures"); + glad_glBindVertexBuffers = (PFNGLBINDVERTEXBUFFERSPROC) load(userptr, "glBindVertexBuffers"); + glad_glBufferStorage = (PFNGLBUFFERSTORAGEPROC) load(userptr, "glBufferStorage"); + glad_glClearTexImage = (PFNGLCLEARTEXIMAGEPROC) load(userptr, "glClearTexImage"); + glad_glClearTexSubImage = (PFNGLCLEARTEXSUBIMAGEPROC) load(userptr, "glClearTexSubImage"); +} +static void glad_gl_load_GL_VERSION_4_5( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_4_5) return; + glad_glBindTextureUnit = (PFNGLBINDTEXTUREUNITPROC) load(userptr, "glBindTextureUnit"); + glad_glBlitNamedFramebuffer = (PFNGLBLITNAMEDFRAMEBUFFERPROC) load(userptr, "glBlitNamedFramebuffer"); + glad_glCheckNamedFramebufferStatus = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckNamedFramebufferStatus"); + glad_glClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATAPROC) load(userptr, "glClearNamedBufferData"); + glad_glClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATAPROC) load(userptr, "glClearNamedBufferSubData"); + glad_glClearNamedFramebufferfi = (PFNGLCLEARNAMEDFRAMEBUFFERFIPROC) load(userptr, "glClearNamedFramebufferfi"); + glad_glClearNamedFramebufferfv = (PFNGLCLEARNAMEDFRAMEBUFFERFVPROC) load(userptr, "glClearNamedFramebufferfv"); + glad_glClearNamedFramebufferiv = (PFNGLCLEARNAMEDFRAMEBUFFERIVPROC) load(userptr, "glClearNamedFramebufferiv"); + glad_glClearNamedFramebufferuiv = (PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC) load(userptr, "glClearNamedFramebufferuiv"); + glad_glClipControl = (PFNGLCLIPCONTROLPROC) load(userptr, "glClipControl"); + glad_glCompressedTextureSubImage1D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC) load(userptr, "glCompressedTextureSubImage1D"); + glad_glCompressedTextureSubImage2D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC) load(userptr, "glCompressedTextureSubImage2D"); + glad_glCompressedTextureSubImage3D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC) load(userptr, "glCompressedTextureSubImage3D"); + glad_glCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATAPROC) load(userptr, "glCopyNamedBufferSubData"); + glad_glCopyTextureSubImage1D = (PFNGLCOPYTEXTURESUBIMAGE1DPROC) load(userptr, "glCopyTextureSubImage1D"); + glad_glCopyTextureSubImage2D = (PFNGLCOPYTEXTURESUBIMAGE2DPROC) load(userptr, "glCopyTextureSubImage2D"); + glad_glCopyTextureSubImage3D = (PFNGLCOPYTEXTURESUBIMAGE3DPROC) load(userptr, "glCopyTextureSubImage3D"); + glad_glCreateBuffers = (PFNGLCREATEBUFFERSPROC) load(userptr, "glCreateBuffers"); + glad_glCreateFramebuffers = (PFNGLCREATEFRAMEBUFFERSPROC) load(userptr, "glCreateFramebuffers"); + glad_glCreateProgramPipelines = (PFNGLCREATEPROGRAMPIPELINESPROC) load(userptr, "glCreateProgramPipelines"); + glad_glCreateQueries = (PFNGLCREATEQUERIESPROC) load(userptr, "glCreateQueries"); + glad_glCreateRenderbuffers = (PFNGLCREATERENDERBUFFERSPROC) load(userptr, "glCreateRenderbuffers"); + glad_glCreateSamplers = (PFNGLCREATESAMPLERSPROC) load(userptr, "glCreateSamplers"); + glad_glCreateTextures = (PFNGLCREATETEXTURESPROC) load(userptr, "glCreateTextures"); + glad_glCreateTransformFeedbacks = (PFNGLCREATETRANSFORMFEEDBACKSPROC) load(userptr, "glCreateTransformFeedbacks"); + glad_glCreateVertexArrays = (PFNGLCREATEVERTEXARRAYSPROC) load(userptr, "glCreateVertexArrays"); + glad_glDisableVertexArrayAttrib = (PFNGLDISABLEVERTEXARRAYATTRIBPROC) load(userptr, "glDisableVertexArrayAttrib"); + glad_glEnableVertexArrayAttrib = (PFNGLENABLEVERTEXARRAYATTRIBPROC) load(userptr, "glEnableVertexArrayAttrib"); + glad_glFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC) load(userptr, "glFlushMappedNamedBufferRange"); + glad_glGenerateTextureMipmap = (PFNGLGENERATETEXTUREMIPMAPPROC) load(userptr, "glGenerateTextureMipmap"); + glad_glGetCompressedTextureImage = (PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC) load(userptr, "glGetCompressedTextureImage"); + glad_glGetCompressedTextureSubImage = (PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC) load(userptr, "glGetCompressedTextureSubImage"); + glad_glGetGraphicsResetStatus = (PFNGLGETGRAPHICSRESETSTATUSPROC) load(userptr, "glGetGraphicsResetStatus"); + glad_glGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64VPROC) load(userptr, "glGetNamedBufferParameteri64v"); + glad_glGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIVPROC) load(userptr, "glGetNamedBufferParameteriv"); + glad_glGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERVPROC) load(userptr, "glGetNamedBufferPointerv"); + glad_glGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATAPROC) load(userptr, "glGetNamedBufferSubData"); + glad_glGetNamedFramebufferAttachmentParameteriv = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetNamedFramebufferAttachmentParameteriv"); + glad_glGetNamedFramebufferParameteriv = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC) load(userptr, "glGetNamedFramebufferParameteriv"); + glad_glGetNamedRenderbufferParameteriv = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetNamedRenderbufferParameteriv"); + glad_glGetQueryBufferObjecti64v = (PFNGLGETQUERYBUFFEROBJECTI64VPROC) load(userptr, "glGetQueryBufferObjecti64v"); + glad_glGetQueryBufferObjectiv = (PFNGLGETQUERYBUFFEROBJECTIVPROC) load(userptr, "glGetQueryBufferObjectiv"); + glad_glGetQueryBufferObjectui64v = (PFNGLGETQUERYBUFFEROBJECTUI64VPROC) load(userptr, "glGetQueryBufferObjectui64v"); + glad_glGetQueryBufferObjectuiv = (PFNGLGETQUERYBUFFEROBJECTUIVPROC) load(userptr, "glGetQueryBufferObjectuiv"); + glad_glGetTextureImage = (PFNGLGETTEXTUREIMAGEPROC) load(userptr, "glGetTextureImage"); + glad_glGetTextureLevelParameterfv = (PFNGLGETTEXTURELEVELPARAMETERFVPROC) load(userptr, "glGetTextureLevelParameterfv"); + glad_glGetTextureLevelParameteriv = (PFNGLGETTEXTURELEVELPARAMETERIVPROC) load(userptr, "glGetTextureLevelParameteriv"); + glad_glGetTextureParameterIiv = (PFNGLGETTEXTUREPARAMETERIIVPROC) load(userptr, "glGetTextureParameterIiv"); + glad_glGetTextureParameterIuiv = (PFNGLGETTEXTUREPARAMETERIUIVPROC) load(userptr, "glGetTextureParameterIuiv"); + glad_glGetTextureParameterfv = (PFNGLGETTEXTUREPARAMETERFVPROC) load(userptr, "glGetTextureParameterfv"); + glad_glGetTextureParameteriv = (PFNGLGETTEXTUREPARAMETERIVPROC) load(userptr, "glGetTextureParameteriv"); + glad_glGetTextureSubImage = (PFNGLGETTEXTURESUBIMAGEPROC) load(userptr, "glGetTextureSubImage"); + glad_glGetTransformFeedbacki64_v = (PFNGLGETTRANSFORMFEEDBACKI64_VPROC) load(userptr, "glGetTransformFeedbacki64_v"); + glad_glGetTransformFeedbacki_v = (PFNGLGETTRANSFORMFEEDBACKI_VPROC) load(userptr, "glGetTransformFeedbacki_v"); + glad_glGetTransformFeedbackiv = (PFNGLGETTRANSFORMFEEDBACKIVPROC) load(userptr, "glGetTransformFeedbackiv"); + glad_glGetVertexArrayIndexed64iv = (PFNGLGETVERTEXARRAYINDEXED64IVPROC) load(userptr, "glGetVertexArrayIndexed64iv"); + glad_glGetVertexArrayIndexediv = (PFNGLGETVERTEXARRAYINDEXEDIVPROC) load(userptr, "glGetVertexArrayIndexediv"); + glad_glGetVertexArrayiv = (PFNGLGETVERTEXARRAYIVPROC) load(userptr, "glGetVertexArrayiv"); + glad_glGetnColorTable = (PFNGLGETNCOLORTABLEPROC) load(userptr, "glGetnColorTable"); + glad_glGetnCompressedTexImage = (PFNGLGETNCOMPRESSEDTEXIMAGEPROC) load(userptr, "glGetnCompressedTexImage"); + glad_glGetnConvolutionFilter = (PFNGLGETNCONVOLUTIONFILTERPROC) load(userptr, "glGetnConvolutionFilter"); + glad_glGetnHistogram = (PFNGLGETNHISTOGRAMPROC) load(userptr, "glGetnHistogram"); + glad_glGetnMapdv = (PFNGLGETNMAPDVPROC) load(userptr, "glGetnMapdv"); + glad_glGetnMapfv = (PFNGLGETNMAPFVPROC) load(userptr, "glGetnMapfv"); + glad_glGetnMapiv = (PFNGLGETNMAPIVPROC) load(userptr, "glGetnMapiv"); + glad_glGetnMinmax = (PFNGLGETNMINMAXPROC) load(userptr, "glGetnMinmax"); + glad_glGetnPixelMapfv = (PFNGLGETNPIXELMAPFVPROC) load(userptr, "glGetnPixelMapfv"); + glad_glGetnPixelMapuiv = (PFNGLGETNPIXELMAPUIVPROC) load(userptr, "glGetnPixelMapuiv"); + glad_glGetnPixelMapusv = (PFNGLGETNPIXELMAPUSVPROC) load(userptr, "glGetnPixelMapusv"); + glad_glGetnPolygonStipple = (PFNGLGETNPOLYGONSTIPPLEPROC) load(userptr, "glGetnPolygonStipple"); + glad_glGetnSeparableFilter = (PFNGLGETNSEPARABLEFILTERPROC) load(userptr, "glGetnSeparableFilter"); + glad_glGetnTexImage = (PFNGLGETNTEXIMAGEPROC) load(userptr, "glGetnTexImage"); + glad_glGetnUniformdv = (PFNGLGETNUNIFORMDVPROC) load(userptr, "glGetnUniformdv"); + glad_glGetnUniformfv = (PFNGLGETNUNIFORMFVPROC) load(userptr, "glGetnUniformfv"); + glad_glGetnUniformiv = (PFNGLGETNUNIFORMIVPROC) load(userptr, "glGetnUniformiv"); + glad_glGetnUniformuiv = (PFNGLGETNUNIFORMUIVPROC) load(userptr, "glGetnUniformuiv"); + glad_glInvalidateNamedFramebufferData = (PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC) load(userptr, "glInvalidateNamedFramebufferData"); + glad_glInvalidateNamedFramebufferSubData = (PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC) load(userptr, "glInvalidateNamedFramebufferSubData"); + glad_glMapNamedBuffer = (PFNGLMAPNAMEDBUFFERPROC) load(userptr, "glMapNamedBuffer"); + glad_glMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGEPROC) load(userptr, "glMapNamedBufferRange"); + glad_glMemoryBarrierByRegion = (PFNGLMEMORYBARRIERBYREGIONPROC) load(userptr, "glMemoryBarrierByRegion"); + glad_glNamedBufferData = (PFNGLNAMEDBUFFERDATAPROC) load(userptr, "glNamedBufferData"); + glad_glNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGEPROC) load(userptr, "glNamedBufferStorage"); + glad_glNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATAPROC) load(userptr, "glNamedBufferSubData"); + glad_glNamedFramebufferDrawBuffer = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC) load(userptr, "glNamedFramebufferDrawBuffer"); + glad_glNamedFramebufferDrawBuffers = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC) load(userptr, "glNamedFramebufferDrawBuffers"); + glad_glNamedFramebufferParameteri = (PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC) load(userptr, "glNamedFramebufferParameteri"); + glad_glNamedFramebufferReadBuffer = (PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC) load(userptr, "glNamedFramebufferReadBuffer"); + glad_glNamedFramebufferRenderbuffer = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glNamedFramebufferRenderbuffer"); + glad_glNamedFramebufferTexture = (PFNGLNAMEDFRAMEBUFFERTEXTUREPROC) load(userptr, "glNamedFramebufferTexture"); + glad_glNamedFramebufferTextureLayer = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glNamedFramebufferTextureLayer"); + glad_glNamedRenderbufferStorage = (PFNGLNAMEDRENDERBUFFERSTORAGEPROC) load(userptr, "glNamedRenderbufferStorage"); + glad_glNamedRenderbufferStorageMultisample = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glNamedRenderbufferStorageMultisample"); + glad_glReadnPixels = (PFNGLREADNPIXELSPROC) load(userptr, "glReadnPixels"); + glad_glTextureBarrier = (PFNGLTEXTUREBARRIERPROC) load(userptr, "glTextureBarrier"); + glad_glTextureBuffer = (PFNGLTEXTUREBUFFERPROC) load(userptr, "glTextureBuffer"); + glad_glTextureBufferRange = (PFNGLTEXTUREBUFFERRANGEPROC) load(userptr, "glTextureBufferRange"); + glad_glTextureParameterIiv = (PFNGLTEXTUREPARAMETERIIVPROC) load(userptr, "glTextureParameterIiv"); + glad_glTextureParameterIuiv = (PFNGLTEXTUREPARAMETERIUIVPROC) load(userptr, "glTextureParameterIuiv"); + glad_glTextureParameterf = (PFNGLTEXTUREPARAMETERFPROC) load(userptr, "glTextureParameterf"); + glad_glTextureParameterfv = (PFNGLTEXTUREPARAMETERFVPROC) load(userptr, "glTextureParameterfv"); + glad_glTextureParameteri = (PFNGLTEXTUREPARAMETERIPROC) load(userptr, "glTextureParameteri"); + glad_glTextureParameteriv = (PFNGLTEXTUREPARAMETERIVPROC) load(userptr, "glTextureParameteriv"); + glad_glTextureStorage1D = (PFNGLTEXTURESTORAGE1DPROC) load(userptr, "glTextureStorage1D"); + glad_glTextureStorage2D = (PFNGLTEXTURESTORAGE2DPROC) load(userptr, "glTextureStorage2D"); + glad_glTextureStorage2DMultisample = (PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC) load(userptr, "glTextureStorage2DMultisample"); + glad_glTextureStorage3D = (PFNGLTEXTURESTORAGE3DPROC) load(userptr, "glTextureStorage3D"); + glad_glTextureStorage3DMultisample = (PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC) load(userptr, "glTextureStorage3DMultisample"); + glad_glTextureSubImage1D = (PFNGLTEXTURESUBIMAGE1DPROC) load(userptr, "glTextureSubImage1D"); + glad_glTextureSubImage2D = (PFNGLTEXTURESUBIMAGE2DPROC) load(userptr, "glTextureSubImage2D"); + glad_glTextureSubImage3D = (PFNGLTEXTURESUBIMAGE3DPROC) load(userptr, "glTextureSubImage3D"); + glad_glTransformFeedbackBufferBase = (PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC) load(userptr, "glTransformFeedbackBufferBase"); + glad_glTransformFeedbackBufferRange = (PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC) load(userptr, "glTransformFeedbackBufferRange"); + glad_glUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFERPROC) load(userptr, "glUnmapNamedBuffer"); + glad_glVertexArrayAttribBinding = (PFNGLVERTEXARRAYATTRIBBINDINGPROC) load(userptr, "glVertexArrayAttribBinding"); + glad_glVertexArrayAttribFormat = (PFNGLVERTEXARRAYATTRIBFORMATPROC) load(userptr, "glVertexArrayAttribFormat"); + glad_glVertexArrayAttribIFormat = (PFNGLVERTEXARRAYATTRIBIFORMATPROC) load(userptr, "glVertexArrayAttribIFormat"); + glad_glVertexArrayAttribLFormat = (PFNGLVERTEXARRAYATTRIBLFORMATPROC) load(userptr, "glVertexArrayAttribLFormat"); + glad_glVertexArrayBindingDivisor = (PFNGLVERTEXARRAYBINDINGDIVISORPROC) load(userptr, "glVertexArrayBindingDivisor"); + glad_glVertexArrayElementBuffer = (PFNGLVERTEXARRAYELEMENTBUFFERPROC) load(userptr, "glVertexArrayElementBuffer"); + glad_glVertexArrayVertexBuffer = (PFNGLVERTEXARRAYVERTEXBUFFERPROC) load(userptr, "glVertexArrayVertexBuffer"); + glad_glVertexArrayVertexBuffers = (PFNGLVERTEXARRAYVERTEXBUFFERSPROC) load(userptr, "glVertexArrayVertexBuffers"); +} +static void glad_gl_load_GL_VERSION_4_6( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_4_6) return; + glad_glMultiDrawArraysIndirectCount = (PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC) load(userptr, "glMultiDrawArraysIndirectCount"); + glad_glMultiDrawElementsIndirectCount = (PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC) load(userptr, "glMultiDrawElementsIndirectCount"); + glad_glPolygonOffsetClamp = (PFNGLPOLYGONOFFSETCLAMPPROC) load(userptr, "glPolygonOffsetClamp"); + glad_glSpecializeShader = (PFNGLSPECIALIZESHADERPROC) load(userptr, "glSpecializeShader"); +} +static void glad_gl_load_GL_ARB_debug_output( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ARB_debug_output) return; + glad_glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) load(userptr, "glDebugMessageCallbackARB"); + glad_glDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC) load(userptr, "glDebugMessageControlARB"); + glad_glDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC) load(userptr, "glDebugMessageInsertARB"); + glad_glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) load(userptr, "glGetDebugMessageLogARB"); +} +static void glad_gl_load_GL_ARB_fragment_program( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ARB_fragment_program) return; + glad_glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) load(userptr, "glBindProgramARB"); + glad_glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) load(userptr, "glDeleteProgramsARB"); + glad_glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) load(userptr, "glGenProgramsARB"); + glad_glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) load(userptr, "glGetProgramEnvParameterdvARB"); + glad_glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) load(userptr, "glGetProgramEnvParameterfvARB"); + glad_glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) load(userptr, "glGetProgramLocalParameterdvARB"); + glad_glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) load(userptr, "glGetProgramLocalParameterfvARB"); + glad_glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) load(userptr, "glGetProgramStringARB"); + glad_glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) load(userptr, "glGetProgramivARB"); + glad_glIsProgramARB = (PFNGLISPROGRAMARBPROC) load(userptr, "glIsProgramARB"); + glad_glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) load(userptr, "glProgramEnvParameter4dARB"); + glad_glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) load(userptr, "glProgramEnvParameter4dvARB"); + glad_glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) load(userptr, "glProgramEnvParameter4fARB"); + glad_glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) load(userptr, "glProgramEnvParameter4fvARB"); + glad_glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) load(userptr, "glProgramLocalParameter4dARB"); + glad_glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) load(userptr, "glProgramLocalParameter4dvARB"); + glad_glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) load(userptr, "glProgramLocalParameter4fARB"); + glad_glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) load(userptr, "glProgramLocalParameter4fvARB"); + glad_glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) load(userptr, "glProgramStringARB"); +} +static void glad_gl_load_GL_ARB_shader_image_load_store( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ARB_shader_image_load_store) return; + glad_glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC) load(userptr, "glBindImageTexture"); + glad_glMemoryBarrier = (PFNGLMEMORYBARRIERPROC) load(userptr, "glMemoryBarrier"); +} +static void glad_gl_load_GL_ARB_shader_objects( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ARB_shader_objects) return; + glad_glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC) load(userptr, "glAttachObjectARB"); + glad_glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC) load(userptr, "glCompileShaderARB"); + glad_glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC) load(userptr, "glCreateProgramObjectARB"); + glad_glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC) load(userptr, "glCreateShaderObjectARB"); + glad_glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC) load(userptr, "glDeleteObjectARB"); + glad_glDetachObjectARB = (PFNGLDETACHOBJECTARBPROC) load(userptr, "glDetachObjectARB"); + glad_glGetActiveUniformARB = (PFNGLGETACTIVEUNIFORMARBPROC) load(userptr, "glGetActiveUniformARB"); + glad_glGetAttachedObjectsARB = (PFNGLGETATTACHEDOBJECTSARBPROC) load(userptr, "glGetAttachedObjectsARB"); + glad_glGetHandleARB = (PFNGLGETHANDLEARBPROC) load(userptr, "glGetHandleARB"); + glad_glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC) load(userptr, "glGetInfoLogARB"); + glad_glGetObjectParameterfvARB = (PFNGLGETOBJECTPARAMETERFVARBPROC) load(userptr, "glGetObjectParameterfvARB"); + glad_glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC) load(userptr, "glGetObjectParameterivARB"); + glad_glGetShaderSourceARB = (PFNGLGETSHADERSOURCEARBPROC) load(userptr, "glGetShaderSourceARB"); + glad_glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC) load(userptr, "glGetUniformLocationARB"); + glad_glGetUniformfvARB = (PFNGLGETUNIFORMFVARBPROC) load(userptr, "glGetUniformfvARB"); + glad_glGetUniformivARB = (PFNGLGETUNIFORMIVARBPROC) load(userptr, "glGetUniformivARB"); + glad_glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC) load(userptr, "glLinkProgramARB"); + glad_glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC) load(userptr, "glShaderSourceARB"); + glad_glUniform1fARB = (PFNGLUNIFORM1FARBPROC) load(userptr, "glUniform1fARB"); + glad_glUniform1fvARB = (PFNGLUNIFORM1FVARBPROC) load(userptr, "glUniform1fvARB"); + glad_glUniform1iARB = (PFNGLUNIFORM1IARBPROC) load(userptr, "glUniform1iARB"); + glad_glUniform1ivARB = (PFNGLUNIFORM1IVARBPROC) load(userptr, "glUniform1ivARB"); + glad_glUniform2fARB = (PFNGLUNIFORM2FARBPROC) load(userptr, "glUniform2fARB"); + glad_glUniform2fvARB = (PFNGLUNIFORM2FVARBPROC) load(userptr, "glUniform2fvARB"); + glad_glUniform2iARB = (PFNGLUNIFORM2IARBPROC) load(userptr, "glUniform2iARB"); + glad_glUniform2ivARB = (PFNGLUNIFORM2IVARBPROC) load(userptr, "glUniform2ivARB"); + glad_glUniform3fARB = (PFNGLUNIFORM3FARBPROC) load(userptr, "glUniform3fARB"); + glad_glUniform3fvARB = (PFNGLUNIFORM3FVARBPROC) load(userptr, "glUniform3fvARB"); + glad_glUniform3iARB = (PFNGLUNIFORM3IARBPROC) load(userptr, "glUniform3iARB"); + glad_glUniform3ivARB = (PFNGLUNIFORM3IVARBPROC) load(userptr, "glUniform3ivARB"); + glad_glUniform4fARB = (PFNGLUNIFORM4FARBPROC) load(userptr, "glUniform4fARB"); + glad_glUniform4fvARB = (PFNGLUNIFORM4FVARBPROC) load(userptr, "glUniform4fvARB"); + glad_glUniform4iARB = (PFNGLUNIFORM4IARBPROC) load(userptr, "glUniform4iARB"); + glad_glUniform4ivARB = (PFNGLUNIFORM4IVARBPROC) load(userptr, "glUniform4ivARB"); + glad_glUniformMatrix2fvARB = (PFNGLUNIFORMMATRIX2FVARBPROC) load(userptr, "glUniformMatrix2fvARB"); + glad_glUniformMatrix3fvARB = (PFNGLUNIFORMMATRIX3FVARBPROC) load(userptr, "glUniformMatrix3fvARB"); + glad_glUniformMatrix4fvARB = (PFNGLUNIFORMMATRIX4FVARBPROC) load(userptr, "glUniformMatrix4fvARB"); + glad_glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC) load(userptr, "glUseProgramObjectARB"); + glad_glValidateProgramARB = (PFNGLVALIDATEPROGRAMARBPROC) load(userptr, "glValidateProgramARB"); +} +static void glad_gl_load_GL_ARB_shader_storage_buffer_object( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ARB_shader_storage_buffer_object) return; + glad_glShaderStorageBlockBinding = (PFNGLSHADERSTORAGEBLOCKBINDINGPROC) load(userptr, "glShaderStorageBlockBinding"); +} +static void glad_gl_load_GL_ARB_vertex_buffer_object( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ARB_vertex_buffer_object) return; + glad_glBindBufferARB = (PFNGLBINDBUFFERARBPROC) load(userptr, "glBindBufferARB"); + glad_glBufferDataARB = (PFNGLBUFFERDATAARBPROC) load(userptr, "glBufferDataARB"); + glad_glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC) load(userptr, "glBufferSubDataARB"); + glad_glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) load(userptr, "glDeleteBuffersARB"); + glad_glGenBuffersARB = (PFNGLGENBUFFERSARBPROC) load(userptr, "glGenBuffersARB"); + glad_glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC) load(userptr, "glGetBufferParameterivARB"); + glad_glGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC) load(userptr, "glGetBufferPointervARB"); + glad_glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC) load(userptr, "glGetBufferSubDataARB"); + glad_glIsBufferARB = (PFNGLISBUFFERARBPROC) load(userptr, "glIsBufferARB"); + glad_glMapBufferARB = (PFNGLMAPBUFFERARBPROC) load(userptr, "glMapBufferARB"); + glad_glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC) load(userptr, "glUnmapBufferARB"); +} +static void glad_gl_load_GL_ARB_vertex_program( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ARB_vertex_program) return; + glad_glBindProgramARB = (PFNGLBINDPROGRAMARBPROC) load(userptr, "glBindProgramARB"); + glad_glDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC) load(userptr, "glDeleteProgramsARB"); + glad_glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) load(userptr, "glDisableVertexAttribArrayARB"); + glad_glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) load(userptr, "glEnableVertexAttribArrayARB"); + glad_glGenProgramsARB = (PFNGLGENPROGRAMSARBPROC) load(userptr, "glGenProgramsARB"); + glad_glGetProgramEnvParameterdvARB = (PFNGLGETPROGRAMENVPARAMETERDVARBPROC) load(userptr, "glGetProgramEnvParameterdvARB"); + glad_glGetProgramEnvParameterfvARB = (PFNGLGETPROGRAMENVPARAMETERFVARBPROC) load(userptr, "glGetProgramEnvParameterfvARB"); + glad_glGetProgramLocalParameterdvARB = (PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC) load(userptr, "glGetProgramLocalParameterdvARB"); + glad_glGetProgramLocalParameterfvARB = (PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC) load(userptr, "glGetProgramLocalParameterfvARB"); + glad_glGetProgramStringARB = (PFNGLGETPROGRAMSTRINGARBPROC) load(userptr, "glGetProgramStringARB"); + glad_glGetProgramivARB = (PFNGLGETPROGRAMIVARBPROC) load(userptr, "glGetProgramivARB"); + glad_glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) load(userptr, "glGetVertexAttribPointervARB"); + glad_glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) load(userptr, "glGetVertexAttribdvARB"); + glad_glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) load(userptr, "glGetVertexAttribfvARB"); + glad_glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) load(userptr, "glGetVertexAttribivARB"); + glad_glIsProgramARB = (PFNGLISPROGRAMARBPROC) load(userptr, "glIsProgramARB"); + glad_glProgramEnvParameter4dARB = (PFNGLPROGRAMENVPARAMETER4DARBPROC) load(userptr, "glProgramEnvParameter4dARB"); + glad_glProgramEnvParameter4dvARB = (PFNGLPROGRAMENVPARAMETER4DVARBPROC) load(userptr, "glProgramEnvParameter4dvARB"); + glad_glProgramEnvParameter4fARB = (PFNGLPROGRAMENVPARAMETER4FARBPROC) load(userptr, "glProgramEnvParameter4fARB"); + glad_glProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC) load(userptr, "glProgramEnvParameter4fvARB"); + glad_glProgramLocalParameter4dARB = (PFNGLPROGRAMLOCALPARAMETER4DARBPROC) load(userptr, "glProgramLocalParameter4dARB"); + glad_glProgramLocalParameter4dvARB = (PFNGLPROGRAMLOCALPARAMETER4DVARBPROC) load(userptr, "glProgramLocalParameter4dvARB"); + glad_glProgramLocalParameter4fARB = (PFNGLPROGRAMLOCALPARAMETER4FARBPROC) load(userptr, "glProgramLocalParameter4fARB"); + glad_glProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC) load(userptr, "glProgramLocalParameter4fvARB"); + glad_glProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC) load(userptr, "glProgramStringARB"); + glad_glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) load(userptr, "glVertexAttrib1dARB"); + glad_glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) load(userptr, "glVertexAttrib1dvARB"); + glad_glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) load(userptr, "glVertexAttrib1fARB"); + glad_glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) load(userptr, "glVertexAttrib1fvARB"); + glad_glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) load(userptr, "glVertexAttrib1sARB"); + glad_glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) load(userptr, "glVertexAttrib1svARB"); + glad_glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) load(userptr, "glVertexAttrib2dARB"); + glad_glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) load(userptr, "glVertexAttrib2dvARB"); + glad_glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) load(userptr, "glVertexAttrib2fARB"); + glad_glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) load(userptr, "glVertexAttrib2fvARB"); + glad_glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) load(userptr, "glVertexAttrib2sARB"); + glad_glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) load(userptr, "glVertexAttrib2svARB"); + glad_glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) load(userptr, "glVertexAttrib3dARB"); + glad_glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) load(userptr, "glVertexAttrib3dvARB"); + glad_glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) load(userptr, "glVertexAttrib3fARB"); + glad_glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) load(userptr, "glVertexAttrib3fvARB"); + glad_glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) load(userptr, "glVertexAttrib3sARB"); + glad_glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) load(userptr, "glVertexAttrib3svARB"); + glad_glVertexAttrib4NbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) load(userptr, "glVertexAttrib4NbvARB"); + glad_glVertexAttrib4NivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) load(userptr, "glVertexAttrib4NivARB"); + glad_glVertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) load(userptr, "glVertexAttrib4NsvARB"); + glad_glVertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) load(userptr, "glVertexAttrib4NubARB"); + glad_glVertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) load(userptr, "glVertexAttrib4NubvARB"); + glad_glVertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) load(userptr, "glVertexAttrib4NuivARB"); + glad_glVertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) load(userptr, "glVertexAttrib4NusvARB"); + glad_glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) load(userptr, "glVertexAttrib4bvARB"); + glad_glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) load(userptr, "glVertexAttrib4dARB"); + glad_glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) load(userptr, "glVertexAttrib4dvARB"); + glad_glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) load(userptr, "glVertexAttrib4fARB"); + glad_glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) load(userptr, "glVertexAttrib4fvARB"); + glad_glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) load(userptr, "glVertexAttrib4ivARB"); + glad_glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) load(userptr, "glVertexAttrib4sARB"); + glad_glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) load(userptr, "glVertexAttrib4svARB"); + glad_glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) load(userptr, "glVertexAttrib4ubvARB"); + glad_glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) load(userptr, "glVertexAttrib4uivARB"); + glad_glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) load(userptr, "glVertexAttrib4usvARB"); + glad_glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) load(userptr, "glVertexAttribPointerARB"); +} +static void glad_gl_load_GL_ARB_vertex_shader( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ARB_vertex_shader) return; + glad_glBindAttribLocationARB = (PFNGLBINDATTRIBLOCATIONARBPROC) load(userptr, "glBindAttribLocationARB"); + glad_glDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC) load(userptr, "glDisableVertexAttribArrayARB"); + glad_glEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC) load(userptr, "glEnableVertexAttribArrayARB"); + glad_glGetActiveAttribARB = (PFNGLGETACTIVEATTRIBARBPROC) load(userptr, "glGetActiveAttribARB"); + glad_glGetAttribLocationARB = (PFNGLGETATTRIBLOCATIONARBPROC) load(userptr, "glGetAttribLocationARB"); + glad_glGetVertexAttribPointervARB = (PFNGLGETVERTEXATTRIBPOINTERVARBPROC) load(userptr, "glGetVertexAttribPointervARB"); + glad_glGetVertexAttribdvARB = (PFNGLGETVERTEXATTRIBDVARBPROC) load(userptr, "glGetVertexAttribdvARB"); + glad_glGetVertexAttribfvARB = (PFNGLGETVERTEXATTRIBFVARBPROC) load(userptr, "glGetVertexAttribfvARB"); + glad_glGetVertexAttribivARB = (PFNGLGETVERTEXATTRIBIVARBPROC) load(userptr, "glGetVertexAttribivARB"); + glad_glVertexAttrib1dARB = (PFNGLVERTEXATTRIB1DARBPROC) load(userptr, "glVertexAttrib1dARB"); + glad_glVertexAttrib1dvARB = (PFNGLVERTEXATTRIB1DVARBPROC) load(userptr, "glVertexAttrib1dvARB"); + glad_glVertexAttrib1fARB = (PFNGLVERTEXATTRIB1FARBPROC) load(userptr, "glVertexAttrib1fARB"); + glad_glVertexAttrib1fvARB = (PFNGLVERTEXATTRIB1FVARBPROC) load(userptr, "glVertexAttrib1fvARB"); + glad_glVertexAttrib1sARB = (PFNGLVERTEXATTRIB1SARBPROC) load(userptr, "glVertexAttrib1sARB"); + glad_glVertexAttrib1svARB = (PFNGLVERTEXATTRIB1SVARBPROC) load(userptr, "glVertexAttrib1svARB"); + glad_glVertexAttrib2dARB = (PFNGLVERTEXATTRIB2DARBPROC) load(userptr, "glVertexAttrib2dARB"); + glad_glVertexAttrib2dvARB = (PFNGLVERTEXATTRIB2DVARBPROC) load(userptr, "glVertexAttrib2dvARB"); + glad_glVertexAttrib2fARB = (PFNGLVERTEXATTRIB2FARBPROC) load(userptr, "glVertexAttrib2fARB"); + glad_glVertexAttrib2fvARB = (PFNGLVERTEXATTRIB2FVARBPROC) load(userptr, "glVertexAttrib2fvARB"); + glad_glVertexAttrib2sARB = (PFNGLVERTEXATTRIB2SARBPROC) load(userptr, "glVertexAttrib2sARB"); + glad_glVertexAttrib2svARB = (PFNGLVERTEXATTRIB2SVARBPROC) load(userptr, "glVertexAttrib2svARB"); + glad_glVertexAttrib3dARB = (PFNGLVERTEXATTRIB3DARBPROC) load(userptr, "glVertexAttrib3dARB"); + glad_glVertexAttrib3dvARB = (PFNGLVERTEXATTRIB3DVARBPROC) load(userptr, "glVertexAttrib3dvARB"); + glad_glVertexAttrib3fARB = (PFNGLVERTEXATTRIB3FARBPROC) load(userptr, "glVertexAttrib3fARB"); + glad_glVertexAttrib3fvARB = (PFNGLVERTEXATTRIB3FVARBPROC) load(userptr, "glVertexAttrib3fvARB"); + glad_glVertexAttrib3sARB = (PFNGLVERTEXATTRIB3SARBPROC) load(userptr, "glVertexAttrib3sARB"); + glad_glVertexAttrib3svARB = (PFNGLVERTEXATTRIB3SVARBPROC) load(userptr, "glVertexAttrib3svARB"); + glad_glVertexAttrib4NbvARB = (PFNGLVERTEXATTRIB4NBVARBPROC) load(userptr, "glVertexAttrib4NbvARB"); + glad_glVertexAttrib4NivARB = (PFNGLVERTEXATTRIB4NIVARBPROC) load(userptr, "glVertexAttrib4NivARB"); + glad_glVertexAttrib4NsvARB = (PFNGLVERTEXATTRIB4NSVARBPROC) load(userptr, "glVertexAttrib4NsvARB"); + glad_glVertexAttrib4NubARB = (PFNGLVERTEXATTRIB4NUBARBPROC) load(userptr, "glVertexAttrib4NubARB"); + glad_glVertexAttrib4NubvARB = (PFNGLVERTEXATTRIB4NUBVARBPROC) load(userptr, "glVertexAttrib4NubvARB"); + glad_glVertexAttrib4NuivARB = (PFNGLVERTEXATTRIB4NUIVARBPROC) load(userptr, "glVertexAttrib4NuivARB"); + glad_glVertexAttrib4NusvARB = (PFNGLVERTEXATTRIB4NUSVARBPROC) load(userptr, "glVertexAttrib4NusvARB"); + glad_glVertexAttrib4bvARB = (PFNGLVERTEXATTRIB4BVARBPROC) load(userptr, "glVertexAttrib4bvARB"); + glad_glVertexAttrib4dARB = (PFNGLVERTEXATTRIB4DARBPROC) load(userptr, "glVertexAttrib4dARB"); + glad_glVertexAttrib4dvARB = (PFNGLVERTEXATTRIB4DVARBPROC) load(userptr, "glVertexAttrib4dvARB"); + glad_glVertexAttrib4fARB = (PFNGLVERTEXATTRIB4FARBPROC) load(userptr, "glVertexAttrib4fARB"); + glad_glVertexAttrib4fvARB = (PFNGLVERTEXATTRIB4FVARBPROC) load(userptr, "glVertexAttrib4fvARB"); + glad_glVertexAttrib4ivARB = (PFNGLVERTEXATTRIB4IVARBPROC) load(userptr, "glVertexAttrib4ivARB"); + glad_glVertexAttrib4sARB = (PFNGLVERTEXATTRIB4SARBPROC) load(userptr, "glVertexAttrib4sARB"); + glad_glVertexAttrib4svARB = (PFNGLVERTEXATTRIB4SVARBPROC) load(userptr, "glVertexAttrib4svARB"); + glad_glVertexAttrib4ubvARB = (PFNGLVERTEXATTRIB4UBVARBPROC) load(userptr, "glVertexAttrib4ubvARB"); + glad_glVertexAttrib4uivARB = (PFNGLVERTEXATTRIB4UIVARBPROC) load(userptr, "glVertexAttrib4uivARB"); + glad_glVertexAttrib4usvARB = (PFNGLVERTEXATTRIB4USVARBPROC) load(userptr, "glVertexAttrib4usvARB"); + glad_glVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC) load(userptr, "glVertexAttribPointerARB"); +} +static void glad_gl_load_GL_ARB_vertex_type_2_10_10_10_rev( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ARB_vertex_type_2_10_10_10_rev) return; + glad_glColorP3ui = (PFNGLCOLORP3UIPROC) load(userptr, "glColorP3ui"); + glad_glColorP3uiv = (PFNGLCOLORP3UIVPROC) load(userptr, "glColorP3uiv"); + glad_glColorP4ui = (PFNGLCOLORP4UIPROC) load(userptr, "glColorP4ui"); + glad_glColorP4uiv = (PFNGLCOLORP4UIVPROC) load(userptr, "glColorP4uiv"); + glad_glMultiTexCoordP1ui = (PFNGLMULTITEXCOORDP1UIPROC) load(userptr, "glMultiTexCoordP1ui"); + glad_glMultiTexCoordP1uiv = (PFNGLMULTITEXCOORDP1UIVPROC) load(userptr, "glMultiTexCoordP1uiv"); + glad_glMultiTexCoordP2ui = (PFNGLMULTITEXCOORDP2UIPROC) load(userptr, "glMultiTexCoordP2ui"); + glad_glMultiTexCoordP2uiv = (PFNGLMULTITEXCOORDP2UIVPROC) load(userptr, "glMultiTexCoordP2uiv"); + glad_glMultiTexCoordP3ui = (PFNGLMULTITEXCOORDP3UIPROC) load(userptr, "glMultiTexCoordP3ui"); + glad_glMultiTexCoordP3uiv = (PFNGLMULTITEXCOORDP3UIVPROC) load(userptr, "glMultiTexCoordP3uiv"); + glad_glMultiTexCoordP4ui = (PFNGLMULTITEXCOORDP4UIPROC) load(userptr, "glMultiTexCoordP4ui"); + glad_glMultiTexCoordP4uiv = (PFNGLMULTITEXCOORDP4UIVPROC) load(userptr, "glMultiTexCoordP4uiv"); + glad_glNormalP3ui = (PFNGLNORMALP3UIPROC) load(userptr, "glNormalP3ui"); + glad_glNormalP3uiv = (PFNGLNORMALP3UIVPROC) load(userptr, "glNormalP3uiv"); + glad_glSecondaryColorP3ui = (PFNGLSECONDARYCOLORP3UIPROC) load(userptr, "glSecondaryColorP3ui"); + glad_glSecondaryColorP3uiv = (PFNGLSECONDARYCOLORP3UIVPROC) load(userptr, "glSecondaryColorP3uiv"); + glad_glTexCoordP1ui = (PFNGLTEXCOORDP1UIPROC) load(userptr, "glTexCoordP1ui"); + glad_glTexCoordP1uiv = (PFNGLTEXCOORDP1UIVPROC) load(userptr, "glTexCoordP1uiv"); + glad_glTexCoordP2ui = (PFNGLTEXCOORDP2UIPROC) load(userptr, "glTexCoordP2ui"); + glad_glTexCoordP2uiv = (PFNGLTEXCOORDP2UIVPROC) load(userptr, "glTexCoordP2uiv"); + glad_glTexCoordP3ui = (PFNGLTEXCOORDP3UIPROC) load(userptr, "glTexCoordP3ui"); + glad_glTexCoordP3uiv = (PFNGLTEXCOORDP3UIVPROC) load(userptr, "glTexCoordP3uiv"); + glad_glTexCoordP4ui = (PFNGLTEXCOORDP4UIPROC) load(userptr, "glTexCoordP4ui"); + glad_glTexCoordP4uiv = (PFNGLTEXCOORDP4UIVPROC) load(userptr, "glTexCoordP4uiv"); + glad_glVertexAttribP1ui = (PFNGLVERTEXATTRIBP1UIPROC) load(userptr, "glVertexAttribP1ui"); + glad_glVertexAttribP1uiv = (PFNGLVERTEXATTRIBP1UIVPROC) load(userptr, "glVertexAttribP1uiv"); + glad_glVertexAttribP2ui = (PFNGLVERTEXATTRIBP2UIPROC) load(userptr, "glVertexAttribP2ui"); + glad_glVertexAttribP2uiv = (PFNGLVERTEXATTRIBP2UIVPROC) load(userptr, "glVertexAttribP2uiv"); + glad_glVertexAttribP3ui = (PFNGLVERTEXATTRIBP3UIPROC) load(userptr, "glVertexAttribP3ui"); + glad_glVertexAttribP3uiv = (PFNGLVERTEXATTRIBP3UIVPROC) load(userptr, "glVertexAttribP3uiv"); + glad_glVertexAttribP4ui = (PFNGLVERTEXATTRIBP4UIPROC) load(userptr, "glVertexAttribP4ui"); + glad_glVertexAttribP4uiv = (PFNGLVERTEXATTRIBP4UIVPROC) load(userptr, "glVertexAttribP4uiv"); + glad_glVertexP2ui = (PFNGLVERTEXP2UIPROC) load(userptr, "glVertexP2ui"); + glad_glVertexP2uiv = (PFNGLVERTEXP2UIVPROC) load(userptr, "glVertexP2uiv"); + glad_glVertexP3ui = (PFNGLVERTEXP3UIPROC) load(userptr, "glVertexP3ui"); + glad_glVertexP3uiv = (PFNGLVERTEXP3UIVPROC) load(userptr, "glVertexP3uiv"); + glad_glVertexP4ui = (PFNGLVERTEXP4UIPROC) load(userptr, "glVertexP4ui"); + glad_glVertexP4uiv = (PFNGLVERTEXP4UIVPROC) load(userptr, "glVertexP4uiv"); +} +static void glad_gl_load_GL_EXT_direct_state_access( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_EXT_direct_state_access) return; + glad_glBindMultiTextureEXT = (PFNGLBINDMULTITEXTUREEXTPROC) load(userptr, "glBindMultiTextureEXT"); + glad_glCheckNamedFramebufferStatusEXT = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSEXTPROC) load(userptr, "glCheckNamedFramebufferStatusEXT"); + glad_glClearNamedBufferDataEXT = (PFNGLCLEARNAMEDBUFFERDATAEXTPROC) load(userptr, "glClearNamedBufferDataEXT"); + glad_glClearNamedBufferSubDataEXT = (PFNGLCLEARNAMEDBUFFERSUBDATAEXTPROC) load(userptr, "glClearNamedBufferSubDataEXT"); + glad_glClientAttribDefaultEXT = (PFNGLCLIENTATTRIBDEFAULTEXTPROC) load(userptr, "glClientAttribDefaultEXT"); + glad_glCompressedMultiTexImage1DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE1DEXTPROC) load(userptr, "glCompressedMultiTexImage1DEXT"); + glad_glCompressedMultiTexImage2DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE2DEXTPROC) load(userptr, "glCompressedMultiTexImage2DEXT"); + glad_glCompressedMultiTexImage3DEXT = (PFNGLCOMPRESSEDMULTITEXIMAGE3DEXTPROC) load(userptr, "glCompressedMultiTexImage3DEXT"); + glad_glCompressedMultiTexSubImage1DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE1DEXTPROC) load(userptr, "glCompressedMultiTexSubImage1DEXT"); + glad_glCompressedMultiTexSubImage2DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE2DEXTPROC) load(userptr, "glCompressedMultiTexSubImage2DEXT"); + glad_glCompressedMultiTexSubImage3DEXT = (PFNGLCOMPRESSEDMULTITEXSUBIMAGE3DEXTPROC) load(userptr, "glCompressedMultiTexSubImage3DEXT"); + glad_glCompressedTextureImage1DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE1DEXTPROC) load(userptr, "glCompressedTextureImage1DEXT"); + glad_glCompressedTextureImage2DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE2DEXTPROC) load(userptr, "glCompressedTextureImage2DEXT"); + glad_glCompressedTextureImage3DEXT = (PFNGLCOMPRESSEDTEXTUREIMAGE3DEXTPROC) load(userptr, "glCompressedTextureImage3DEXT"); + glad_glCompressedTextureSubImage1DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DEXTPROC) load(userptr, "glCompressedTextureSubImage1DEXT"); + glad_glCompressedTextureSubImage2DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DEXTPROC) load(userptr, "glCompressedTextureSubImage2DEXT"); + glad_glCompressedTextureSubImage3DEXT = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DEXTPROC) load(userptr, "glCompressedTextureSubImage3DEXT"); + glad_glCopyMultiTexImage1DEXT = (PFNGLCOPYMULTITEXIMAGE1DEXTPROC) load(userptr, "glCopyMultiTexImage1DEXT"); + glad_glCopyMultiTexImage2DEXT = (PFNGLCOPYMULTITEXIMAGE2DEXTPROC) load(userptr, "glCopyMultiTexImage2DEXT"); + glad_glCopyMultiTexSubImage1DEXT = (PFNGLCOPYMULTITEXSUBIMAGE1DEXTPROC) load(userptr, "glCopyMultiTexSubImage1DEXT"); + glad_glCopyMultiTexSubImage2DEXT = (PFNGLCOPYMULTITEXSUBIMAGE2DEXTPROC) load(userptr, "glCopyMultiTexSubImage2DEXT"); + glad_glCopyMultiTexSubImage3DEXT = (PFNGLCOPYMULTITEXSUBIMAGE3DEXTPROC) load(userptr, "glCopyMultiTexSubImage3DEXT"); + glad_glCopyTextureImage1DEXT = (PFNGLCOPYTEXTUREIMAGE1DEXTPROC) load(userptr, "glCopyTextureImage1DEXT"); + glad_glCopyTextureImage2DEXT = (PFNGLCOPYTEXTUREIMAGE2DEXTPROC) load(userptr, "glCopyTextureImage2DEXT"); + glad_glCopyTextureSubImage1DEXT = (PFNGLCOPYTEXTURESUBIMAGE1DEXTPROC) load(userptr, "glCopyTextureSubImage1DEXT"); + glad_glCopyTextureSubImage2DEXT = (PFNGLCOPYTEXTURESUBIMAGE2DEXTPROC) load(userptr, "glCopyTextureSubImage2DEXT"); + glad_glCopyTextureSubImage3DEXT = (PFNGLCOPYTEXTURESUBIMAGE3DEXTPROC) load(userptr, "glCopyTextureSubImage3DEXT"); + glad_glDisableClientStateIndexedEXT = (PFNGLDISABLECLIENTSTATEINDEXEDEXTPROC) load(userptr, "glDisableClientStateIndexedEXT"); + glad_glDisableClientStateiEXT = (PFNGLDISABLECLIENTSTATEIEXTPROC) load(userptr, "glDisableClientStateiEXT"); + glad_glDisableIndexedEXT = (PFNGLDISABLEINDEXEDEXTPROC) load(userptr, "glDisableIndexedEXT"); + glad_glDisableVertexArrayAttribEXT = (PFNGLDISABLEVERTEXARRAYATTRIBEXTPROC) load(userptr, "glDisableVertexArrayAttribEXT"); + glad_glDisableVertexArrayEXT = (PFNGLDISABLEVERTEXARRAYEXTPROC) load(userptr, "glDisableVertexArrayEXT"); + glad_glEnableClientStateIndexedEXT = (PFNGLENABLECLIENTSTATEINDEXEDEXTPROC) load(userptr, "glEnableClientStateIndexedEXT"); + glad_glEnableClientStateiEXT = (PFNGLENABLECLIENTSTATEIEXTPROC) load(userptr, "glEnableClientStateiEXT"); + glad_glEnableIndexedEXT = (PFNGLENABLEINDEXEDEXTPROC) load(userptr, "glEnableIndexedEXT"); + glad_glEnableVertexArrayAttribEXT = (PFNGLENABLEVERTEXARRAYATTRIBEXTPROC) load(userptr, "glEnableVertexArrayAttribEXT"); + glad_glEnableVertexArrayEXT = (PFNGLENABLEVERTEXARRAYEXTPROC) load(userptr, "glEnableVertexArrayEXT"); + glad_glFlushMappedNamedBufferRangeEXT = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEEXTPROC) load(userptr, "glFlushMappedNamedBufferRangeEXT"); + glad_glFramebufferDrawBufferEXT = (PFNGLFRAMEBUFFERDRAWBUFFEREXTPROC) load(userptr, "glFramebufferDrawBufferEXT"); + glad_glFramebufferDrawBuffersEXT = (PFNGLFRAMEBUFFERDRAWBUFFERSEXTPROC) load(userptr, "glFramebufferDrawBuffersEXT"); + glad_glFramebufferReadBufferEXT = (PFNGLFRAMEBUFFERREADBUFFEREXTPROC) load(userptr, "glFramebufferReadBufferEXT"); + glad_glGenerateMultiTexMipmapEXT = (PFNGLGENERATEMULTITEXMIPMAPEXTPROC) load(userptr, "glGenerateMultiTexMipmapEXT"); + glad_glGenerateTextureMipmapEXT = (PFNGLGENERATETEXTUREMIPMAPEXTPROC) load(userptr, "glGenerateTextureMipmapEXT"); + glad_glGetBooleanIndexedvEXT = (PFNGLGETBOOLEANINDEXEDVEXTPROC) load(userptr, "glGetBooleanIndexedvEXT"); + glad_glGetCompressedMultiTexImageEXT = (PFNGLGETCOMPRESSEDMULTITEXIMAGEEXTPROC) load(userptr, "glGetCompressedMultiTexImageEXT"); + glad_glGetCompressedTextureImageEXT = (PFNGLGETCOMPRESSEDTEXTUREIMAGEEXTPROC) load(userptr, "glGetCompressedTextureImageEXT"); + glad_glGetDoubleIndexedvEXT = (PFNGLGETDOUBLEINDEXEDVEXTPROC) load(userptr, "glGetDoubleIndexedvEXT"); + glad_glGetDoublei_vEXT = (PFNGLGETDOUBLEI_VEXTPROC) load(userptr, "glGetDoublei_vEXT"); + glad_glGetFloatIndexedvEXT = (PFNGLGETFLOATINDEXEDVEXTPROC) load(userptr, "glGetFloatIndexedvEXT"); + glad_glGetFloati_vEXT = (PFNGLGETFLOATI_VEXTPROC) load(userptr, "glGetFloati_vEXT"); + glad_glGetFramebufferParameterivEXT = (PFNGLGETFRAMEBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetFramebufferParameterivEXT"); + glad_glGetIntegerIndexedvEXT = (PFNGLGETINTEGERINDEXEDVEXTPROC) load(userptr, "glGetIntegerIndexedvEXT"); + glad_glGetMultiTexEnvfvEXT = (PFNGLGETMULTITEXENVFVEXTPROC) load(userptr, "glGetMultiTexEnvfvEXT"); + glad_glGetMultiTexEnvivEXT = (PFNGLGETMULTITEXENVIVEXTPROC) load(userptr, "glGetMultiTexEnvivEXT"); + glad_glGetMultiTexGendvEXT = (PFNGLGETMULTITEXGENDVEXTPROC) load(userptr, "glGetMultiTexGendvEXT"); + glad_glGetMultiTexGenfvEXT = (PFNGLGETMULTITEXGENFVEXTPROC) load(userptr, "glGetMultiTexGenfvEXT"); + glad_glGetMultiTexGenivEXT = (PFNGLGETMULTITEXGENIVEXTPROC) load(userptr, "glGetMultiTexGenivEXT"); + glad_glGetMultiTexImageEXT = (PFNGLGETMULTITEXIMAGEEXTPROC) load(userptr, "glGetMultiTexImageEXT"); + glad_glGetMultiTexLevelParameterfvEXT = (PFNGLGETMULTITEXLEVELPARAMETERFVEXTPROC) load(userptr, "glGetMultiTexLevelParameterfvEXT"); + glad_glGetMultiTexLevelParameterivEXT = (PFNGLGETMULTITEXLEVELPARAMETERIVEXTPROC) load(userptr, "glGetMultiTexLevelParameterivEXT"); + glad_glGetMultiTexParameterIivEXT = (PFNGLGETMULTITEXPARAMETERIIVEXTPROC) load(userptr, "glGetMultiTexParameterIivEXT"); + glad_glGetMultiTexParameterIuivEXT = (PFNGLGETMULTITEXPARAMETERIUIVEXTPROC) load(userptr, "glGetMultiTexParameterIuivEXT"); + glad_glGetMultiTexParameterfvEXT = (PFNGLGETMULTITEXPARAMETERFVEXTPROC) load(userptr, "glGetMultiTexParameterfvEXT"); + glad_glGetMultiTexParameterivEXT = (PFNGLGETMULTITEXPARAMETERIVEXTPROC) load(userptr, "glGetMultiTexParameterivEXT"); + glad_glGetNamedBufferParameterivEXT = (PFNGLGETNAMEDBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetNamedBufferParameterivEXT"); + glad_glGetNamedBufferPointervEXT = (PFNGLGETNAMEDBUFFERPOINTERVEXTPROC) load(userptr, "glGetNamedBufferPointervEXT"); + glad_glGetNamedBufferSubDataEXT = (PFNGLGETNAMEDBUFFERSUBDATAEXTPROC) load(userptr, "glGetNamedBufferSubDataEXT"); + glad_glGetNamedFramebufferAttachmentParameterivEXT = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) load(userptr, "glGetNamedFramebufferAttachmentParameterivEXT"); + glad_glGetNamedFramebufferParameterivEXT = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetNamedFramebufferParameterivEXT"); + glad_glGetNamedProgramLocalParameterIivEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERIIVEXTPROC) load(userptr, "glGetNamedProgramLocalParameterIivEXT"); + glad_glGetNamedProgramLocalParameterIuivEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERIUIVEXTPROC) load(userptr, "glGetNamedProgramLocalParameterIuivEXT"); + glad_glGetNamedProgramLocalParameterdvEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERDVEXTPROC) load(userptr, "glGetNamedProgramLocalParameterdvEXT"); + glad_glGetNamedProgramLocalParameterfvEXT = (PFNGLGETNAMEDPROGRAMLOCALPARAMETERFVEXTPROC) load(userptr, "glGetNamedProgramLocalParameterfvEXT"); + glad_glGetNamedProgramStringEXT = (PFNGLGETNAMEDPROGRAMSTRINGEXTPROC) load(userptr, "glGetNamedProgramStringEXT"); + glad_glGetNamedProgramivEXT = (PFNGLGETNAMEDPROGRAMIVEXTPROC) load(userptr, "glGetNamedProgramivEXT"); + glad_glGetNamedRenderbufferParameterivEXT = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetNamedRenderbufferParameterivEXT"); + glad_glGetPointerIndexedvEXT = (PFNGLGETPOINTERINDEXEDVEXTPROC) load(userptr, "glGetPointerIndexedvEXT"); + glad_glGetPointeri_vEXT = (PFNGLGETPOINTERI_VEXTPROC) load(userptr, "glGetPointeri_vEXT"); + glad_glGetTextureImageEXT = (PFNGLGETTEXTUREIMAGEEXTPROC) load(userptr, "glGetTextureImageEXT"); + glad_glGetTextureLevelParameterfvEXT = (PFNGLGETTEXTURELEVELPARAMETERFVEXTPROC) load(userptr, "glGetTextureLevelParameterfvEXT"); + glad_glGetTextureLevelParameterivEXT = (PFNGLGETTEXTURELEVELPARAMETERIVEXTPROC) load(userptr, "glGetTextureLevelParameterivEXT"); + glad_glGetTextureParameterIivEXT = (PFNGLGETTEXTUREPARAMETERIIVEXTPROC) load(userptr, "glGetTextureParameterIivEXT"); + glad_glGetTextureParameterIuivEXT = (PFNGLGETTEXTUREPARAMETERIUIVEXTPROC) load(userptr, "glGetTextureParameterIuivEXT"); + glad_glGetTextureParameterfvEXT = (PFNGLGETTEXTUREPARAMETERFVEXTPROC) load(userptr, "glGetTextureParameterfvEXT"); + glad_glGetTextureParameterivEXT = (PFNGLGETTEXTUREPARAMETERIVEXTPROC) load(userptr, "glGetTextureParameterivEXT"); + glad_glGetVertexArrayIntegeri_vEXT = (PFNGLGETVERTEXARRAYINTEGERI_VEXTPROC) load(userptr, "glGetVertexArrayIntegeri_vEXT"); + glad_glGetVertexArrayIntegervEXT = (PFNGLGETVERTEXARRAYINTEGERVEXTPROC) load(userptr, "glGetVertexArrayIntegervEXT"); + glad_glGetVertexArrayPointeri_vEXT = (PFNGLGETVERTEXARRAYPOINTERI_VEXTPROC) load(userptr, "glGetVertexArrayPointeri_vEXT"); + glad_glGetVertexArrayPointervEXT = (PFNGLGETVERTEXARRAYPOINTERVEXTPROC) load(userptr, "glGetVertexArrayPointervEXT"); + glad_glIsEnabledIndexedEXT = (PFNGLISENABLEDINDEXEDEXTPROC) load(userptr, "glIsEnabledIndexedEXT"); + glad_glMapNamedBufferEXT = (PFNGLMAPNAMEDBUFFEREXTPROC) load(userptr, "glMapNamedBufferEXT"); + glad_glMapNamedBufferRangeEXT = (PFNGLMAPNAMEDBUFFERRANGEEXTPROC) load(userptr, "glMapNamedBufferRangeEXT"); + glad_glMatrixFrustumEXT = (PFNGLMATRIXFRUSTUMEXTPROC) load(userptr, "glMatrixFrustumEXT"); + glad_glMatrixLoadIdentityEXT = (PFNGLMATRIXLOADIDENTITYEXTPROC) load(userptr, "glMatrixLoadIdentityEXT"); + glad_glMatrixLoadTransposedEXT = (PFNGLMATRIXLOADTRANSPOSEDEXTPROC) load(userptr, "glMatrixLoadTransposedEXT"); + glad_glMatrixLoadTransposefEXT = (PFNGLMATRIXLOADTRANSPOSEFEXTPROC) load(userptr, "glMatrixLoadTransposefEXT"); + glad_glMatrixLoaddEXT = (PFNGLMATRIXLOADDEXTPROC) load(userptr, "glMatrixLoaddEXT"); + glad_glMatrixLoadfEXT = (PFNGLMATRIXLOADFEXTPROC) load(userptr, "glMatrixLoadfEXT"); + glad_glMatrixMultTransposedEXT = (PFNGLMATRIXMULTTRANSPOSEDEXTPROC) load(userptr, "glMatrixMultTransposedEXT"); + glad_glMatrixMultTransposefEXT = (PFNGLMATRIXMULTTRANSPOSEFEXTPROC) load(userptr, "glMatrixMultTransposefEXT"); + glad_glMatrixMultdEXT = (PFNGLMATRIXMULTDEXTPROC) load(userptr, "glMatrixMultdEXT"); + glad_glMatrixMultfEXT = (PFNGLMATRIXMULTFEXTPROC) load(userptr, "glMatrixMultfEXT"); + glad_glMatrixOrthoEXT = (PFNGLMATRIXORTHOEXTPROC) load(userptr, "glMatrixOrthoEXT"); + glad_glMatrixPopEXT = (PFNGLMATRIXPOPEXTPROC) load(userptr, "glMatrixPopEXT"); + glad_glMatrixPushEXT = (PFNGLMATRIXPUSHEXTPROC) load(userptr, "glMatrixPushEXT"); + glad_glMatrixRotatedEXT = (PFNGLMATRIXROTATEDEXTPROC) load(userptr, "glMatrixRotatedEXT"); + glad_glMatrixRotatefEXT = (PFNGLMATRIXROTATEFEXTPROC) load(userptr, "glMatrixRotatefEXT"); + glad_glMatrixScaledEXT = (PFNGLMATRIXSCALEDEXTPROC) load(userptr, "glMatrixScaledEXT"); + glad_glMatrixScalefEXT = (PFNGLMATRIXSCALEFEXTPROC) load(userptr, "glMatrixScalefEXT"); + glad_glMatrixTranslatedEXT = (PFNGLMATRIXTRANSLATEDEXTPROC) load(userptr, "glMatrixTranslatedEXT"); + glad_glMatrixTranslatefEXT = (PFNGLMATRIXTRANSLATEFEXTPROC) load(userptr, "glMatrixTranslatefEXT"); + glad_glMultiTexBufferEXT = (PFNGLMULTITEXBUFFEREXTPROC) load(userptr, "glMultiTexBufferEXT"); + glad_glMultiTexCoordPointerEXT = (PFNGLMULTITEXCOORDPOINTEREXTPROC) load(userptr, "glMultiTexCoordPointerEXT"); + glad_glMultiTexEnvfEXT = (PFNGLMULTITEXENVFEXTPROC) load(userptr, "glMultiTexEnvfEXT"); + glad_glMultiTexEnvfvEXT = (PFNGLMULTITEXENVFVEXTPROC) load(userptr, "glMultiTexEnvfvEXT"); + glad_glMultiTexEnviEXT = (PFNGLMULTITEXENVIEXTPROC) load(userptr, "glMultiTexEnviEXT"); + glad_glMultiTexEnvivEXT = (PFNGLMULTITEXENVIVEXTPROC) load(userptr, "glMultiTexEnvivEXT"); + glad_glMultiTexGendEXT = (PFNGLMULTITEXGENDEXTPROC) load(userptr, "glMultiTexGendEXT"); + glad_glMultiTexGendvEXT = (PFNGLMULTITEXGENDVEXTPROC) load(userptr, "glMultiTexGendvEXT"); + glad_glMultiTexGenfEXT = (PFNGLMULTITEXGENFEXTPROC) load(userptr, "glMultiTexGenfEXT"); + glad_glMultiTexGenfvEXT = (PFNGLMULTITEXGENFVEXTPROC) load(userptr, "glMultiTexGenfvEXT"); + glad_glMultiTexGeniEXT = (PFNGLMULTITEXGENIEXTPROC) load(userptr, "glMultiTexGeniEXT"); + glad_glMultiTexGenivEXT = (PFNGLMULTITEXGENIVEXTPROC) load(userptr, "glMultiTexGenivEXT"); + glad_glMultiTexImage1DEXT = (PFNGLMULTITEXIMAGE1DEXTPROC) load(userptr, "glMultiTexImage1DEXT"); + glad_glMultiTexImage2DEXT = (PFNGLMULTITEXIMAGE2DEXTPROC) load(userptr, "glMultiTexImage2DEXT"); + glad_glMultiTexImage3DEXT = (PFNGLMULTITEXIMAGE3DEXTPROC) load(userptr, "glMultiTexImage3DEXT"); + glad_glMultiTexParameterIivEXT = (PFNGLMULTITEXPARAMETERIIVEXTPROC) load(userptr, "glMultiTexParameterIivEXT"); + glad_glMultiTexParameterIuivEXT = (PFNGLMULTITEXPARAMETERIUIVEXTPROC) load(userptr, "glMultiTexParameterIuivEXT"); + glad_glMultiTexParameterfEXT = (PFNGLMULTITEXPARAMETERFEXTPROC) load(userptr, "glMultiTexParameterfEXT"); + glad_glMultiTexParameterfvEXT = (PFNGLMULTITEXPARAMETERFVEXTPROC) load(userptr, "glMultiTexParameterfvEXT"); + glad_glMultiTexParameteriEXT = (PFNGLMULTITEXPARAMETERIEXTPROC) load(userptr, "glMultiTexParameteriEXT"); + glad_glMultiTexParameterivEXT = (PFNGLMULTITEXPARAMETERIVEXTPROC) load(userptr, "glMultiTexParameterivEXT"); + glad_glMultiTexRenderbufferEXT = (PFNGLMULTITEXRENDERBUFFEREXTPROC) load(userptr, "glMultiTexRenderbufferEXT"); + glad_glMultiTexSubImage1DEXT = (PFNGLMULTITEXSUBIMAGE1DEXTPROC) load(userptr, "glMultiTexSubImage1DEXT"); + glad_glMultiTexSubImage2DEXT = (PFNGLMULTITEXSUBIMAGE2DEXTPROC) load(userptr, "glMultiTexSubImage2DEXT"); + glad_glMultiTexSubImage3DEXT = (PFNGLMULTITEXSUBIMAGE3DEXTPROC) load(userptr, "glMultiTexSubImage3DEXT"); + glad_glNamedBufferDataEXT = (PFNGLNAMEDBUFFERDATAEXTPROC) load(userptr, "glNamedBufferDataEXT"); + glad_glNamedBufferStorageEXT = (PFNGLNAMEDBUFFERSTORAGEEXTPROC) load(userptr, "glNamedBufferStorageEXT"); + glad_glNamedBufferSubDataEXT = (PFNGLNAMEDBUFFERSUBDATAEXTPROC) load(userptr, "glNamedBufferSubDataEXT"); + glad_glNamedCopyBufferSubDataEXT = (PFNGLNAMEDCOPYBUFFERSUBDATAEXTPROC) load(userptr, "glNamedCopyBufferSubDataEXT"); + glad_glNamedFramebufferParameteriEXT = (PFNGLNAMEDFRAMEBUFFERPARAMETERIEXTPROC) load(userptr, "glNamedFramebufferParameteriEXT"); + glad_glNamedFramebufferRenderbufferEXT = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFEREXTPROC) load(userptr, "glNamedFramebufferRenderbufferEXT"); + glad_glNamedFramebufferTexture1DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE1DEXTPROC) load(userptr, "glNamedFramebufferTexture1DEXT"); + glad_glNamedFramebufferTexture2DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE2DEXTPROC) load(userptr, "glNamedFramebufferTexture2DEXT"); + glad_glNamedFramebufferTexture3DEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURE3DEXTPROC) load(userptr, "glNamedFramebufferTexture3DEXT"); + glad_glNamedFramebufferTextureEXT = (PFNGLNAMEDFRAMEBUFFERTEXTUREEXTPROC) load(userptr, "glNamedFramebufferTextureEXT"); + glad_glNamedFramebufferTextureFaceEXT = (PFNGLNAMEDFRAMEBUFFERTEXTUREFACEEXTPROC) load(userptr, "glNamedFramebufferTextureFaceEXT"); + glad_glNamedFramebufferTextureLayerEXT = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYEREXTPROC) load(userptr, "glNamedFramebufferTextureLayerEXT"); + glad_glNamedProgramLocalParameter4dEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4DEXTPROC) load(userptr, "glNamedProgramLocalParameter4dEXT"); + glad_glNamedProgramLocalParameter4dvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4DVEXTPROC) load(userptr, "glNamedProgramLocalParameter4dvEXT"); + glad_glNamedProgramLocalParameter4fEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4FEXTPROC) load(userptr, "glNamedProgramLocalParameter4fEXT"); + glad_glNamedProgramLocalParameter4fvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETER4FVEXTPROC) load(userptr, "glNamedProgramLocalParameter4fvEXT"); + glad_glNamedProgramLocalParameterI4iEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4IEXTPROC) load(userptr, "glNamedProgramLocalParameterI4iEXT"); + glad_glNamedProgramLocalParameterI4ivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4IVEXTPROC) load(userptr, "glNamedProgramLocalParameterI4ivEXT"); + glad_glNamedProgramLocalParameterI4uiEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIEXTPROC) load(userptr, "glNamedProgramLocalParameterI4uiEXT"); + glad_glNamedProgramLocalParameterI4uivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERI4UIVEXTPROC) load(userptr, "glNamedProgramLocalParameterI4uivEXT"); + glad_glNamedProgramLocalParameters4fvEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERS4FVEXTPROC) load(userptr, "glNamedProgramLocalParameters4fvEXT"); + glad_glNamedProgramLocalParametersI4ivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERSI4IVEXTPROC) load(userptr, "glNamedProgramLocalParametersI4ivEXT"); + glad_glNamedProgramLocalParametersI4uivEXT = (PFNGLNAMEDPROGRAMLOCALPARAMETERSI4UIVEXTPROC) load(userptr, "glNamedProgramLocalParametersI4uivEXT"); + glad_glNamedProgramStringEXT = (PFNGLNAMEDPROGRAMSTRINGEXTPROC) load(userptr, "glNamedProgramStringEXT"); + glad_glNamedRenderbufferStorageEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEEXTPROC) load(userptr, "glNamedRenderbufferStorageEXT"); + glad_glNamedRenderbufferStorageMultisampleCoverageEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLECOVERAGEEXTPROC) load(userptr, "glNamedRenderbufferStorageMultisampleCoverageEXT"); + glad_glNamedRenderbufferStorageMultisampleEXT = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) load(userptr, "glNamedRenderbufferStorageMultisampleEXT"); + glad_glProgramUniform1dEXT = (PFNGLPROGRAMUNIFORM1DEXTPROC) load(userptr, "glProgramUniform1dEXT"); + glad_glProgramUniform1dvEXT = (PFNGLPROGRAMUNIFORM1DVEXTPROC) load(userptr, "glProgramUniform1dvEXT"); + glad_glProgramUniform1fEXT = (PFNGLPROGRAMUNIFORM1FEXTPROC) load(userptr, "glProgramUniform1fEXT"); + glad_glProgramUniform1fvEXT = (PFNGLPROGRAMUNIFORM1FVEXTPROC) load(userptr, "glProgramUniform1fvEXT"); + glad_glProgramUniform1iEXT = (PFNGLPROGRAMUNIFORM1IEXTPROC) load(userptr, "glProgramUniform1iEXT"); + glad_glProgramUniform1ivEXT = (PFNGLPROGRAMUNIFORM1IVEXTPROC) load(userptr, "glProgramUniform1ivEXT"); + glad_glProgramUniform1uiEXT = (PFNGLPROGRAMUNIFORM1UIEXTPROC) load(userptr, "glProgramUniform1uiEXT"); + glad_glProgramUniform1uivEXT = (PFNGLPROGRAMUNIFORM1UIVEXTPROC) load(userptr, "glProgramUniform1uivEXT"); + glad_glProgramUniform2dEXT = (PFNGLPROGRAMUNIFORM2DEXTPROC) load(userptr, "glProgramUniform2dEXT"); + glad_glProgramUniform2dvEXT = (PFNGLPROGRAMUNIFORM2DVEXTPROC) load(userptr, "glProgramUniform2dvEXT"); + glad_glProgramUniform2fEXT = (PFNGLPROGRAMUNIFORM2FEXTPROC) load(userptr, "glProgramUniform2fEXT"); + glad_glProgramUniform2fvEXT = (PFNGLPROGRAMUNIFORM2FVEXTPROC) load(userptr, "glProgramUniform2fvEXT"); + glad_glProgramUniform2iEXT = (PFNGLPROGRAMUNIFORM2IEXTPROC) load(userptr, "glProgramUniform2iEXT"); + glad_glProgramUniform2ivEXT = (PFNGLPROGRAMUNIFORM2IVEXTPROC) load(userptr, "glProgramUniform2ivEXT"); + glad_glProgramUniform2uiEXT = (PFNGLPROGRAMUNIFORM2UIEXTPROC) load(userptr, "glProgramUniform2uiEXT"); + glad_glProgramUniform2uivEXT = (PFNGLPROGRAMUNIFORM2UIVEXTPROC) load(userptr, "glProgramUniform2uivEXT"); + glad_glProgramUniform3dEXT = (PFNGLPROGRAMUNIFORM3DEXTPROC) load(userptr, "glProgramUniform3dEXT"); + glad_glProgramUniform3dvEXT = (PFNGLPROGRAMUNIFORM3DVEXTPROC) load(userptr, "glProgramUniform3dvEXT"); + glad_glProgramUniform3fEXT = (PFNGLPROGRAMUNIFORM3FEXTPROC) load(userptr, "glProgramUniform3fEXT"); + glad_glProgramUniform3fvEXT = (PFNGLPROGRAMUNIFORM3FVEXTPROC) load(userptr, "glProgramUniform3fvEXT"); + glad_glProgramUniform3iEXT = (PFNGLPROGRAMUNIFORM3IEXTPROC) load(userptr, "glProgramUniform3iEXT"); + glad_glProgramUniform3ivEXT = (PFNGLPROGRAMUNIFORM3IVEXTPROC) load(userptr, "glProgramUniform3ivEXT"); + glad_glProgramUniform3uiEXT = (PFNGLPROGRAMUNIFORM3UIEXTPROC) load(userptr, "glProgramUniform3uiEXT"); + glad_glProgramUniform3uivEXT = (PFNGLPROGRAMUNIFORM3UIVEXTPROC) load(userptr, "glProgramUniform3uivEXT"); + glad_glProgramUniform4dEXT = (PFNGLPROGRAMUNIFORM4DEXTPROC) load(userptr, "glProgramUniform4dEXT"); + glad_glProgramUniform4dvEXT = (PFNGLPROGRAMUNIFORM4DVEXTPROC) load(userptr, "glProgramUniform4dvEXT"); + glad_glProgramUniform4fEXT = (PFNGLPROGRAMUNIFORM4FEXTPROC) load(userptr, "glProgramUniform4fEXT"); + glad_glProgramUniform4fvEXT = (PFNGLPROGRAMUNIFORM4FVEXTPROC) load(userptr, "glProgramUniform4fvEXT"); + glad_glProgramUniform4iEXT = (PFNGLPROGRAMUNIFORM4IEXTPROC) load(userptr, "glProgramUniform4iEXT"); + glad_glProgramUniform4ivEXT = (PFNGLPROGRAMUNIFORM4IVEXTPROC) load(userptr, "glProgramUniform4ivEXT"); + glad_glProgramUniform4uiEXT = (PFNGLPROGRAMUNIFORM4UIEXTPROC) load(userptr, "glProgramUniform4uiEXT"); + glad_glProgramUniform4uivEXT = (PFNGLPROGRAMUNIFORM4UIVEXTPROC) load(userptr, "glProgramUniform4uivEXT"); + glad_glProgramUniformMatrix2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2DVEXTPROC) load(userptr, "glProgramUniformMatrix2dvEXT"); + glad_glProgramUniformMatrix2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) load(userptr, "glProgramUniformMatrix2fvEXT"); + glad_glProgramUniformMatrix2x3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3DVEXTPROC) load(userptr, "glProgramUniformMatrix2x3dvEXT"); + glad_glProgramUniformMatrix2x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) load(userptr, "glProgramUniformMatrix2x3fvEXT"); + glad_glProgramUniformMatrix2x4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4DVEXTPROC) load(userptr, "glProgramUniformMatrix2x4dvEXT"); + glad_glProgramUniformMatrix2x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) load(userptr, "glProgramUniformMatrix2x4fvEXT"); + glad_glProgramUniformMatrix3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3DVEXTPROC) load(userptr, "glProgramUniformMatrix3dvEXT"); + glad_glProgramUniformMatrix3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) load(userptr, "glProgramUniformMatrix3fvEXT"); + glad_glProgramUniformMatrix3x2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2DVEXTPROC) load(userptr, "glProgramUniformMatrix3x2dvEXT"); + glad_glProgramUniformMatrix3x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) load(userptr, "glProgramUniformMatrix3x2fvEXT"); + glad_glProgramUniformMatrix3x4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4DVEXTPROC) load(userptr, "glProgramUniformMatrix3x4dvEXT"); + glad_glProgramUniformMatrix3x4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) load(userptr, "glProgramUniformMatrix3x4fvEXT"); + glad_glProgramUniformMatrix4dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4DVEXTPROC) load(userptr, "glProgramUniformMatrix4dvEXT"); + glad_glProgramUniformMatrix4fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) load(userptr, "glProgramUniformMatrix4fvEXT"); + glad_glProgramUniformMatrix4x2dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2DVEXTPROC) load(userptr, "glProgramUniformMatrix4x2dvEXT"); + glad_glProgramUniformMatrix4x2fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) load(userptr, "glProgramUniformMatrix4x2fvEXT"); + glad_glProgramUniformMatrix4x3dvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3DVEXTPROC) load(userptr, "glProgramUniformMatrix4x3dvEXT"); + glad_glProgramUniformMatrix4x3fvEXT = (PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) load(userptr, "glProgramUniformMatrix4x3fvEXT"); + glad_glPushClientAttribDefaultEXT = (PFNGLPUSHCLIENTATTRIBDEFAULTEXTPROC) load(userptr, "glPushClientAttribDefaultEXT"); + glad_glTextureBufferEXT = (PFNGLTEXTUREBUFFEREXTPROC) load(userptr, "glTextureBufferEXT"); + glad_glTextureBufferRangeEXT = (PFNGLTEXTUREBUFFERRANGEEXTPROC) load(userptr, "glTextureBufferRangeEXT"); + glad_glTextureImage1DEXT = (PFNGLTEXTUREIMAGE1DEXTPROC) load(userptr, "glTextureImage1DEXT"); + glad_glTextureImage2DEXT = (PFNGLTEXTUREIMAGE2DEXTPROC) load(userptr, "glTextureImage2DEXT"); + glad_glTextureImage3DEXT = (PFNGLTEXTUREIMAGE3DEXTPROC) load(userptr, "glTextureImage3DEXT"); + glad_glTexturePageCommitmentEXT = (PFNGLTEXTUREPAGECOMMITMENTEXTPROC) load(userptr, "glTexturePageCommitmentEXT"); + glad_glTextureParameterIivEXT = (PFNGLTEXTUREPARAMETERIIVEXTPROC) load(userptr, "glTextureParameterIivEXT"); + glad_glTextureParameterIuivEXT = (PFNGLTEXTUREPARAMETERIUIVEXTPROC) load(userptr, "glTextureParameterIuivEXT"); + glad_glTextureParameterfEXT = (PFNGLTEXTUREPARAMETERFEXTPROC) load(userptr, "glTextureParameterfEXT"); + glad_glTextureParameterfvEXT = (PFNGLTEXTUREPARAMETERFVEXTPROC) load(userptr, "glTextureParameterfvEXT"); + glad_glTextureParameteriEXT = (PFNGLTEXTUREPARAMETERIEXTPROC) load(userptr, "glTextureParameteriEXT"); + glad_glTextureParameterivEXT = (PFNGLTEXTUREPARAMETERIVEXTPROC) load(userptr, "glTextureParameterivEXT"); + glad_glTextureRenderbufferEXT = (PFNGLTEXTURERENDERBUFFEREXTPROC) load(userptr, "glTextureRenderbufferEXT"); + glad_glTextureStorage1DEXT = (PFNGLTEXTURESTORAGE1DEXTPROC) load(userptr, "glTextureStorage1DEXT"); + glad_glTextureStorage2DEXT = (PFNGLTEXTURESTORAGE2DEXTPROC) load(userptr, "glTextureStorage2DEXT"); + glad_glTextureStorage2DMultisampleEXT = (PFNGLTEXTURESTORAGE2DMULTISAMPLEEXTPROC) load(userptr, "glTextureStorage2DMultisampleEXT"); + glad_glTextureStorage3DEXT = (PFNGLTEXTURESTORAGE3DEXTPROC) load(userptr, "glTextureStorage3DEXT"); + glad_glTextureStorage3DMultisampleEXT = (PFNGLTEXTURESTORAGE3DMULTISAMPLEEXTPROC) load(userptr, "glTextureStorage3DMultisampleEXT"); + glad_glTextureSubImage1DEXT = (PFNGLTEXTURESUBIMAGE1DEXTPROC) load(userptr, "glTextureSubImage1DEXT"); + glad_glTextureSubImage2DEXT = (PFNGLTEXTURESUBIMAGE2DEXTPROC) load(userptr, "glTextureSubImage2DEXT"); + glad_glTextureSubImage3DEXT = (PFNGLTEXTURESUBIMAGE3DEXTPROC) load(userptr, "glTextureSubImage3DEXT"); + glad_glUnmapNamedBufferEXT = (PFNGLUNMAPNAMEDBUFFEREXTPROC) load(userptr, "glUnmapNamedBufferEXT"); + glad_glVertexArrayBindVertexBufferEXT = (PFNGLVERTEXARRAYBINDVERTEXBUFFEREXTPROC) load(userptr, "glVertexArrayBindVertexBufferEXT"); + glad_glVertexArrayColorOffsetEXT = (PFNGLVERTEXARRAYCOLOROFFSETEXTPROC) load(userptr, "glVertexArrayColorOffsetEXT"); + glad_glVertexArrayEdgeFlagOffsetEXT = (PFNGLVERTEXARRAYEDGEFLAGOFFSETEXTPROC) load(userptr, "glVertexArrayEdgeFlagOffsetEXT"); + glad_glVertexArrayFogCoordOffsetEXT = (PFNGLVERTEXARRAYFOGCOORDOFFSETEXTPROC) load(userptr, "glVertexArrayFogCoordOffsetEXT"); + glad_glVertexArrayIndexOffsetEXT = (PFNGLVERTEXARRAYINDEXOFFSETEXTPROC) load(userptr, "glVertexArrayIndexOffsetEXT"); + glad_glVertexArrayMultiTexCoordOffsetEXT = (PFNGLVERTEXARRAYMULTITEXCOORDOFFSETEXTPROC) load(userptr, "glVertexArrayMultiTexCoordOffsetEXT"); + glad_glVertexArrayNormalOffsetEXT = (PFNGLVERTEXARRAYNORMALOFFSETEXTPROC) load(userptr, "glVertexArrayNormalOffsetEXT"); + glad_glVertexArraySecondaryColorOffsetEXT = (PFNGLVERTEXARRAYSECONDARYCOLOROFFSETEXTPROC) load(userptr, "glVertexArraySecondaryColorOffsetEXT"); + glad_glVertexArrayTexCoordOffsetEXT = (PFNGLVERTEXARRAYTEXCOORDOFFSETEXTPROC) load(userptr, "glVertexArrayTexCoordOffsetEXT"); + glad_glVertexArrayVertexAttribBindingEXT = (PFNGLVERTEXARRAYVERTEXATTRIBBINDINGEXTPROC) load(userptr, "glVertexArrayVertexAttribBindingEXT"); + glad_glVertexArrayVertexAttribDivisorEXT = (PFNGLVERTEXARRAYVERTEXATTRIBDIVISOREXTPROC) load(userptr, "glVertexArrayVertexAttribDivisorEXT"); + glad_glVertexArrayVertexAttribFormatEXT = (PFNGLVERTEXARRAYVERTEXATTRIBFORMATEXTPROC) load(userptr, "glVertexArrayVertexAttribFormatEXT"); + glad_glVertexArrayVertexAttribIFormatEXT = (PFNGLVERTEXARRAYVERTEXATTRIBIFORMATEXTPROC) load(userptr, "glVertexArrayVertexAttribIFormatEXT"); + glad_glVertexArrayVertexAttribIOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBIOFFSETEXTPROC) load(userptr, "glVertexArrayVertexAttribIOffsetEXT"); + glad_glVertexArrayVertexAttribLFormatEXT = (PFNGLVERTEXARRAYVERTEXATTRIBLFORMATEXTPROC) load(userptr, "glVertexArrayVertexAttribLFormatEXT"); + glad_glVertexArrayVertexAttribLOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBLOFFSETEXTPROC) load(userptr, "glVertexArrayVertexAttribLOffsetEXT"); + glad_glVertexArrayVertexAttribOffsetEXT = (PFNGLVERTEXARRAYVERTEXATTRIBOFFSETEXTPROC) load(userptr, "glVertexArrayVertexAttribOffsetEXT"); + glad_glVertexArrayVertexBindingDivisorEXT = (PFNGLVERTEXARRAYVERTEXBINDINGDIVISOREXTPROC) load(userptr, "glVertexArrayVertexBindingDivisorEXT"); + glad_glVertexArrayVertexOffsetEXT = (PFNGLVERTEXARRAYVERTEXOFFSETEXTPROC) load(userptr, "glVertexArrayVertexOffsetEXT"); +} +static void glad_gl_load_GL_EXT_framebuffer_blit( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_EXT_framebuffer_blit) return; + glad_glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC) load(userptr, "glBlitFramebufferEXT"); +} +static void glad_gl_load_GL_EXT_framebuffer_object( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_EXT_framebuffer_object) return; + glad_glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) load(userptr, "glBindFramebufferEXT"); + glad_glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) load(userptr, "glBindRenderbufferEXT"); + glad_glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) load(userptr, "glCheckFramebufferStatusEXT"); + glad_glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) load(userptr, "glDeleteFramebuffersEXT"); + glad_glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) load(userptr, "glDeleteRenderbuffersEXT"); + glad_glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) load(userptr, "glFramebufferRenderbufferEXT"); + glad_glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) load(userptr, "glFramebufferTexture1DEXT"); + glad_glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) load(userptr, "glFramebufferTexture2DEXT"); + glad_glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) load(userptr, "glFramebufferTexture3DEXT"); + glad_glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) load(userptr, "glGenFramebuffersEXT"); + glad_glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) load(userptr, "glGenRenderbuffersEXT"); + glad_glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) load(userptr, "glGenerateMipmapEXT"); + glad_glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) load(userptr, "glGetFramebufferAttachmentParameterivEXT"); + glad_glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) load(userptr, "glGetRenderbufferParameterivEXT"); + glad_glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) load(userptr, "glIsFramebufferEXT"); + glad_glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) load(userptr, "glIsRenderbufferEXT"); + glad_glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) load(userptr, "glRenderbufferStorageEXT"); +} +static void glad_gl_load_GL_EXT_geometry_shader4( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_EXT_geometry_shader4) return; + glad_glProgramParameteriEXT = (PFNGLPROGRAMPARAMETERIEXTPROC) load(userptr, "glProgramParameteriEXT"); +} +static void glad_gl_load_GL_EXT_gpu_shader4( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_EXT_gpu_shader4) return; + glad_glBindFragDataLocationEXT = (PFNGLBINDFRAGDATALOCATIONEXTPROC) load(userptr, "glBindFragDataLocationEXT"); + glad_glGetFragDataLocationEXT = (PFNGLGETFRAGDATALOCATIONEXTPROC) load(userptr, "glGetFragDataLocationEXT"); + glad_glGetUniformuivEXT = (PFNGLGETUNIFORMUIVEXTPROC) load(userptr, "glGetUniformuivEXT"); + glad_glGetVertexAttribIivEXT = (PFNGLGETVERTEXATTRIBIIVEXTPROC) load(userptr, "glGetVertexAttribIivEXT"); + glad_glGetVertexAttribIuivEXT = (PFNGLGETVERTEXATTRIBIUIVEXTPROC) load(userptr, "glGetVertexAttribIuivEXT"); + glad_glUniform1uiEXT = (PFNGLUNIFORM1UIEXTPROC) load(userptr, "glUniform1uiEXT"); + glad_glUniform1uivEXT = (PFNGLUNIFORM1UIVEXTPROC) load(userptr, "glUniform1uivEXT"); + glad_glUniform2uiEXT = (PFNGLUNIFORM2UIEXTPROC) load(userptr, "glUniform2uiEXT"); + glad_glUniform2uivEXT = (PFNGLUNIFORM2UIVEXTPROC) load(userptr, "glUniform2uivEXT"); + glad_glUniform3uiEXT = (PFNGLUNIFORM3UIEXTPROC) load(userptr, "glUniform3uiEXT"); + glad_glUniform3uivEXT = (PFNGLUNIFORM3UIVEXTPROC) load(userptr, "glUniform3uivEXT"); + glad_glUniform4uiEXT = (PFNGLUNIFORM4UIEXTPROC) load(userptr, "glUniform4uiEXT"); + glad_glUniform4uivEXT = (PFNGLUNIFORM4UIVEXTPROC) load(userptr, "glUniform4uivEXT"); + glad_glVertexAttribI1iEXT = (PFNGLVERTEXATTRIBI1IEXTPROC) load(userptr, "glVertexAttribI1iEXT"); + glad_glVertexAttribI1ivEXT = (PFNGLVERTEXATTRIBI1IVEXTPROC) load(userptr, "glVertexAttribI1ivEXT"); + glad_glVertexAttribI1uiEXT = (PFNGLVERTEXATTRIBI1UIEXTPROC) load(userptr, "glVertexAttribI1uiEXT"); + glad_glVertexAttribI1uivEXT = (PFNGLVERTEXATTRIBI1UIVEXTPROC) load(userptr, "glVertexAttribI1uivEXT"); + glad_glVertexAttribI2iEXT = (PFNGLVERTEXATTRIBI2IEXTPROC) load(userptr, "glVertexAttribI2iEXT"); + glad_glVertexAttribI2ivEXT = (PFNGLVERTEXATTRIBI2IVEXTPROC) load(userptr, "glVertexAttribI2ivEXT"); + glad_glVertexAttribI2uiEXT = (PFNGLVERTEXATTRIBI2UIEXTPROC) load(userptr, "glVertexAttribI2uiEXT"); + glad_glVertexAttribI2uivEXT = (PFNGLVERTEXATTRIBI2UIVEXTPROC) load(userptr, "glVertexAttribI2uivEXT"); + glad_glVertexAttribI3iEXT = (PFNGLVERTEXATTRIBI3IEXTPROC) load(userptr, "glVertexAttribI3iEXT"); + glad_glVertexAttribI3ivEXT = (PFNGLVERTEXATTRIBI3IVEXTPROC) load(userptr, "glVertexAttribI3ivEXT"); + glad_glVertexAttribI3uiEXT = (PFNGLVERTEXATTRIBI3UIEXTPROC) load(userptr, "glVertexAttribI3uiEXT"); + glad_glVertexAttribI3uivEXT = (PFNGLVERTEXATTRIBI3UIVEXTPROC) load(userptr, "glVertexAttribI3uivEXT"); + glad_glVertexAttribI4bvEXT = (PFNGLVERTEXATTRIBI4BVEXTPROC) load(userptr, "glVertexAttribI4bvEXT"); + glad_glVertexAttribI4iEXT = (PFNGLVERTEXATTRIBI4IEXTPROC) load(userptr, "glVertexAttribI4iEXT"); + glad_glVertexAttribI4ivEXT = (PFNGLVERTEXATTRIBI4IVEXTPROC) load(userptr, "glVertexAttribI4ivEXT"); + glad_glVertexAttribI4svEXT = (PFNGLVERTEXATTRIBI4SVEXTPROC) load(userptr, "glVertexAttribI4svEXT"); + glad_glVertexAttribI4ubvEXT = (PFNGLVERTEXATTRIBI4UBVEXTPROC) load(userptr, "glVertexAttribI4ubvEXT"); + glad_glVertexAttribI4uiEXT = (PFNGLVERTEXATTRIBI4UIEXTPROC) load(userptr, "glVertexAttribI4uiEXT"); + glad_glVertexAttribI4uivEXT = (PFNGLVERTEXATTRIBI4UIVEXTPROC) load(userptr, "glVertexAttribI4uivEXT"); + glad_glVertexAttribI4usvEXT = (PFNGLVERTEXATTRIBI4USVEXTPROC) load(userptr, "glVertexAttribI4usvEXT"); + glad_glVertexAttribIPointerEXT = (PFNGLVERTEXATTRIBIPOINTEREXTPROC) load(userptr, "glVertexAttribIPointerEXT"); +} +static void glad_gl_load_GL_EXT_shader_image_load_store( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_EXT_shader_image_load_store) return; + glad_glBindImageTextureEXT = (PFNGLBINDIMAGETEXTUREEXTPROC) load(userptr, "glBindImageTextureEXT"); + glad_glMemoryBarrierEXT = (PFNGLMEMORYBARRIEREXTPROC) load(userptr, "glMemoryBarrierEXT"); +} +static void glad_gl_load_GL_EXT_texture_array( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_EXT_texture_array) return; + glad_glFramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) load(userptr, "glFramebufferTextureLayerEXT"); +} +static void glad_gl_load_GL_EXT_texture_integer( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_EXT_texture_integer) return; + glad_glClearColorIiEXT = (PFNGLCLEARCOLORIIEXTPROC) load(userptr, "glClearColorIiEXT"); + glad_glClearColorIuiEXT = (PFNGLCLEARCOLORIUIEXTPROC) load(userptr, "glClearColorIuiEXT"); + glad_glGetTexParameterIivEXT = (PFNGLGETTEXPARAMETERIIVEXTPROC) load(userptr, "glGetTexParameterIivEXT"); + glad_glGetTexParameterIuivEXT = (PFNGLGETTEXPARAMETERIUIVEXTPROC) load(userptr, "glGetTexParameterIuivEXT"); + glad_glTexParameterIivEXT = (PFNGLTEXPARAMETERIIVEXTPROC) load(userptr, "glTexParameterIivEXT"); + glad_glTexParameterIuivEXT = (PFNGLTEXPARAMETERIUIVEXTPROC) load(userptr, "glTexParameterIuivEXT"); +} +static void glad_gl_load_GL_EXT_transform_feedback( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_EXT_transform_feedback) return; + glad_glBeginTransformFeedbackEXT = (PFNGLBEGINTRANSFORMFEEDBACKEXTPROC) load(userptr, "glBeginTransformFeedbackEXT"); + glad_glBindBufferBaseEXT = (PFNGLBINDBUFFERBASEEXTPROC) load(userptr, "glBindBufferBaseEXT"); + glad_glBindBufferOffsetEXT = (PFNGLBINDBUFFEROFFSETEXTPROC) load(userptr, "glBindBufferOffsetEXT"); + glad_glBindBufferRangeEXT = (PFNGLBINDBUFFERRANGEEXTPROC) load(userptr, "glBindBufferRangeEXT"); + glad_glEndTransformFeedbackEXT = (PFNGLENDTRANSFORMFEEDBACKEXTPROC) load(userptr, "glEndTransformFeedbackEXT"); + glad_glGetTransformFeedbackVaryingEXT = (PFNGLGETTRANSFORMFEEDBACKVARYINGEXTPROC) load(userptr, "glGetTransformFeedbackVaryingEXT"); + glad_glTransformFeedbackVaryingsEXT = (PFNGLTRANSFORMFEEDBACKVARYINGSEXTPROC) load(userptr, "glTransformFeedbackVaryingsEXT"); +} +static void glad_gl_load_GL_NV_conservative_raster( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_NV_conservative_raster) return; + glad_glSubpixelPrecisionBiasNV = (PFNGLSUBPIXELPRECISIONBIASNVPROC) load(userptr, "glSubpixelPrecisionBiasNV"); +} + + + +static void glad_gl_free_extensions(char **exts_i) { + if (exts_i != NULL) { + unsigned int index; + for(index = 0; exts_i[index]; index++) { + free((void *) (exts_i[index])); + } + free((void *)exts_i); + exts_i = NULL; + } +} +static int glad_gl_get_extensions( const char **out_exts, char ***out_exts_i) { +#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0) + if (glad_glGetStringi != NULL && glad_glGetIntegerv != NULL) { + unsigned int index = 0; + unsigned int num_exts_i = 0; + char **exts_i = NULL; + glad_glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i); + exts_i = (char **) malloc((num_exts_i + 1) * (sizeof *exts_i)); + if (exts_i == NULL) { + return 0; + } + for(index = 0; index < num_exts_i; index++) { + const char *gl_str_tmp = (const char*) glad_glGetStringi(GL_EXTENSIONS, index); + size_t len = strlen(gl_str_tmp) + 1; + + char *local_str = (char*) malloc(len * sizeof(char)); + if(local_str == NULL) { + exts_i[index] = NULL; + glad_gl_free_extensions(exts_i); + return 0; + } + + memcpy(local_str, gl_str_tmp, len * sizeof(char)); + exts_i[index] = local_str; + } + exts_i[index] = NULL; + + *out_exts_i = exts_i; + + return 1; + } +#else + GLAD_UNUSED(out_exts_i); +#endif + if (glad_glGetString == NULL) { + return 0; + } + *out_exts = (const char *)glad_glGetString(GL_EXTENSIONS); + return 1; +} +static int glad_gl_has_extension(const char *exts, char **exts_i, const char *ext) { + if(exts_i) { + unsigned int index; + for(index = 0; exts_i[index]; index++) { + const char *e = exts_i[index]; + if(strcmp(e, ext) == 0) { + return 1; + } + } + } else { + const char *extensions; + const char *loc; + const char *terminator; + extensions = exts; + if(extensions == NULL || ext == NULL) { + return 0; + } + while(1) { + loc = strstr(extensions, ext); + if(loc == NULL) { + return 0; + } + terminator = loc + strlen(ext); + if((loc == extensions || *(loc - 1) == ' ') && + (*terminator == ' ' || *terminator == '\0')) { + return 1; + } + extensions = terminator; + } + } + return 0; +} + +static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name) { + return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name); +} + +static int glad_gl_find_extensions_gl(void) { + const char *exts = NULL; + char **exts_i = NULL; + if (!glad_gl_get_extensions(&exts, &exts_i)) return 0; + + GLAD_GL_ARB_compatibility = glad_gl_has_extension(exts, exts_i, "GL_ARB_compatibility"); + GLAD_GL_ARB_debug_output = glad_gl_has_extension(exts, exts_i, "GL_ARB_debug_output"); + GLAD_GL_ARB_fragment_program = glad_gl_has_extension(exts, exts_i, "GL_ARB_fragment_program"); + GLAD_GL_ARB_fragment_shader = glad_gl_has_extension(exts, exts_i, "GL_ARB_fragment_shader"); + GLAD_GL_ARB_framebuffer_sRGB = glad_gl_has_extension(exts, exts_i, "GL_ARB_framebuffer_sRGB"); + GLAD_GL_ARB_shader_image_load_store = glad_gl_has_extension(exts, exts_i, "GL_ARB_shader_image_load_store"); + GLAD_GL_ARB_shader_image_size = glad_gl_has_extension(exts, exts_i, "GL_ARB_shader_image_size"); + GLAD_GL_ARB_shader_objects = glad_gl_has_extension(exts, exts_i, "GL_ARB_shader_objects"); + GLAD_GL_ARB_shader_storage_buffer_object = glad_gl_has_extension(exts, exts_i, "GL_ARB_shader_storage_buffer_object"); + GLAD_GL_ARB_shading_language_100 = glad_gl_has_extension(exts, exts_i, "GL_ARB_shading_language_100"); + GLAD_GL_ARB_texture_float = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_float"); + GLAD_GL_ARB_texture_rg = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_rg"); + GLAD_GL_ARB_texture_rgb10_a2ui = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_rgb10_a2ui"); + GLAD_GL_ARB_vertex_buffer_object = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_buffer_object"); + GLAD_GL_ARB_vertex_program = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_program"); + GLAD_GL_ARB_vertex_shader = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_shader"); + GLAD_GL_ARB_vertex_type_2_10_10_10_rev = glad_gl_has_extension(exts, exts_i, "GL_ARB_vertex_type_2_10_10_10_rev"); + GLAD_GL_EXT_direct_state_access = glad_gl_has_extension(exts, exts_i, "GL_EXT_direct_state_access"); + GLAD_GL_EXT_framebuffer_blit = glad_gl_has_extension(exts, exts_i, "GL_EXT_framebuffer_blit"); + GLAD_GL_EXT_framebuffer_object = glad_gl_has_extension(exts, exts_i, "GL_EXT_framebuffer_object"); + GLAD_GL_EXT_framebuffer_sRGB = glad_gl_has_extension(exts, exts_i, "GL_EXT_framebuffer_sRGB"); + GLAD_GL_EXT_geometry_shader4 = glad_gl_has_extension(exts, exts_i, "GL_EXT_geometry_shader4"); + GLAD_GL_EXT_gpu_shader4 = glad_gl_has_extension(exts, exts_i, "GL_EXT_gpu_shader4"); + GLAD_GL_EXT_shader_image_load_store = glad_gl_has_extension(exts, exts_i, "GL_EXT_shader_image_load_store"); + GLAD_GL_EXT_texture_array = glad_gl_has_extension(exts, exts_i, "GL_EXT_texture_array"); + GLAD_GL_EXT_texture_compression_s3tc = glad_gl_has_extension(exts, exts_i, "GL_EXT_texture_compression_s3tc"); + GLAD_GL_EXT_texture_integer = glad_gl_has_extension(exts, exts_i, "GL_EXT_texture_integer"); + GLAD_GL_EXT_texture_sRGB = glad_gl_has_extension(exts, exts_i, "GL_EXT_texture_sRGB"); + GLAD_GL_EXT_transform_feedback = glad_gl_has_extension(exts, exts_i, "GL_EXT_transform_feedback"); + GLAD_GL_INTEL_conservative_rasterization = glad_gl_has_extension(exts, exts_i, "GL_INTEL_conservative_rasterization"); + GLAD_GL_NV_conservative_raster = glad_gl_has_extension(exts, exts_i, "GL_NV_conservative_raster"); + + glad_gl_free_extensions(exts_i); + + return 1; +} + +static int glad_gl_find_core_gl(void) { + int i; + const char* version; + const char* prefixes[] = { + "OpenGL ES-CM ", + "OpenGL ES-CL ", + "OpenGL ES ", + "OpenGL SC ", + NULL + }; + int major = 0; + int minor = 0; + version = (const char*) glad_glGetString(GL_VERSION); + if (!version) return 0; + for (i = 0; prefixes[i]; i++) { + const size_t length = strlen(prefixes[i]); + if (strncmp(version, prefixes[i], length) == 0) { + version += length; + break; + } + } + + GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor); + + GLAD_GL_VERSION_1_0 = (major == 1 && minor >= 0) || major > 1; + GLAD_GL_VERSION_1_1 = (major == 1 && minor >= 1) || major > 1; + GLAD_GL_VERSION_1_2 = (major == 1 && minor >= 2) || major > 1; + GLAD_GL_VERSION_1_3 = (major == 1 && minor >= 3) || major > 1; + GLAD_GL_VERSION_1_4 = (major == 1 && minor >= 4) || major > 1; + GLAD_GL_VERSION_1_5 = (major == 1 && minor >= 5) || major > 1; + GLAD_GL_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2; + GLAD_GL_VERSION_2_1 = (major == 2 && minor >= 1) || major > 2; + GLAD_GL_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3; + GLAD_GL_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3; + GLAD_GL_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3; + GLAD_GL_VERSION_3_3 = (major == 3 && minor >= 3) || major > 3; + GLAD_GL_VERSION_4_0 = (major == 4 && minor >= 0) || major > 4; + GLAD_GL_VERSION_4_1 = (major == 4 && minor >= 1) || major > 4; + GLAD_GL_VERSION_4_2 = (major == 4 && minor >= 2) || major > 4; + GLAD_GL_VERSION_4_3 = (major == 4 && minor >= 3) || major > 4; + GLAD_GL_VERSION_4_4 = (major == 4 && minor >= 4) || major > 4; + GLAD_GL_VERSION_4_5 = (major == 4 && minor >= 5) || major > 4; + GLAD_GL_VERSION_4_6 = (major == 4 && minor >= 6) || major > 4; + + return GLAD_MAKE_VERSION(major, minor); +} + +int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr) { + int version; + + glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString"); + if(glad_glGetString == NULL) return 0; + version = glad_gl_find_core_gl(); + + glad_gl_load_GL_VERSION_1_0(load, userptr); + glad_gl_load_GL_VERSION_1_1(load, userptr); + glad_gl_load_GL_VERSION_1_2(load, userptr); + glad_gl_load_GL_VERSION_1_3(load, userptr); + glad_gl_load_GL_VERSION_1_4(load, userptr); + glad_gl_load_GL_VERSION_1_5(load, userptr); + glad_gl_load_GL_VERSION_2_0(load, userptr); + glad_gl_load_GL_VERSION_2_1(load, userptr); + glad_gl_load_GL_VERSION_3_0(load, userptr); + glad_gl_load_GL_VERSION_3_1(load, userptr); + glad_gl_load_GL_VERSION_3_2(load, userptr); + glad_gl_load_GL_VERSION_3_3(load, userptr); + glad_gl_load_GL_VERSION_4_0(load, userptr); + glad_gl_load_GL_VERSION_4_1(load, userptr); + glad_gl_load_GL_VERSION_4_2(load, userptr); + glad_gl_load_GL_VERSION_4_3(load, userptr); + glad_gl_load_GL_VERSION_4_4(load, userptr); + glad_gl_load_GL_VERSION_4_5(load, userptr); + glad_gl_load_GL_VERSION_4_6(load, userptr); + + if (!glad_gl_find_extensions_gl()) return 0; + glad_gl_load_GL_ARB_debug_output(load, userptr); + glad_gl_load_GL_ARB_fragment_program(load, userptr); + glad_gl_load_GL_ARB_shader_image_load_store(load, userptr); + glad_gl_load_GL_ARB_shader_objects(load, userptr); + glad_gl_load_GL_ARB_shader_storage_buffer_object(load, userptr); + glad_gl_load_GL_ARB_vertex_buffer_object(load, userptr); + glad_gl_load_GL_ARB_vertex_program(load, userptr); + glad_gl_load_GL_ARB_vertex_shader(load, userptr); + glad_gl_load_GL_ARB_vertex_type_2_10_10_10_rev(load, userptr); + glad_gl_load_GL_EXT_direct_state_access(load, userptr); + glad_gl_load_GL_EXT_framebuffer_blit(load, userptr); + glad_gl_load_GL_EXT_framebuffer_object(load, userptr); + glad_gl_load_GL_EXT_geometry_shader4(load, userptr); + glad_gl_load_GL_EXT_gpu_shader4(load, userptr); + glad_gl_load_GL_EXT_shader_image_load_store(load, userptr); + glad_gl_load_GL_EXT_texture_array(load, userptr); + glad_gl_load_GL_EXT_texture_integer(load, userptr); + glad_gl_load_GL_EXT_transform_feedback(load, userptr); + glad_gl_load_GL_NV_conservative_raster(load, userptr); + + + + return version; +} + + +int gladLoadGL( GLADloadfunc load) { + return gladLoadGLUserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load); +} + + + + + + +#ifdef __cplusplus +} +#endif + +#endif /* GLAD_GL_IMPLEMENTATION */ + diff --git a/src/k3mix.c b/src/k3mix.c new file mode 100644 index 0000000..228b74c --- /dev/null +++ b/src/k3mix.c @@ -0,0 +1,395 @@ +#include"k3mix.h" + +#include +#include +#include +#include +#include +#include + +static uint32_t FinalSampleRate; +static uint8_t FinalChannels; + +void k3MixInit(uint32_t sampleRate, uint8_t channels) { + FinalSampleRate = sampleRate; + FinalChannels = channels; +} + +struct k3MixSource { + char *filepath; + OggVorbis_File vf; + int bitstream; +}; +struct k3MixSource *k3MixSourceFile(const char *path) { + struct k3MixSource *ret = calloc(1, sizeof(*ret)); + ret->filepath = strdup(path); + ov_fopen(path, &ret->vf); + ret->bitstream = 0; + return ret; +} +void k3MixSourceClose(struct k3MixSource *src) { + ov_clear(&src->vf); + free(src->filepath); + free(src); +} + +__attribute__((optimize("Ofast"))) static intmax_t ogg_read(struct k3MixWave *this, size_t sampleCount, float *data) { + struct k3MixSource *od = this->data; + + float **ni; + long totalRead = 0; + do { + long lastRead = ov_read_float(&od->vf, &ni, sampleCount, &od->bitstream); + + if(this->loop && lastRead == 0) { + ov_pcm_seek(&od->vf, 0); + continue; + } else if(lastRead <= 0) { + this->end = true; + return totalRead; + } + + for(long s = 0; s < lastRead; s++) { + for(long c = 0; c < this->channels; c++) { + *(data++) += ni[c][s] * this->volume; + } + } + + totalRead += lastRead; + sampleCount -= lastRead; + } while(sampleCount); + + return totalRead; +} +static void ogg_close(struct k3MixWave *this) { + if(this->refs-- == 1) { + k3MixSourceClose(this->data); + } +} +static void ogg_clone(struct k3MixWave *this, struct k3MixWave *new) { + new->refs = 1; + new->sampleRate = this->sampleRate; + new->channels = this->channels; + new->data = k3MixSourceFile(((struct k3MixSource*) this->data)->filepath); + new->read = ogg_read; + new->clone = ogg_clone; + new->close = ogg_close; + + new->loop = this->loop; + new->dam = this->dam; + new->volume = this->volume; +} +struct k3MixWave *k3MixSimple(struct k3MixSource *src) { + vorbis_info *vi = ov_info(&src->vf, -1); + + struct k3MixWave *ret = calloc(1, sizeof(*ret)); + ret->refs = 1; + ret->sampleRate = vi->rate; + ret->channels = vi->channels; + ret->data = k3MixSourceFile(src->filepath); + + ret->read = ogg_read; + ret->clone = ogg_clone; + ret->close = ogg_close; + + ret->loop = 0; + ret->dam = 0; + ret->volume = 1; + + return ret; +} +void k3MixSimpleSeek(struct k3MixWave *this, double t) { + struct k3MixSource *od = this->data; + ov_time_seek(&od->vf, t); +} + +struct qdata { + size_t ref; + size_t count; + struct k3MixWave *children; + + pthread_mutex_t damootecks; +}; +static intmax_t queue_read(struct k3MixWave *this, size_t sampleCount, float *data) { + struct qdata *qdat = this->data; + + pthread_mutex_lock(&qdat->damootecks); + + size_t totalRead = 0; + + while(sampleCount && qdat->count > 0) { + intmax_t i = qdat->children[0].read(&qdat->children[0], sampleCount, data); + + if(i == 0) { + qdat->children[0].close(&qdat->children[0]); + memmove(&qdat->children[0], &qdat->children[1], sizeof(*qdat->children) * (qdat->count - 1)); + qdat->count--; + } else { + data += this->channels * i; + totalRead += i; + sampleCount -= i; + } + } + + pthread_mutex_unlock(&qdat->damootecks); + + return totalRead; +} +static void queue_close(struct k3MixWave *this) { + if(this->refs-- == 1) { + struct qdata *qdat = this->data; + + if(--qdat->ref == 0) { + for(size_t i = 0; i < qdat->count; i++) { + qdat->children[i].close(&qdat->children[i]); + } + + free(qdat); + } + } +} +static void queue_clone(struct k3MixWave *this, struct k3MixWave *new) { + struct qdata *data = this->data; + + data->ref++; + + new->refs = 1; + new->sampleRate = this->sampleRate; + new->channels = this->channels; + new->data = data; + new->read = queue_read; + new->clone = queue_clone; + new->close = queue_close; + + new->loop = this->loop; + new->dam = this->dam; + new->volume = this->volume; +} +struct k3MixWave *k3MixQueue() { + struct k3MixWave *ret = malloc(sizeof(*ret)); + ret->refs = 1; + ret->sampleRate = FinalSampleRate; + ret->channels = FinalChannels; + + struct qdata *data = ret->data = calloc(1, sizeof(struct qdata)); + data->ref = 1; + pthread_mutex_init(&data->damootecks, NULL); + + ret->read = queue_read; + ret->clone = queue_clone; + ret->close = queue_close; + + ret->loop = 0; + ret->dam = 0; + ret->volume = 1; + + return ret; +} +void k3MixQueueAdd(struct k3MixWave *this, struct k3MixWave *child) { + struct qdata *qdat = this->data; + + pthread_mutex_lock(&qdat->damootecks); + qdat->children = realloc(qdat->children, sizeof(*qdat->children) * (qdat->count + 1)); + child->clone(child, &qdat->children[qdat->count]); + qdat->count++; + pthread_mutex_unlock(&qdat->damootecks); +} +void k3MixQueueClear(struct k3MixWave *this) { + struct qdata *qdat = this->data; + + pthread_mutex_lock(&qdat->damootecks); + for(size_t i = 0; i < qdat->count; i++) { + qdat->children[i].close(&qdat->children[i]); + } + qdat->count = 0; + free(qdat->children); + qdat->children = NULL; + pthread_mutex_unlock(&qdat->damootecks); +} + +struct powermeasurementdata { + struct k3MixWave *child; + + size_t historySize; + float *history; +}; + +static intmax_t power_measurement_read(struct k3MixWave *this, size_t sampleCount, float *data) { + struct powermeasurementdata *dat = this->data; + + sampleCount = dat->child->read(dat->child, sampleCount, data); + + if(sampleCount * FinalChannels < dat->historySize) { + memmove(dat->history, dat->history + sampleCount * FinalChannels, (dat->historySize - sampleCount * FinalChannels) * sizeof(*dat->history)); + memcpy(dat->history + (dat->historySize - sampleCount * FinalChannels), data, sampleCount * FinalChannels * sizeof(*dat->history)); + } else { + memcpy(dat->history, data + sampleCount * FinalChannels - dat->historySize, dat->historySize * sizeof(*dat->history)); + } + + this->end = dat->child->end; + + return sampleCount; +} + +static void power_measurement_close(struct k3MixWave *this) { + if(this->refs-- == 1) { + struct powermeasurementdata *dat = this->data; + + dat->child->close(dat->child); + + free(dat); + } +} + +static void power_measurement_clone(struct k3MixWave *this, struct k3MixWave *new) { + struct powermeasurementdata *src = this->data; + + struct powermeasurementdata *dat = malloc(sizeof(*dat)); + dat->child = calloc(1, sizeof(*dat->child)); + src->child->clone(src->child, dat->child); + dat->history = calloc(dat->historySize = src->historySize, sizeof(*dat->history)); + memcpy(dat->history, src->history, sizeof(*dat->history) * dat->historySize); + + new->refs = 1; + new->sampleRate = FinalSampleRate; + new->channels = FinalChannels; + + new->data = dat; + + new->read = power_measurement_read; + new->clone = power_measurement_clone; + new->close = power_measurement_close; + + new->loop = this->loop; + new->dam = this->dam; + new->volume = this->volume; +} + +float k3MixPowerMeasurementGetRMS(struct k3MixWave *this) { + struct powermeasurementdata *dat = this->data; + + float sum = 0; + + for(int i = 0; i < dat->historySize; i++) { + sum += pow(dat->history[i], 2); + } + + return sqrtf(sum / dat->historySize); +} + +struct k3MixWave *k3MixPowerMeasurement(struct k3MixWave *child) { + child->refs++; + + struct powermeasurementdata *dat = malloc(sizeof(*dat)); + dat->child = child; + + dat->historySize = 8820; + dat->history = calloc(dat->historySize, sizeof(*dat->history)); + + struct k3MixWave *ret = malloc(sizeof(*ret)); + + ret->refs = 1; + ret->sampleRate = FinalSampleRate; + ret->channels = FinalChannels; + + ret->data = dat; + + ret->read = power_measurement_read; + ret->clone = power_measurement_clone; + ret->close = power_measurement_close; + + ret->loop = 0; + ret->dam = 0; + ret->volume = 1; + + return ret; +} + +static size_t playingCount, playingCapacity; +static struct k3MixWave **playings; + +void k3MixStop(struct k3MixWave *wav) { + for(size_t i = 0; i < playingCount; i++) { + if(playings[i] == wav) { + playings[i]->close(playings[i]); + + memmove(&playings[i], &playings[i + 1], sizeof(*playings) * (playingCount - i - 1)); + playingCount--; + } + } +} + +struct k3MixWave *k3MixPlay(struct k3MixWave *wav) { + for(size_t i = 0; i < playingCount; i++) { + if(playings[i] == wav) { + return NULL; + } + } + + k3MixPlayDirect(wav); + + return wav; +} + +void k3MixPlayDirect(struct k3MixWave *w) { + w->refs++; + + if(playingCount == playingCapacity) { + playings = realloc(playings, sizeof(*playings) * (playingCapacity += 8)); + } + playings[playingCount++] = w; +} + +#include +__attribute__((optimize("Ofast"))) static void k3MixDoYourThang(size_t sampleCount, float *FinalData) { + memset(FinalData, 0, sampleCount * FinalChannels * sizeof(*FinalData)); + for(size_t i = 0; i < playingCount;) { + intmax_t read = playings[i]->read(playings[i], sampleCount, FinalData); + + if(playings[i]->end) { + k3MixStop(playings[i]); + } else i++; + } + + for(size_t i = 0; i < sampleCount * FinalChannels; i += 4) { + // Compute tanh approximation x*(27+x*x)/(27+9*x*x) + + float *ptr = FinalData + i; + + __m128 x = _mm_loadu_ps(ptr); + __m128 xx = _mm_mul_ps(x, x); + + __m128 numer = _mm_mul_ps(x, _mm_add_ps(_mm_set1_ps(27), xx)); + __m128 denom = _mm_add_ps(_mm_set1_ps(27), _mm_mul_ps(_mm_set1_ps(9), xx)); + + _mm_storeu_ps(ptr, _mm_div_ps(numer, denom)); + } + + // The accuracy isn't worth the function call per sample + /*for(size_t i = 0; i < sampleCount * FinalChannels; i++) { + *FinalData = tanhf(*FinalData); + FinalData++; + }*/ +} + +#include +#include +static PaStream *paStream; +static int pa_callback(const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo *timeInfo, PaStreamCallbackFlags statusFlags, void *ud) { + float *out = output; + + static int done = 0; + if(done == 0) { + done = 1; + _mm_setcsr(_mm_getcsr() | 0x8040); + } + + k3MixDoYourThang(frameCount, out); + + return paContinue; +} +void k3MixPortAudio() { + Pa_Initialize(); + Pa_OpenDefaultStream(&paStream, 0, FinalChannels, paFloat32, FinalSampleRate, 512, pa_callback, NULL); + Pa_StartStream(paStream); +} diff --git a/src/k3mix.h b/src/k3mix.h new file mode 100644 index 0000000..1a45408 --- /dev/null +++ b/src/k3mix.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include + +struct k3MixWave; + +typedef intmax_t(*k3MixWaveReadFunc)(struct k3MixWave *dis, size_t sampleCount, float *buf); +typedef void(*k3MixWaveCloseFunc)(struct k3MixWave *dis); +typedef void(*k3MixWaveCloneFunc)(struct k3MixWave *dis, struct k3MixWave *destination); + +struct k3MixSource; +struct k3MixSource *k3MixSourceFile(const char *path); +void k3MixSourceClose(struct k3MixSource*); + +struct k3MixWave { + size_t refs; + uint32_t sampleRate; + uint8_t channels; + void *data; + + k3MixWaveReadFunc read; + k3MixWaveCloseFunc close; + k3MixWaveCloneFunc clone; + + // All the cool things + bool loop; + bool end; + uint16_t dam; + float volume; +}; + +void k3MixInit(uint32_t sampleRate, uint8_t channels); + +struct k3MixWave *k3MixSimple(struct k3MixSource*); +void k3MixSimpleSeek(struct k3MixWave*, double t); + +struct k3MixWave *k3MixQueue(); +void k3MixQueueAdd(struct k3MixWave *this, struct k3MixWave *child); +void k3MixQueueClear(struct k3MixWave *this); + +struct k3MixWave *k3MixPowerMeasurement(struct k3MixWave *child); +float k3MixPowerMeasurementGetRMS(struct k3MixWave*); + +void k3MixStop(struct k3MixWave*); +struct k3MixWave *k3MixPlay(struct k3MixWave*); +void k3MixPlayDirect(struct k3MixWave*); + +void k3MixPortAudio(); diff --git a/src/k4.h b/src/k4.h new file mode 100644 index 0000000..38e5d96 --- /dev/null +++ b/src/k4.h @@ -0,0 +1,41 @@ +#pragma once + +#define K4_MAX_CONTROLS 32 + +struct k3MScreen; + +#include"stoon.h" +struct NetWrap { + struct Stoon stoon; + + int stage; + float timeout; + + int isHost; + + // Used for punching stage + int gotten; + + char otherpeer[STOON_CONN_INFO_SIZE]; +}; +extern struct NetWrap NetWrap; + +extern struct k3MScreen *UiActive; + +__attribute__((pure)) const char *k4_get_arg(const char *arg); + +int k4_control_set(const char *name, int btn); + +int k4_control_get_id(int btn); + +int k4_control_get_by_name(const char *name); + +int k4_control_get_id_by_name(const char *name); + +const char *k4_control_get_name_by_ctrl(int btn); + +void k4_set_reduction(float); +void k4_set_texture_reduction(int); + +void k4_set_clipboard_text(const char *str); +const char *k4_get_clipboard_text(); diff --git a/src/komihash.h b/src/komihash.h new file mode 100644 index 0000000..a12feef --- /dev/null +++ b/src/komihash.h @@ -0,0 +1,973 @@ +/** + * @file komihash.h + * + * @version 5.10 + * + * @brief The inclusion file for the "komihash" 64-bit hash function, + * "komirand" 64-bit PRNG, and streamed "komihash". + * + * This function is named the way it is named is to honor the Komi Republic + * (located in Russia), native to the author. + * + * Description is available at https://github.com/avaneev/komihash + * + * E-mail: aleksey.vaneev@gmail.com or info@voxengo.com + * + * LICENSE: + * + * Copyright (c) 2021-2024 Aleksey Vaneev + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * 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 OR COPYRIGHT HOLDERS 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. + */ + +#ifndef KOMIHASH_INCLUDED +#define KOMIHASH_INCLUDED + +#include +#include + +#define KOMIHASH_VER_STR "5.10" ///< KOMIHASH source code version string. + +/** + * @def KOMIHASH_LITTLE_ENDIAN + * @brief Endianness definition macro, can be used as a logical constant. + * + * Can be defined externally (e.g., =1, if endianness-correction and + * hash-value portability are unnecessary in any case, to reduce overhead). + */ + +#if !defined( KOMIHASH_LITTLE_ENDIAN ) + #if defined( __LITTLE_ENDIAN__ ) || defined( __LITTLE_ENDIAN ) || \ + defined( _LITTLE_ENDIAN ) || defined( _WIN32 ) || defined( i386 ) || \ + defined( __i386 ) || defined( __i386__ ) || defined( __x86_64__ ) || \ + ( defined( __BYTE_ORDER__ ) && \ + __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) + + #define KOMIHASH_LITTLE_ENDIAN 1 + + #elif defined( __BIG_ENDIAN__ ) || defined( __BIG_ENDIAN ) || \ + defined( _BIG_ENDIAN ) || defined( __SYSC_ZARCH__ ) || \ + defined( __zarch__ ) || defined( __s390x__ ) || defined( __sparc ) || \ + defined( __sparc__ ) || ( defined( __BYTE_ORDER__ ) && \ + __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) + + #define KOMIHASH_LITTLE_ENDIAN 0 + + #else // defined( __BIG_ENDIAN__ ) + + #warning KOMIHASH: cannot determine endianness, assuming little-endian. + + #define KOMIHASH_LITTLE_ENDIAN 1 + + #endif // defined( __BIG_ENDIAN__ ) +#endif // !defined( KOMIHASH_LITTLE_ENDIAN ) + +/** + * @def KOMIHASH_GCC_BUILTINS + * @brief Macro that denotes availability of GCC-style built-in functions. + */ + +#if defined( __GNUC__ ) || defined( __clang__ ) || \ + defined( __IBMC__ ) || defined( __IBMCPP__ ) || defined( __COMPCERT__ ) + + #define KOMIHASH_GCC_BUILTINS + +#endif // GCC built-ins check + +/** + * @def KOMIHASH_EC32( v ) + * @brief Macro that appies 32-bit byte-swapping, for endianness-correction. + * @param v Value to byte-swap. + */ + +/** + * @def KOMIHASH_EC64( v ) + * @brief Macro that appies 64-bit byte-swapping, for endianness-correction. + * @param v Value to byte-swap. + */ + +#if KOMIHASH_LITTLE_ENDIAN + + #define KOMIHASH_EC32( v ) ( v ) + #define KOMIHASH_EC64( v ) ( v ) + +#else // KOMIHASH_LITTLE_ENDIAN + + #if defined( KOMIHASH_GCC_BUILTINS ) + + #define KOMIHASH_EC32( v ) __builtin_bswap32( v ) + #define KOMIHASH_EC64( v ) __builtin_bswap64( v ) + + #elif defined( _MSC_VER ) + + #include + + #define KOMIHASH_EC32( v ) _byteswap_ulong( v ) + #define KOMIHASH_EC64( v ) _byteswap_uint64( v ) + + #else // defined( _MSC_VER ) + + #define KOMIHASH_EC32( v ) ( \ + ( v & 0xFF000000 ) >> 24 | \ + ( v & 0x00FF0000 ) >> 8 | \ + ( v & 0x0000FF00 ) << 8 | \ + ( v & 0x000000FF ) << 24 ) + + #define KOMIHASH_EC64( v ) ( \ + ( v & 0xFF00000000000000 ) >> 56 | \ + ( v & 0x00FF000000000000 ) >> 40 | \ + ( v & 0x0000FF0000000000 ) >> 24 | \ + ( v & 0x000000FF00000000 ) >> 8 | \ + ( v & 0x00000000FF000000 ) << 8 | \ + ( v & 0x0000000000FF0000 ) << 24 | \ + ( v & 0x000000000000FF00 ) << 40 | \ + ( v & 0x00000000000000FF ) << 56 ) + + #endif // defined( _MSC_VER ) + +#endif // KOMIHASH_LITTLE_ENDIAN + +/** + * @def KOMIHASH_LIKELY( x ) + * @brief Likelihood macro that is used for manually-guided + * micro-optimization. + * @param x Expression that is likely to be evaluated to "true". + */ + +/** + * @def KOMIHASH_UNLIKELY( x ) + * @brief Unlikelihood macro that is used for manually-guided + * micro-optimization. + * @param x Expression that is unlikely to be evaluated to "true". + */ + +#if defined( KOMIHASH_GCC_BUILTINS ) + + #define KOMIHASH_LIKELY( x ) __builtin_expect( x, 1 ) + #define KOMIHASH_UNLIKELY( x ) __builtin_expect( x, 0 ) + +#else // defined( KOMIHASH_GCC_BUILTINS ) + + #define KOMIHASH_LIKELY( x ) ( x ) + #define KOMIHASH_UNLIKELY( x ) ( x ) + +#endif // defined( KOMIHASH_GCC_BUILTINS ) + +/** + * @def KOMIHASH_PREFETCH( a ) + * @brief Memory address prefetch macro, to preload some data into CPU cache. + * + * Temporal locality=2, in case a collision resolution would be necessary, + * or for a subsequent disk write. + * + * @param a Prefetch address. + */ + +#if defined( KOMIHASH_GCC_BUILTINS ) && !defined( __COMPCERT__ ) + + #define KOMIHASH_PREFETCH( a ) __builtin_prefetch( a, 0, 2 ) + +#else // Prefetch macro + + #define KOMIHASH_PREFETCH( a ) + +#endif // Prefetch macro + +/** + * @def KOMIHASH_PREFETCH_1 + * @brief Compiler-dependent address prefetch macro, ordered position 1. + * @param a Prefetch address. + */ + +/** + * @def KOMIHASH_PREFETCH_2 + * @brief Compiler-dependent address prefetch macro, ordered position 2. + * @param a Prefetch address. + */ + +#if defined( __clang__ ) + #define KOMIHASH_PREFETCH_1( a ) KOMIHASH_PREFETCH( a ) + #define KOMIHASH_PREFETCH_2( a ) +#else // defined( __clang__ ) + #define KOMIHASH_PREFETCH_1( a ) + #define KOMIHASH_PREFETCH_2( a ) KOMIHASH_PREFETCH( a ) +#endif // defined( __clang__ ) + +/** + * @def KOMIHASH_INLINE + * @brief Macro to force code inlining. + */ + +#if defined( KOMIHASH_GCC_BUILTINS ) + + #define KOMIHASH_INLINE inline __attribute__((always_inline)) + +#elif defined( _MSC_VER ) + + #define KOMIHASH_INLINE inline __forceinline + +#else // defined( _MSC_VER ) + + #define KOMIHASH_INLINE inline + +#endif // defined( _MSC_VER ) + +/** + * @brief Load unsigned 32-bit value with endianness-correction. + * + * An auxiliary function that returns an unsigned 32-bit value created out of + * a sequence of bytes in memory. This function is used to convert endianness + * of in-memory 32-bit unsigned values, and to avoid unaligned memory + * accesses. + * + * @param p Pointer to 4 bytes in memory. Alignment is unimportant. + * @return Endianness-corrected 32-bit value from memory. + */ + +static KOMIHASH_INLINE uint32_t kh_lu32ec( const uint8_t* const p ) +{ + uint32_t v; + memcpy( &v, p, 4 ); + + return( KOMIHASH_EC32( v )); +} + +/** + * @brief Load unsigned 64-bit value with endianness-correction. + * + * An auxiliary function that returns an unsigned 64-bit value created out of + * a sequence of bytes in memory. This function is used to convert endianness + * of in-memory 64-bit unsigned values, and to avoid unaligned memory + * accesses. + * + * @param p Pointer to 8 bytes in memory. Alignment is unimportant. + * @return Endianness-corrected 64-bit value from memory. + */ + +static KOMIHASH_INLINE uint64_t kh_lu64ec( const uint8_t* const p ) +{ + uint64_t v; + memcpy( &v, p, 8 ); + + return( KOMIHASH_EC64( v )); +} + +/** + * @brief Load unsigned 64-bit value with padding (Msg-3 reads). + * + * Function builds an unsigned 64-bit value out of remaining bytes in a + * message, and pads it with the "final byte". This function can only be + * called if less than 8 bytes are left to read. The message should be "long", + * permitting `Msg[ -3 ]` reads. + * + * @param Msg Message pointer, alignment is unimportant. + * @param MsgLen Message's remaining length, in bytes; can be 0. + * @return Final byte-padded value from the message. + */ + +static KOMIHASH_INLINE uint64_t kh_lpu64ec_l3( const uint8_t* const Msg, + const size_t MsgLen ) +{ + const int ml8 = (int) ( MsgLen * 8 ); + + if( MsgLen < 4 ) + { + const uint8_t* const Msg3 = Msg + MsgLen - 3; + const uint64_t m = (uint64_t) Msg3[ 0 ] | (uint64_t) Msg3[ 1 ] << 8 | + (uint64_t) Msg3[ 2 ] << 16; + + return( (uint64_t) 1 << ml8 | m >> ( 24 - ml8 )); + } + + const uint64_t mh = kh_lu32ec( Msg + MsgLen - 4 ); + const uint64_t ml = kh_lu32ec( Msg ); + + return( (uint64_t) 1 << ml8 | ml | ( mh >> ( 64 - ml8 )) << 32 ); +} + +/** + * @brief Load unsigned 64-bit value with padding (non-zero message length). + * + * Function builds an unsigned 64-bit value out of remaining bytes in a + * message, and pads it with the "final byte". This function can only be + * called if less than 8 bytes are left to read. Can be used on "short" + * messages, but `MsgLen` should be greater than 0. + * + * @param Msg Message pointer, alignment is unimportant. + * @param MsgLen Message's remaining length, in bytes; cannot be 0. + * @return Final byte-padded value from the message. + */ + +static KOMIHASH_INLINE uint64_t kh_lpu64ec_nz( const uint8_t* const Msg, + const size_t MsgLen ) +{ + const int ml8 = (int) ( MsgLen * 8 ); + + if( MsgLen < 4 ) + { + uint64_t m = Msg[ 0 ]; + + if( MsgLen > 1 ) + { + m |= (uint64_t) Msg[ 1 ] << 8; + + if( MsgLen > 2 ) + { + m |= (uint64_t) Msg[ 2 ] << 16; + } + } + + return( (uint64_t) 1 << ml8 | m ); + } + + const uint64_t mh = kh_lu32ec( Msg + MsgLen - 4 ); + const uint64_t ml = kh_lu32ec( Msg ); + + return( (uint64_t) 1 << ml8 | ml | ( mh >> ( 64 - ml8 )) << 32 ); +} + +/** + * @brief Load unsigned 64-bit value with padding (Msg-4 reads). + * + * Function builds an unsigned 64-bit value out of remaining bytes in a + * message, and pads it with the "final byte". This function can only be + * called if less than 8 bytes are left to read. The message should be "long", + * permitting `Msg[ -4 ]` reads. + * + * @param Msg Message pointer, alignment is unimportant. + * @param MsgLen Message's remaining length, in bytes; can be 0. + * @return Final byte-padded value from the message. + */ + +static KOMIHASH_INLINE uint64_t kh_lpu64ec_l4( const uint8_t* const Msg, + const size_t MsgLen ) +{ + const int ml8 = (int) ( MsgLen * 8 ); + + if( MsgLen < 5 ) + { + const uint64_t m = kh_lu32ec( Msg + MsgLen - 4 ); + + return( (uint64_t) 1 << ml8 | m >> ( 32 - ml8 )); + } + + const uint64_t m = kh_lu64ec( Msg + MsgLen - 8 ); + + return( (uint64_t) 1 << ml8 | m >> ( 64 - ml8 )); +} + +/** + * @fn void kh_m128( uint64_t u, uint64_t v, uint64_t* rl, uint64_t* rha ) + * @brief 64-bit by 64-bit unsigned multiplication with result accumulation. + * + * @param u Multiplier 1. + * @param v Multiplier 2. + * @param[out] rl The lower half of the 128-bit result. + * @param[in,out] rha The accumulator to receive the higher half of the + * 128-bit result. + */ + +/** + * @def KOMIHASH_EMULU( u, v ) + * @brief Macro for 32-bit by 32-bit unsigned multiplication with 64-bit + * result. + * @param u Multiplier 1. + * @param v Multiplier 2. + */ + +#if defined( _MSC_VER ) && ( defined( _M_ARM64 ) || \ + ( defined( _M_X64 ) && defined( __INTEL_COMPILER ))) + + #include + + static KOMIHASH_INLINE void kh_m128( const uint64_t u, const uint64_t v, + uint64_t* const rl, uint64_t* const rha ) + { + *rl = u * v; + *rha += __umulh( u, v ); + } + +#elif defined( _MSC_VER ) && ( defined( _M_X64 ) || defined( _M_IA64 )) + + #include + #pragma intrinsic(_umul128) + + static KOMIHASH_INLINE void kh_m128( const uint64_t u, const uint64_t v, + uint64_t* const rl, uint64_t* const rha ) + { + uint64_t rh; + *rl = _umul128( u, v, &rh ); + *rha += rh; + } + +#elif defined( __SIZEOF_INT128__ ) + + static KOMIHASH_INLINE void kh_m128( const uint64_t u, const uint64_t v, + uint64_t* const rl, uint64_t* const rha ) + { + const unsigned __int128 r = (unsigned __int128) u * v; + + *rha += (uint64_t) ( r >> 64 ); + *rl = (uint64_t) r; + } + +#elif ( defined( __IBMC__ ) || defined( __IBMCPP__ )) && defined( __LP64__ ) + + static KOMIHASH_INLINE void kh_m128( const uint64_t u, const uint64_t v, + uint64_t* const rl, uint64_t* const rha ) + { + *rl = u * v; + *rha += __mulhdu( u, v ); + } + +#else // defined( __IBMC__ ) + + // _umul128() code for 32-bit systems, adapted from Hacker's Delight, + // Henry S. Warren, Jr. + + #if defined( _MSC_VER ) && !defined( __INTEL_COMPILER ) + + #include + #pragma intrinsic(__emulu) + + #define KOMIHASH_EMULU( u, v ) __emulu( u, v ) + + #else // defined( _MSC_VER ) && !defined( __INTEL_COMPILER ) + + #define KOMIHASH_EMULU( u, v ) ( (uint64_t) ( u ) * ( v )) + + #endif // defined( _MSC_VER ) && !defined( __INTEL_COMPILER ) + + static inline void kh_m128( const uint64_t u, const uint64_t v, + uint64_t* const rl, uint64_t* const rha ) + { + *rl = u * v; + + const uint32_t u0 = (uint32_t) u; + const uint32_t v0 = (uint32_t) v; + const uint64_t w0 = KOMIHASH_EMULU( u0, v0 ); + const uint32_t u1 = (uint32_t) ( u >> 32 ); + const uint32_t v1 = (uint32_t) ( v >> 32 ); + const uint64_t t = KOMIHASH_EMULU( u1, v0 ) + (uint32_t) ( w0 >> 32 ); + const uint64_t w1 = KOMIHASH_EMULU( u0, v1 ) + (uint32_t) t; + + *rha += KOMIHASH_EMULU( u1, v1 ) + (uint32_t) ( w1 >> 32 ) + + (uint32_t) ( t >> 32 ); + } + +#endif // defined( __IBMC__ ) + +/** + * @def KOMIHASH_HASHROUND() + * @brief Macro for a common hashing round without input. + * + * The three instructions in this macro (multiply, add, and XOR) represent the + * simplest constantless PRNG, scalable to any even-sized state variables, + * with the `Seed1` being the PRNG output (2^64 PRNG period). It passes + * `PractRand` tests with rare non-systematic "unusual" evaluations. + * + * To make this PRNG reliable, self-starting, and eliminate a risk of + * stopping, the following variant can be used, which adds a "register + * checker-board", a source of raw entropy. The PRNG is available as the + * komirand() function. Not required for hashing (but works for it) since the + * input entropy is usually available in abundance during hashing. + * + * `Seed5 += 0xAAAAAAAAAAAAAAAA;` + * + * (the `0xAAAA...` constant should match register's size; essentially, it is + * a replication of the `10` bit-pair; it is not an arbitrary constant). + */ + +#define KOMIHASH_HASHROUND() \ + kh_m128( Seed1, Seed5, &Seed1, &Seed5 ); \ + Seed1 ^= Seed5; + +/** + * @def KOMIHASH_HASH16( m ) + * @brief Macro for a common hashing round with 16-byte input. + * @param m Message pointer, alignment is unimportant. + */ + +#define KOMIHASH_HASH16( m ) \ + kh_m128( Seed1 ^ kh_lu64ec( m ), \ + Seed5 ^ kh_lu64ec( m + 8 ), &Seed1, &Seed5 ); \ + Seed1 ^= Seed5; + +/** + * @def KOMIHASH_HASHFIN() + * @brief Macro for common hashing finalization round. + * + * The final hashing input is expected in the `r1h` and `r2h` temporary + * variables. The macro inserts the function return instruction. + */ + +#define KOMIHASH_HASHFIN() \ + kh_m128( r1h, r2h, &Seed1, &Seed5 ); \ + Seed1 ^= Seed5; \ + KOMIHASH_HASHROUND(); \ + return( Seed1 ); + +/** + * @def KOMIHASH_HASHLOOP64() + * @brief Macro for a common 64-byte full-performance hashing loop. + * + * Expects `Msg` and `MsgLen` values (greater than 63), requires initialized + * `Seed1-8` values. + * + * The "shifting" arrangement of `Seed1-4` XORs (below) does not increase + * individual `SeedN` PRNG period beyond 2^64, but reduces a chance of any + * occassional synchronization between PRNG lanes happening. Practically, + * `Seed1-4` together become a single "fused" 256-bit PRNG value, having 2^66 + * summary PRNG period. + */ + +#define KOMIHASH_HASHLOOP64() \ + do \ + { \ + KOMIHASH_PREFETCH_1( Msg ); \ + \ + kh_m128( Seed1 ^ kh_lu64ec( Msg ), \ + Seed5 ^ kh_lu64ec( Msg + 32 ), &Seed1, &Seed5 ); \ + \ + kh_m128( Seed2 ^ kh_lu64ec( Msg + 8 ), \ + Seed6 ^ kh_lu64ec( Msg + 40 ), &Seed2, &Seed6 ); \ + \ + kh_m128( Seed3 ^ kh_lu64ec( Msg + 16 ), \ + Seed7 ^ kh_lu64ec( Msg + 48 ), &Seed3, &Seed7 ); \ + \ + kh_m128( Seed4 ^ kh_lu64ec( Msg + 24 ), \ + Seed8 ^ kh_lu64ec( Msg + 56 ), &Seed4, &Seed8 ); \ + \ + Msg += 64; \ + MsgLen -= 64; \ + \ + KOMIHASH_PREFETCH_2( Msg ); \ + \ + Seed2 ^= Seed5; \ + Seed3 ^= Seed6; \ + Seed4 ^= Seed7; \ + Seed1 ^= Seed8; \ + \ + } while( KOMIHASH_LIKELY( MsgLen > 63 )); + +/** + * @brief The hashing epilogue function (for internal use). + * + * @param Msg Pointer to the remaining part of the message. + * @param MsgLen Remaining part's length, can be 0. + * @param Seed1 Latest Seed1 value. + * @param Seed5 Latest Seed5 value. + * @return 64-bit hash value. + */ + +static KOMIHASH_INLINE uint64_t komihash_epi( const uint8_t* Msg, + size_t MsgLen, uint64_t Seed1, uint64_t Seed5 ) +{ + uint64_t r1h, r2h; + + if( KOMIHASH_LIKELY( MsgLen > 31 )) + { + KOMIHASH_HASH16( Msg ); + KOMIHASH_HASH16( Msg + 16 ); + + Msg += 32; + MsgLen -= 32; + } + + if( MsgLen > 15 ) + { + KOMIHASH_HASH16( Msg ); + + Msg += 16; + MsgLen -= 16; + } + + if( MsgLen > 7 ) + { + r2h = Seed5 ^ kh_lpu64ec_l4( Msg + 8, MsgLen - 8 ); + r1h = Seed1 ^ kh_lu64ec( Msg ); + } + else + { + r1h = Seed1 ^ kh_lpu64ec_l4( Msg, MsgLen ); + r2h = Seed5; + } + + KOMIHASH_HASHFIN(); +} + +/** + * @brief KOMIHASH 64-bit hash function. + * + * Produces and returns a 64-bit hash value of the specified message, string, + * or binary data block. Designed for 64-bit hash-table and hash-map uses. + * Produces identical hashes on both big- and little-endian systems. + * + * @param Msg0 The message to produce a hash from. The alignment of this + * pointer is unimportant. It is valid to pass 0 when `MsgLen` equals 0 + * (assuming that compiler's implementation of the address prefetch permits + * the use of zero address). + * @param MsgLen Message's length, in bytes, can be zero. + * @param UseSeed Optional value, to use instead of the default seed. To use + * the default seed, set to 0. The UseSeed value can have any bit length and + * statistical quality, and is used only as an additional entropy source. May + * need endianness-correction via KOMIHASH_EC64(), if this value is shared + * between big- and little-endian systems. + * @return 64-bit hash of the input data. Should be endianness-corrected when + * this value is shared between big- and little-endian systems. + */ + +static inline uint64_t komihash( const void* const Msg0, size_t MsgLen, + const uint64_t UseSeed ) +{ + const uint8_t* Msg = (const uint8_t*) Msg0; + + // The seeds are initialized to the first mantissa bits of PI. + + uint64_t Seed1 = 0x243F6A8885A308D3 ^ ( UseSeed & 0x5555555555555555 ); + uint64_t Seed5 = 0x452821E638D01377 ^ ( UseSeed & 0xAAAAAAAAAAAAAAAA ); + uint64_t r1h, r2h; + + KOMIHASH_PREFETCH( Msg ); + + KOMIHASH_HASHROUND(); // Required for Perlin Noise. + + if( KOMIHASH_LIKELY( MsgLen < 16 )) + { + r1h = Seed1; + r2h = Seed5; + + if( MsgLen > 7 ) + { + // The following two XOR instructions are equivalent to mixing a + // message with a cryptographic one-time-pad (bitwise modulo 2 + // addition). Message's statistics and distribution are thus + // unimportant. + + r2h ^= kh_lpu64ec_l3( Msg + 8, MsgLen - 8 ); + r1h ^= kh_lu64ec( Msg ); + } + else + if( KOMIHASH_LIKELY( MsgLen != 0 )) + { + r1h ^= kh_lpu64ec_nz( Msg, MsgLen ); + } + + KOMIHASH_HASHFIN(); + } + + if( KOMIHASH_LIKELY( MsgLen < 32 )) + { + KOMIHASH_HASH16( Msg ); + + if( MsgLen > 23 ) + { + r2h = Seed5 ^ kh_lpu64ec_l4( Msg + 24, MsgLen - 24 ); + r1h = Seed1 ^ kh_lu64ec( Msg + 16 ); + KOMIHASH_HASHFIN(); + } + else + { + r1h = Seed1 ^ kh_lpu64ec_l4( Msg + 16, MsgLen - 16 ); + r2h = Seed5; + KOMIHASH_HASHFIN(); + } + } + + if( KOMIHASH_LIKELY( MsgLen > 63 )) + { + uint64_t Seed2 = 0x13198A2E03707344 ^ Seed1; + uint64_t Seed3 = 0xA4093822299F31D0 ^ Seed1; + uint64_t Seed4 = 0x082EFA98EC4E6C89 ^ Seed1; + uint64_t Seed6 = 0xBE5466CF34E90C6C ^ Seed5; + uint64_t Seed7 = 0xC0AC29B7C97C50DD ^ Seed5; + uint64_t Seed8 = 0x3F84D5B5B5470917 ^ Seed5; + + KOMIHASH_HASHLOOP64(); + + Seed5 ^= Seed6 ^ Seed7 ^ Seed8; + Seed1 ^= Seed2 ^ Seed3 ^ Seed4; + } + + return( komihash_epi( Msg, MsgLen, Seed1, Seed5 )); +} + +/** + * @brief KOMIRAND 64-bit pseudo-random number generator. + * + * Simple, reliable, self-starting yet efficient PRNG, with 2^64 period. + * 0.62 cycles/byte performance. Self-starts in 4 iterations, which is a + * suggested "warming up" initialization before using its output. + * + * @param[in,out] Seed1 Seed value 1. Can be initialized to any value + * (even 0). This is the usual "PRNG seed" value. + * @param[in,out] Seed2 Seed value 2, a supporting variable. Best initialized + * to the same value as `Seed1`. + * @return The next uniformly-random 64-bit value. + */ + +static KOMIHASH_INLINE uint64_t komirand( uint64_t* const Seed1, + uint64_t* const Seed2 ) +{ + uint64_t s1 = *Seed1; + uint64_t s2 = *Seed2; + + kh_m128( s1, s2, &s1, &s2 ); + s2 += 0xAAAAAAAAAAAAAAAA; + s1 ^= s2; + + *Seed2 = s2; + *Seed1 = s1; + + return( s1 ); +} + +/** + * @def KOMIHASH_BUFSIZE + * @brief Streamed hashing's buffer size, in bytes. + * + * Must be a multiple of 64, and not less than 128. Can be defined externally. + */ + +#if !defined( KOMIHASH_BUFSIZE ) + + #define KOMIHASH_BUFSIZE 768 + +#endif // !defined( KOMIHASH_BUFSIZE ) + +/** + * @brief Context structure for the streamed "komihash" hashing. + * + * The komihash_init() function should be called to initalize the structure + * before hashing. Note that the default buffer size is modest, permitting + * placement of this structure on stack. `Seed[ 0 ]` is used as `UseSeed` + * value storage. + */ + +typedef struct { + uint8_t pb[ 8 ]; ///< Buffer's padding bytes, to avoid OOB. + uint8_t Buf[ KOMIHASH_BUFSIZE ]; ///< Buffer. + uint64_t Seed[ 8 ]; ///< Hashing state variables. + size_t BufFill; ///< Buffer fill count (position), in bytes. + size_t IsHashing; ///< 0 or 1, equals 1 if the actual hashing was started. +} komihash_stream_t; + +/** + * @brief Function initializes the streamed "komihash" hashing session. + * + * @param[out] ctx Pointer to the context structure. + * @param UseSeed Optional value, to use instead of the default seed. To use + * the default seed, set to 0. The UseSeed value can have any bit length and + * statistical quality, and is used only as an additional entropy source. May + * need endianness-correction via KOMIHASH_EC64(), if this value is shared + * between big- and little-endian systems. + */ + +static inline void komihash_stream_init( komihash_stream_t* const ctx, + const uint64_t UseSeed ) +{ + ctx -> Seed[ 0 ] = UseSeed; + ctx -> BufFill = 0; + ctx -> IsHashing = 0; +} + +/** + * @brief Function updates the streamed hashing state with a new input data. + * + * @param[in,out] ctx Pointer to the context structure. The structure must be + * initialized via the komihash_stream_init() function. + * @param Msg0 The next part of the whole message being hashed. The alignment + * of this pointer is unimportant. It is valid to pass 0 when `MsgLen` equals + * 0. + * @param MsgLen Message's length, in bytes, can be zero. + */ + +static inline void komihash_stream_update( komihash_stream_t* const ctx, + const void* const Msg0, size_t MsgLen ) +{ + const uint8_t* Msg = (const uint8_t*) Msg0; + + const uint8_t* SwMsg = 0; + size_t SwMsgLen = 0; + size_t BufFill = ctx -> BufFill; + + if( BufFill + MsgLen >= KOMIHASH_BUFSIZE && BufFill != 0 ) + { + const size_t CopyLen = KOMIHASH_BUFSIZE - BufFill; + memcpy( ctx -> Buf + BufFill, Msg, CopyLen ); + BufFill = 0; + + SwMsg = Msg + CopyLen; + SwMsgLen = MsgLen - CopyLen; + + Msg = ctx -> Buf; + MsgLen = KOMIHASH_BUFSIZE; + } + + if( BufFill == 0 ) + { + while( MsgLen > 127 ) + { + uint64_t Seed1, Seed2, Seed3, Seed4; + uint64_t Seed5, Seed6, Seed7, Seed8; + + KOMIHASH_PREFETCH_2( Msg ); + + if( ctx -> IsHashing ) + { + Seed1 = ctx -> Seed[ 0 ]; + Seed2 = ctx -> Seed[ 1 ]; + Seed3 = ctx -> Seed[ 2 ]; + Seed4 = ctx -> Seed[ 3 ]; + Seed5 = ctx -> Seed[ 4 ]; + Seed6 = ctx -> Seed[ 5 ]; + Seed7 = ctx -> Seed[ 6 ]; + Seed8 = ctx -> Seed[ 7 ]; + } + else + { + ctx -> IsHashing = 1; + + const uint64_t UseSeed = ctx -> Seed[ 0 ]; + Seed1 = 0x243F6A8885A308D3 ^ ( UseSeed & 0x5555555555555555 ); + Seed5 = 0x452821E638D01377 ^ ( UseSeed & 0xAAAAAAAAAAAAAAAA ); + + KOMIHASH_HASHROUND(); + + Seed2 = 0x13198A2E03707344 ^ Seed1; + Seed3 = 0xA4093822299F31D0 ^ Seed1; + Seed4 = 0x082EFA98EC4E6C89 ^ Seed1; + Seed6 = 0xBE5466CF34E90C6C ^ Seed5; + Seed7 = 0xC0AC29B7C97C50DD ^ Seed5; + Seed8 = 0x3F84D5B5B5470917 ^ Seed5; + } + + KOMIHASH_HASHLOOP64(); + + ctx -> Seed[ 0 ] = Seed1; + ctx -> Seed[ 1 ] = Seed2; + ctx -> Seed[ 2 ] = Seed3; + ctx -> Seed[ 3 ] = Seed4; + ctx -> Seed[ 4 ] = Seed5; + ctx -> Seed[ 5 ] = Seed6; + ctx -> Seed[ 6 ] = Seed7; + ctx -> Seed[ 7 ] = Seed8; + + if( SwMsgLen == 0 ) + { + if( MsgLen != 0 ) + { + break; + } + + ctx -> BufFill = 0; + return; + } + + Msg = SwMsg; + MsgLen = SwMsgLen; + SwMsgLen = 0; + } + } + + ctx -> BufFill = BufFill + MsgLen; + uint8_t* op = ctx -> Buf + BufFill; + + while( MsgLen != 0 ) + { + *op = *Msg; + Msg++; + op++; + MsgLen--; + } +} + +/** + * @brief Function finalizes the streamed "komihash" hashing session. + * + * Returns the resulting hash value of the previously hashed data. This value + * is equal to the value returned by the komihash() function for the same + * provided data. + * + * Note that since this function is non-destructive to the context structure, + * the function can be used to obtain intermediate hashes of the data stream + * being hashed, and the hashing can then be resumed. + * + * @param[in] ctx Pointer to the context structure. The structure must be + * initialized via the komihash_stream_init() function. + * @return 64-bit hash value. Should be endianness-corrected when this value + * is shared between big- and little-endian systems. + */ + +static inline uint64_t komihash_stream_final( komihash_stream_t* const ctx ) +{ + const uint8_t* Msg = ctx -> Buf; + size_t MsgLen = ctx -> BufFill; + + if( ctx -> IsHashing == 0 ) + { + return( komihash( Msg, MsgLen, ctx -> Seed[ 0 ])); + } + + ctx -> pb[ 4 ] = 0; + ctx -> pb[ 5 ] = 0; + ctx -> pb[ 6 ] = 0; + ctx -> pb[ 7 ] = 0; + + uint64_t Seed1 = ctx -> Seed[ 0 ]; + uint64_t Seed2 = ctx -> Seed[ 1 ]; + uint64_t Seed3 = ctx -> Seed[ 2 ]; + uint64_t Seed4 = ctx -> Seed[ 3 ]; + uint64_t Seed5 = ctx -> Seed[ 4 ]; + uint64_t Seed6 = ctx -> Seed[ 5 ]; + uint64_t Seed7 = ctx -> Seed[ 6 ]; + uint64_t Seed8 = ctx -> Seed[ 7 ]; + + if( MsgLen > 63 ) + { + KOMIHASH_HASHLOOP64(); + } + + Seed5 ^= Seed6 ^ Seed7 ^ Seed8; + Seed1 ^= Seed2 ^ Seed3 ^ Seed4; + + return( komihash_epi( Msg, MsgLen, Seed1, Seed5 )); +} + +/** + * @brief FOR TESTING PURPOSES ONLY - use the komihash() function instead. + * + * @param Msg The message to produce a hash from. + * @param MsgLen Message's length, in bytes. + * @param UseSeed Seed to use. + * @return 64-bit hash value. + */ + +static inline uint64_t komihash_stream_oneshot( const void* const Msg, + const size_t MsgLen, const uint64_t UseSeed ) +{ + komihash_stream_t ctx; + + komihash_stream_init( &ctx, UseSeed ); + komihash_stream_update( &ctx, Msg, MsgLen ); + + return( komihash_stream_final( &ctx )); +} + +#endif // KOMIHASH_INCLUDED diff --git a/src/loaders.inc b/src/loaders.inc new file mode 100644 index 0000000..d1ab3f0 --- /dev/null +++ b/src/loaders.inc @@ -0,0 +1,347 @@ +static int matloader(void *ud, struct ResManRes *res) { + char namebuf[256] = {}; + snprintf(namebuf, sizeof(namebuf), "assets/mdl/%s.lua", res->name); + + struct k3Mat *mat = _mm_malloc(sizeof(*mat), 16); + luaapi_fillmaterial(namebuf, mat); + + res->thing = mat; + return 1; +} + +static int mdlloader(void *ud, struct ResManRes *res) { + char buf[256]; + snprintf(buf, sizeof(buf), "assets/mdl/%s.k3m", res->name); + + FILE *f = fopen(buf, "rb"); + + struct { + uint32_t magic; + uint32_t vertCount; + uint32_t indCount; + uint8_t boneCount; + uint8_t flags; + uint16_t animCount; + } header; + fread(&header, 4, 4, f); + + int colorsEnabled = header.flags & 1; + + mat4 *invBind = _mm_malloc(sizeof(*invBind) * header.boneCount, 16); + fread(invBind, sizeof(*invBind), header.boneCount, f); + + uint8_t *boneParents = malloc(header.boneCount); + fread(boneParents, 1, header.boneCount, f); + + vec3 *pos = malloc(sizeof(*pos) * header.vertCount); + fread(pos, sizeof(vec3), header.vertCount, f); + + uint8_t *nrm = malloc(3 * header.vertCount); + fread(nrm, 3, header.vertCount, f); + + float *uvs = malloc(8 * header.vertCount); + fread(uvs, 8, header.vertCount, f); + + uint8_t *boneIDs = malloc(4 * header.vertCount); + fread(boneIDs, 4, header.vertCount, f); + + uint16_t *boneWeights = malloc(8 * header.vertCount); + fread(boneWeights, 8, header.vertCount, f); + + uint8_t *cols = NULL; + if(colorsEnabled) { + cols = malloc(4 * header.vertCount); + fread(cols, 4, header.vertCount, f); + } + + uint16_t *inds = malloc(sizeof(*inds) * header.indCount); + fread(inds, sizeof(uint16_t), header.indCount, f); + + struct k3Mdl *mdl = k3MdlCreate(header.vertCount, header.indCount, header.boneCount, pos, nrm, uvs, cols, boneIDs, boneWeights, inds, invBind, boneParents); + + k3MdlSetDebugName(mdl, res->name); + + free(pos); + free(nrm); + free(uvs); + free(inds); + + uint16_t meshes; + fread(&meshes, sizeof(uint16_t), 1, f); + + for(uint32_t i = 0; i < meshes; i++) { + uint16_t startnum[2]; + fread(startnum, sizeof(uint16_t), 2, f); + + char buf[256] = {}; + for(int c = 0; c < sizeof(buf) - 1; c++) { + fread(buf + c, 1, 1, f); + if(buf[c] == 0) { + break; + } + } + + k3MdlAddMesh(mdl, resman_ref(RESMAN_MATERIAL, buf), startnum[0], startnum[1]); + } + + for(size_t i = 0; i < header.animCount; i++) { + struct { + uint16_t id; + uint16_t frames; + uint16_t fps; + uint16_t zero; + } info; + fread(&info, sizeof(info), 1, f); + + struct k3Animation *anim = malloc(sizeof(*anim)); + anim->frames = _mm_malloc(sizeof(*anim->frames) * info.frames * header.boneCount, 16); + anim->boneParents = boneParents; + anim->invBind = invBind; + anim->id = info.id; + anim->fps = info.fps; + anim->frameCount = info.frames; + anim->boneCount = header.boneCount; + + fread(anim->frames, sizeof(*anim->frames), info.frames * header.boneCount, f); + + k3MdlAddAnim(mdl, anim); + } + + fclose(f); + + res->thing = mdl; + return 1; +} + +static int physloader(void *ud, struct ResManRes *res) { + char namebuf[256]; + snprintf(namebuf, sizeof(namebuf), "assets/phys/%s.phys", res->name); + + FILE *p = fopen(namebuf, "rb"); + if(!p) return 0; + dTriMeshDataID trid = dGeomTriMeshDataCreate(); + fseek(p, 0, SEEK_END); + size_t len = ftell(p); + assert(len % 36 == 0); + fseek(p, 0, SEEK_SET); + float *data = malloc(len); + fread(data, 1, len, p); + int *idxs = malloc(sizeof(*idxs) * (len / sizeof(vec3))); + for(int i = 0; i < len / sizeof(vec3); i++) idxs[i] = i; + dGeomTriMeshDataBuildSingle(trid, data, sizeof(vec3), len / sizeof(vec3), idxs, len / sizeof(vec3), 3 * sizeof(int)); + fclose(p); + + struct TrimeshData *ret = malloc(sizeof(*ret)); + ret->vdata = data; + ret->idata = idxs; + ret->trid = trid; + + res->thing = ret; + return 1; +} + +static int binloader(void *ud, struct ResManRes *res) { + char namebuf[256]; + snprintf(namebuf, sizeof(namebuf), "assets/%s", res->name); + + FILE *f = fopen(namebuf, "rb"); + if(!f) return 0; + + fseek(f, 0, SEEK_END); + size_t len = ftell(f); + struct ResManBin *data = malloc(sizeof(*data) + len + 1); + fseek(f, 0, SEEK_SET); + fread(data->data, 1, len, f); + data->data[len] = 0; + data->length = len; + fclose(f); + + res->thing = data; + return 1; +} +static void binunloader(void *ud, const char *name, void *data) { + free(data); +} + +static int streamloader(void *ud, struct ResManRes *res) { + char namebuf[256]; + snprintf(namebuf, sizeof(namebuf), "assets/aud/%s", res->name); + + res->thing = k3MixSourceFile(namebuf); + return 1; +} + +static int refresh_texture(struct ResManRes *res) { + if(strlen(res->name) < 8) return 0; + + const char *suffix = res->name + strlen(res->name) - 8; + + if(!strcmp(suffix, ".cub.png")) { + char namebuf[256]; + int w, h, origN; + unsigned char *data; + + struct k3Tex *tex = res->thing; + + if(!tex) { + tex = k3TexCreate(k3_CUBEMAP); + } + + snprintf(namebuf, sizeof(namebuf), "assets/mdl/%.*s.nx.png", suffix - res->name, res->name); + data = stbi_load(namebuf, &w, &h, &origN, 4); + k3TexUpdate(tex, k3_DIFFUSE, 1, w, h, data); + stbi_image_free(data); + + snprintf(namebuf, sizeof(namebuf), "assets/mdl/%.*s.px.png", suffix - res->name, res->name); + data = stbi_load(namebuf, &w, &h, &origN, 4); + k3TexUpdate(tex, k3_DIFFUSE, 0, w, h, data); + stbi_image_free(data); + + snprintf(namebuf, sizeof(namebuf), "assets/mdl/%.*s.py.png", suffix - res->name, res->name); + data = stbi_load(namebuf, &w, &h, &origN, 4); + k3TexUpdate(tex, k3_DIFFUSE, 2, w, h, data); + stbi_image_free(data); + + snprintf(namebuf, sizeof(namebuf), "assets/mdl/%.*s.ny.png", suffix - res->name, res->name); + data = stbi_load(namebuf, &w, &h, &origN, 4); + k3TexUpdate(tex, k3_DIFFUSE, 3, w, h, data); + stbi_image_free(data); + + snprintf(namebuf, sizeof(namebuf), "assets/mdl/%.*s.nz.png", suffix - res->name, res->name); + data = stbi_load(namebuf, &w, &h, &origN, 4); + k3TexUpdate(tex, k3_DIFFUSE, 5, w, h, data); + stbi_image_free(data); + + snprintf(namebuf, sizeof(namebuf), "assets/mdl/%.*s.pz.png", suffix - res->name, res->name); + data = stbi_load(namebuf, &w, &h, &origN, 4); + k3TexUpdate(tex, k3_DIFFUSE, 4, w, h, data); + stbi_image_free(data); + + res->thing = tex; + } else { + enum k3TexType type; + int n, gamma; + + if(!strcmp(suffix, ".alp.png")) { + type = k3_ALPHA; + n = 1; + gamma = 0; + } else if(!strcmp(suffix, ".nrm.png")) { + type = k3_NORMAL; + n = 4; + gamma = 1; + } else if(!strcmp(suffix, ".dsp.png")) { + type = k3_DISPLACEMENT; + n = 1; + gamma = 0; + } else if(!strcmp(suffix, ".emt.png")) { + type = k3_EMISSION; + n = 4; + gamma = 1; + } else if(!strcmp(suffix, ".rgh.png")) { + type = k3_ROUGHNESS; + n = 1; + gamma = 0; + } else if(!strcmp(suffix, ".dif.png")) { + type = k3_DIFFUSE; + n = 4; + gamma = 1; + } else return 0; + + char namebuf[256]; + snprintf(namebuf, sizeof(namebuf), "assets/mdl/%s", res->name); + + int w, h, origN; + unsigned char *data = stbi_load(namebuf, &w, &h, &origN, n); + int stbifree = 1; + + if(TextureResolutionReduction && data) { + int newW = w >> TextureResolutionReduction; + int newH = h >> TextureResolutionReduction; + + if(newW <= 4) newW = 4; + if(newH <= 4) newH = 4; + + unsigned char *data2 = malloc(newW * newH * n); + int success = stbir_resize_uint8_generic(data, w, h, 0, data2, newW, newH, 0, n, n == 4 ? 3 : -1, 0, STBIR_EDGE_WRAP, STBIR_FILTER_DEFAULT, gamma ? STBIR_COLORSPACE_SRGB : STBIR_COLORSPACE_LINEAR, NULL); + + if(success) { + stbi_image_free(data); + + w = newW; + h = newH; + data = data2; + stbifree = 0; + } else { + free(data2); + } + } + + if(!res->thing) { + res->thing = k3TexCreate(type); + } + + if(data) { + k3TexUpdate(res->thing, type, 0, w, h, data); + + if(stbifree) { + stbi_image_free(data); + } else { + free(data); + } + } + } + + return 1; +} + +static int refresh_textures() { + for(int b = 0; b < RESMAN_BUCKETS; b++) { + for(struct ResManRes *r = ResMan.buckets[b]; r; r = r->next) { + if(r->type == RESMAN_TEXTURE) { + refresh_texture(r); + } + } + } +} + +static int texloader(void *ud, struct ResManRes *res) { + refresh_texture(res); + return 1; +} + +static int fontloader(void *ud, struct ResManRes *res) { + FILE *fntf = fopen(res->name, "rb"); + fseek(fntf, 0, SEEK_END); + size_t fntfsz = ftell(fntf); + fseek(fntf, 0, SEEK_SET); + char *fntbuf = malloc(fntfsz); + fread(fntbuf, 1, fntfsz, fntf); + + struct k3Font *fnt = k3FontCreate(); + struct k3Tex *fnttexldr(struct k3Font *fnt, const char *name) { + return resman_ref(RESMAN_TEXTURE, name); + } + k3FontLoad(fnt, fntbuf, fntfsz, fnttexldr); + + res->thing = fnt; + + return 1; +} + +static void init_res_handlers() { + ResMan.handlers[RESMAN_MATERIAL].loader = matloader; + + ResMan.handlers[RESMAN_MODEL].loader = mdlloader; + + ResMan.handlers[RESMAN_PHYSICS].loader = physloader; + + ResMan.handlers[RESMAN_BIN].loader = binloader; + ResMan.handlers[RESMAN_BIN].unloader = binunloader; + + ResMan.handlers[RESMAN_STREAM].loader = streamloader; + + ResMan.handlers[RESMAN_TEXTURE].loader = texloader; + + ResMan.handlers[RESMAN_FONT].loader = fontloader; +} diff --git a/src/luaapi.c b/src/luaapi.c new file mode 100644 index 0000000..fc45347 --- /dev/null +++ b/src/luaapi.c @@ -0,0 +1,3422 @@ +#include"luaapi.h" + +#include"resman.h" +#include +#include +#include +#include"game.h" +#include"k3mix.h" +#include"k3water.h" +#include"net_server.h" +#include"net_client.h" +#include"gl.h" +#include"k4.h" +#include"net.h" +#include"k3menu.h" +#include + +/* + * This is by far the least clean or well-maintained source in the + * entire project. Touch it as little as possible to minimize loss + * of sanity. + * */ + +static lua_State *L; + +#define seti(src, dst) \ + lua_getfield(L, -1, src);\ + li = lua_tointegerx(L, -1, &i);\ + if(i) {\ + dst = li;\ + }\ + lua_pop(L, 1); + +#define setf(src, dst) \ + lua_getfield(L, -1, src);\ + dst = lua_tonumber(L, -1);\ + lua_pop(L, 1); + +#define setv3(src, dst) \ + lua_getfield(L, -1, src);\ + if(lua_istable(L, -1)) {\ + lua_geti(L, -1, 1);\ + lua_geti(L, -2, 2);\ + lua_geti(L, -3, 3);\ + dst[0] = lua_tonumber(L, -3);\ + dst[1] = lua_tonumber(L, -2);\ + dst[2] = lua_tonumber(L, -1);\ + lua_pop(L, 3);\ + }\ + lua_pop(L, 1); + +#define setv4(src, dst) \ + lua_getfield(L, -1, src);\ + if(lua_istable(L, -1)) {\ + lua_geti(L, -1, 1);\ + lua_geti(L, -2, 2);\ + lua_geti(L, -3, 3);\ + lua_geti(L, -3, 4);\ + dst[0] = lua_tonumber(L, -4);\ + dst[1] = lua_tonumber(L, -3);\ + dst[2] = lua_tonumber(L, -2);\ + dst[3] = lua_tonumber(L, -1);\ + lua_pop(L, 4);\ + }\ + lua_pop(L, 1); + +#define setstrstatic(src, dst, maxlen) \ + lua_getfield(L, -1, src);\ + if(lua_isstring(L, -1)) {\ + size_t len;\ + const char *s = lua_tolstring(L, -1, &len);\ + strncpy(dst, s, (maxlen) - 1);\ + }\ + lua_pop(L, 1); + +static int serialize(struct bstr *b) { + int top = lua_gettop(L); + + if(lua_type(L, -1) == LUA_TNIL) { + b_wu8(b, 0); + } else if(lua_type(L, -1) == LUA_TNUMBER) { + if(lua_isinteger(L, -1)) { + b_wu8(b, 1); + b_wu64(b, lua_tointeger(L, -1)); + } else { + b_wu8(b, 2); + b_wf64(b, lua_tonumber(L, -1)); + } + } else if(lua_type(L, -1) == LUA_TSTRING) { + b_wu8(b, 3); + + size_t len; + const uint8_t *data = lua_tolstring(L, -1, &len); + + b_wu32(b, len); + b_wraw(b, data, len); + } else if(lua_type(L, -1) == LUA_TBOOLEAN) { + b_wu8(b, lua_toboolean(L, -1) ? 5 : 4); + } else if(lua_type(L, -1) == LUA_TTABLE) { + b_wu8(b, 6); + + lua_pushnil(L); + + while(lua_next(L, -2)) { + + lua_pushvalue(L, -2); + if(!serialize(b)) goto error; + lua_pop(L, 1); + + if(!serialize(b)) goto error; + lua_pop(L, 1); + + } + + b_wu8(b, 0); + } else goto error; + + return 1; + +error: + + lua_settop(L, top); + + return 0; +} + +static int deserialize(struct bstr *b) { + uint8_t type = b_ru8(b); + + int top = lua_gettop(L); + + if(type == 0) { + lua_pushnil(L); + } else if(type == 1) { + lua_pushinteger(L, b_ru64(b)); + } else if(type == 2) { + lua_pushnumber(L, b_rf64(b)); + } else if(type == 3) { + size_t len = b_ru32(b); + + lua_pushlstring(L, b_rraw(b, len), len); + } else if(type == 4) { + lua_pushboolean(L, 0); + } else if(type == 5) { + lua_pushboolean(L, 1); + } else if(type == 6) { + lua_newtable(L); + + while(1) { + deserialize(b); + + if(lua_type(L, -1) == LUA_TNIL) { + lua_pop(L, 1); + break; + } + + deserialize(b); + + lua_rawset(L, -3); + } + } else goto error; + + return 1; + +error: + + lua_settop(L, top); + + return 0; +} + +static int game_addentity(lua_State *L) { + lua_Integer li; + int i; + + uint16_t id; + + lua_getfield(L, 1, "id"); + if(lua_isnil(L, -1)) { + id = game_nextid(); + } else { + id = lua_tointeger(L, -1); + } + lua_pop(L, 1); + + game_claimentid(id); + + lua_getfield(L, 1, "physics"); + if(lua_istable(L, -1)) { + struct CPhysics c; + memset(&c, 0, sizeof(c)); + + c.entity = id; + + seti("trigger", c.trigger); + seti("type", c.type); + seti("dynamics", c.dynamics); + + if(c.type == CPHYSICS_CAPSULE) { + lua_getfield(L, -1, "capsule"); + setf("radius", c.capsule.radius); + setf("length", c.capsule.length); + lua_pop(L, 1); + } else if(c.type == CPHYSICS_BOX) { + lua_getfield(L, -1, "box"); + setf("w", c.box.w); + setf("h", c.box.h); + setf("l", c.box.l); + lua_pop(L, 1); + } else if(c.type == CPHYSICS_SPHERE) { + lua_getfield(L, -1, "sphere"); + setf("radius", c.sphere.radius); + lua_pop(L, 1); + } else if(c.type == CPHYSICS_TRIMESH) { + lua_getfield(L, -1, "trimesh"); + if(lua_type(L, -1) == LUA_TSTRING) { + strncpy(c.trimesh.name, lua_tostring(L, -1), sizeof(c.trimesh.name) - 1); + } else { + c.trimesh.cache = *(struct TrimeshData**) luaL_checkudata(L, -1, "k3physics"); + } + lua_pop(L, 1); + } + + setf("speed", c.speed); + + lua_getfield(L, -1, "mass"); + c.mass = lua_isnil(L, -1) ? 1 : lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "friction"); + c.friction = lua_isnil(L, -1) ? 1.414 : lua_tonumber(L, -1); + lua_pop(L, 1); + + setv3("pos", c.start); + + c.collide = CATEGORY_STATIC | CATEGORY_ENTITY; + lua_getfield(L, -1, "collide"); + if(!lua_isnil(L, -1)) { + c.collide = lua_tointeger(L, -1); + } + lua_pop(L, 1); + + lua_getfield(L, -1, "rot"); + if(lua_istable(L, -1)) { + lua_geti(L, -1, 1); + lua_geti(L, -2, 2); + lua_geti(L, -3, 3); + lua_geti(L, -4, 4); + c.rot[0] = lua_tonumber(L, -4); + c.rot[1] = lua_tonumber(L, -3); + c.rot[2] = lua_tonumber(L, -2); + c.rot[3] = lua_tonumber(L, -1); + lua_pop(L, 4); + } else { + c.rot[0] = 0; + c.rot[1] = 0; + c.rot[2] = 0; + c.rot[3] = 1; + } + lua_pop(L, 1); + + game_addcomponent(physics, &c); + } + lua_pop(L, 1); + + lua_getfield(L, 1, "render"); + if(lua_istable(L, -1)) { + struct CRender c; + memset(&c, 0, sizeof(c)); + + c.entity = id; + + setv4("pos", c.pos); + setv4("rot", c.rot); + + setstrstatic("mdl", c.mdl, sizeof(c.mdl)); + + //c.animator.base = NULL; + + game_addcomponent(render, &c); + } + lua_pop(L, 1); + + lua_getfield(L, 1, "movement"); + if(lua_istable(L, -1)) { + struct CMovement c; + memset(&c, 0, sizeof(c)); + + c.entity = id; + + setv3("dir", c.dir); + + setf("pointing", c.pointing); + + seti("jump", c.jump); + seti("canjump", c.canJump); + + c.holding = ENT_ID_INVALID; + + game_addcomponent(movement, &c); + } + lua_pop(L, 1); + + lua_getfield(L, 1, "boned"); + if(lua_istable(L, -1)) { + struct CBoned c; + memset(&c, 0, sizeof(c)); + + c.entity = id; + + lua_getfield(L, -1, "size"); + if(lua_isnil(L, -1)) { + lua_pop(L, 1); + lua_getfield(L, -1, "bones"); + c.size = lua_isnil(L, -1) ? 0 : luaL_len(L, -1); + } else { + c.size = lua_tointeger(L, -1); + lua_pop(L, 1); + lua_getfield(L, -1, "bones"); + } + + c.bones = _mm_malloc(sizeof(*c.bones) * c.size, 16); + + if(lua_isnil(L, -1)) { + glm_quat_identity_array((versor*) c.bones, c.size * 2); + } else { + for(size_t i = 0; i < c.size; i++) { + lua_rawgeti(L, -1, i + 1); // bone + + if(lua_isnil(L, -1)) { + c.bones[i].translation[0] = 0; + c.bones[i].translation[1] = 0; + c.bones[i].translation[2] = 0; + c.bones[i].translation[3] = 1; + + c.bones[i].rotation[0] = 0; + c.bones[i].rotation[1] = 0; + c.bones[i].rotation[2] = 0; + c.bones[i].rotation[3] = 1; + } else { + lua_rawgeti(L, -1, 1); // translation + lua_rawgeti(L, -1, 1); // x + lua_rawgeti(L, -2, 2); // y + lua_rawgeti(L, -3, 3); // z + lua_rawgeti(L, -4, 4); // w + c.bones[i].translation[0] = lua_tonumber(L, -4); + c.bones[i].translation[1] = lua_tonumber(L, -3); + c.bones[i].translation[2] = lua_tonumber(L, -2); + c.bones[i].translation[3] = lua_tonumber(L, -1); + lua_pop(L, 5); + + lua_rawgeti(L, -1, 2); // rotation + lua_rawgeti(L, -1, 1); // x + lua_rawgeti(L, -2, 2); // y + lua_rawgeti(L, -3, 3); // z + lua_rawgeti(L, -4, 4); // w + c.bones[i].rotation[0] = lua_tonumber(L, -4); + c.bones[i].rotation[1] = lua_tonumber(L, -3); + c.bones[i].rotation[2] = lua_tonumber(L, -2); + c.bones[i].rotation[3] = lua_tonumber(L, -1); + lua_pop(L, 5); + } + + lua_pop(L, 1); + } + } + + lua_pop(L, 1); + + lua_getfield(L, -1, "anim"); + if(lua_istable(L, -1)) { + lua_getfield(L, -1, "id"); + c.anim.id = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "standard"); + c.anim.standard = lua_toboolean(L, -1); + lua_pop(L, 1); + } + lua_pop(L, 1); + + game_addcomponent(boned, &c); + } + lua_pop(L, 1); + + lua_pushinteger(L, id); + return 1; +} + +double LuaapiStartTime; +float LuaapiFov = 75; + +static int gametriggersref; +static int luaapi_triggerfunc(size_t id, uint16_t ethis, uint16_t ethat, uint8_t event) { + lua_rawgeti(L, LUA_REGISTRYINDEX, gametriggersref); + lua_rawgeti(L, -1, id); + + lua_pushinteger(L, id); + + if(ethis == ENT_ID_INVALID) + lua_pushnil(L); + else + lua_pushinteger(L, ethis); + + if(ethat == ENT_ID_INVALID) + lua_pushnil(L); + else + lua_pushinteger(L, ethat); + + lua_pushinteger(L, event); + + if(lua_pcall(L, 4, 0, 0) != LUA_OK) { + puts(lua_tolstring(L, -1, NULL)); + lua_pop(L, 1); + } + lua_pop(L, 1); +} +static int game_triggers_set(lua_State *L) { + size_t idx = lua_tointeger(L, 2); + if(idx >= 1 && idx <= MAX_TRIGGERS) { + lua_pushvalue(L, 2); + lua_pushvalue(L, 3); + lua_rawset(L, 1); + + if(idx > Game.triggerCount) { + Game.triggers = realloc(Game.triggers, sizeof(*Game.triggers) * idx); + for(size_t j = Game.triggerCount; j < idx; j++) { + Game.triggers[j] = NULL; + } + Game.triggerCount = idx; + } + Game.triggers[idx - 1] = luaapi_triggerfunc; + } + return 0; +} +static int game_triggers_get(lua_State *L) { + lua_pushvalue(L, 2); + lua_rawget(L, 1); + return 1; +} + +static int gameconveyorsref; +static int game_conveyors_set(lua_State *L) { + size_t idx = lua_tointeger(L, 2); + if(idx >= 1 && idx <= MAX_CONVEYORS) { + if(Game.conveyorCount < idx) { + Game.conveyors = realloc(Game.conveyors, sizeof(*Game.conveyors) * idx); + for(size_t i = Game.conveyorCount; i < idx; i++) { + Game.conveyors[i] = NULL; + } + Game.conveyorCount = idx; + } + + struct Conveyor *c = Game.conveyors[idx - 1]; + if(!c) { + c = calloc(sizeof(*c), 1); + } + + lua_getfield(L, 3, "entity"); + c->entity = lua_isnil(L, -1) ? ENT_ID_INVALID : lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, 3, "active"); + c->active = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, 3, "type"); + c->type = lua_tointeger(L, -1); + lua_pop(L, 1); + + lua_getfield(L, 3, "speed"); + c->speed = lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_getfield(L, 3, "position"); + c->position = lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_getfield(L, 3, "points"); + c->pointCount = lua_rawlen(L, -1); + c->points = realloc(c->points, sizeof(*c->points) * c->pointCount); + for(size_t i = 0; i < c->pointCount; i++) { + lua_rawgeti(L, -1, i + 1); + lua_rawgeti(L, -1, 1); + lua_rawgeti(L, -2, 2); + lua_rawgeti(L, -3, 3); + c->points[i][0] = lua_tonumber(L, -3); + c->points[i][1] = lua_tonumber(L, -2); + c->points[i][2] = lua_tonumber(L, -1); + lua_pop(L, 4); + } + lua_pop(L, 1); + + lua_getfield(L, 3, "trigger"); + c->trigger = lua_isnil(L, -1) ? TRIGGER_INVALID : lua_tointeger(L, -1); + lua_pop(L, 1); + + Game.conveyors[idx - 1] = c; + } + return 0; +} +static int game_conveyors_get(lua_State *L) { + size_t idx = lua_tointeger(L, 2); + if(idx >= 1 && idx <= Game.conveyorCount && Game.conveyors[idx - 1]) { + size_t *z = lua_newuserdata(L, sizeof(*z)); + *z = idx; + luaL_setmetatable(L, "k3conveyor"); + } else { + lua_pushnil(L); + } + return 1; +} + +static int game_conveyor_set(lua_State *L) { + const char *k = lua_tostring(L, 2); + + size_t *idxptr = lua_touserdata(L, 1); + size_t idx = *idxptr; + + if(idx == 0 || idx > Game.conveyorCount || !Game.conveyors[idx - 1]) { + return 0; + } + + struct Conveyor *conv = Game.conveyors[idx - 1]; + + if(!strcmp(k, "entity")) { + conv->entity = lua_isnil(L, 3) ? ENT_ID_INVALID : lua_tointeger(L, 3); + } else if(!strcmp(k, "active")) { + conv->active = lua_tointeger(L, 3); + } else if(!strcmp(k, "type")) { + conv->type = lua_tointeger(L, 3); + } else if(!strcmp(k, "speed")) { + conv->speed = lua_tonumber(L, 3); + } else if(!strcmp(k, "position")) { + conv->position = lua_tonumber(L, 3); + } else if(!strcmp(k, "points")) { + // TODO + } + + return 0; +} + +static int game_conveyor_get(lua_State *L) { + const char *k = lua_tostring(L, 2); + + size_t *idxptr = lua_touserdata(L, 1); + size_t idx = *idxptr; + + if(idx == 0 || idx > Game.conveyorCount || !Game.conveyors[idx - 1]) { + return 0; + } + + struct Conveyor *conv = Game.conveyors[idx - 1]; + + if(!strcmp(k, "entity")) { + if(conv->entity == ENT_ID_INVALID) { + lua_pushnil(L); + } else { + lua_pushinteger(L, conv->entity); + } + } else if(!strcmp(k, "active")) { + lua_pushinteger(L, conv->active); + } else if(!strcmp(k, "type")) { + lua_pushinteger(L, conv->type); + } else if(!strcmp(k, "speed")) { + lua_pushnumber(L, conv->speed); + } else if(!strcmp(k, "position")) { + lua_pushnumber(L, conv->position); + } else if(!strcmp(k, "points")) { + lua_newtable(L); + for(size_t i = 0; i < conv->pointCount; i++) { + lua_newtable(L); + + lua_pushnumber(L, conv->points[i][0]); + lua_rawseti(L, -2, 1); + + lua_pushnumber(L, conv->points[i][1]); + lua_rawseti(L, -2, 2); + + lua_pushnumber(L, conv->points[i][2]); + lua_rawseti(L, -2, 3); + + lua_rawseti(L, -2, i + 1); + } + } else return 0; + + return 1; +} + +static int game_water(lua_State *L) { + void **mat = lua_touserdata(L, 4); + + struct k3Water **w = lua_newuserdata(L, sizeof(*w)); + *w = k3WaterCreate(lua_tonumber(L, 1), lua_tonumber(L, 2), lua_tointeger(L, 3), *mat); + + luaL_setmetatable(L, "k3water"); + + return 1; +} + +static int game_water_simulate(lua_State *L) { + void **w = lua_touserdata(L, 1); + k3WaterSimulate(*w, lua_tonumber(L, 2), lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tointeger(L, 5)); + return 0; +} + +static int game_water_update(lua_State *L) { + void **w = lua_touserdata(L, 1); + k3WaterUpdate(*w); + return 0; +} + +static int game_water_disturb(lua_State *L) { + void **w = lua_touserdata(L, 1); + k3WaterDisturb(*w, lua_tonumber(L, 2), lua_tonumber(L, 3), lua_tonumber(L, 4), lua_tonumber(L, 5)); + return 0; +} + +struct mixitem { + void *thing; +#define MIXITEM_SOURCE 0 +#define MIXITEM_SOUND 1 +#define MIXITEM_QUEUE 2 +#define MIXITEM_POWER 3 + int type; +}; + +static int dagame_mixsound(lua_State *L) { + struct mixitem *i = lua_touserdata(L, 1); + + assert(i->type == MIXITEM_SOURCE); + + struct mixitem *r = lua_newuserdata(L, sizeof(*r)); + r->type = MIXITEM_SOUND; + r->thing = k3MixSimple(i->thing); + + luaL_setmetatable(L, "k3mixwave"); + + return 1; +} + +static int game_mixplay(lua_State *L) { + struct mixitem *i = lua_touserdata(L, 1); + + assert(i->type != MIXITEM_SOURCE); + k3MixPlay(i->thing); + + lua_pushvalue(L, 1); + + return 1; +} + +static int dagame_mixstop(lua_State *L) { + struct mixitem *i = lua_touserdata(L, 1); + + assert(i->type != MIXITEM_SOURCE); + k3MixStop(i->thing); + + lua_pushvalue(L, 1); + + return 1; +} + +static int dagame_mixpower(lua_State *L) { + struct mixitem *i = lua_touserdata(L, 1); + + assert(i->type != MIXITEM_SOURCE); + + struct k3MixWave *wav = k3MixPowerMeasurement(i->thing); + + struct mixitem *r = lua_newuserdata(L, sizeof(*r)); + r->thing = wav; + r->type = MIXITEM_POWER; + + luaL_setmetatable(L, "k3mixwave"); + + return 1; +} + +static int game_mixwave_set(lua_State *L) { + struct mixitem *i = lua_touserdata(L, 1); + + assert(i->type != MIXITEM_SOURCE); + + if(!strcmp(lua_tostring(L, 2), "volume")) { + ((struct k3MixWave*) i->thing)->volume = lua_tonumber(L, 3); + } else if(!strcmp(lua_tostring(L, 2), "loop")) { + ((struct k3MixWave*) i->thing)->loop = lua_toboolean(L, 3); + } else if(i->type == MIXITEM_SOUND && !strcmp(lua_tostring(L, 2), "time")) { + k3MixSimpleSeek((struct k3MixWave*) i->thing, lua_tonumber(L, 3)); + } + + return 0; +} + +static int game_mixwave_get(lua_State *L) { + struct mixitem *i = lua_touserdata(L, 1); + + if(!strcmp(lua_tostring(L, 2), "volume")) { + lua_pushnumber(L, ((struct k3MixWave*) i->thing)->volume); + return 1; + } else if(!strcmp(lua_tostring(L, 2), "loop")) { + lua_pushboolean(L, ((struct k3MixWave*) i->thing)->loop); + return 1; + } else if(i->type == MIXITEM_POWER && !strcmp(lua_tostring(L, 2), "rms")) { + lua_pushnumber(L, k3MixPowerMeasurementGetRMS(((struct k3MixWave*) i->thing))); + return 1; + } + + return 0; +} + +static int dagame_mixwave_gc(lua_State *L) { + struct mixitem *i = lua_touserdata(L, 1); + + if(i->type != MIXITEM_SOURCE) { + struct k3MixWave *wav = i->thing; + wav->close(wav); + } + + return 0; +} + +static int game_mixqueue(lua_State *L) { + struct mixitem *i = lua_newuserdata(L, sizeof(*i)); + i->thing = k3MixQueue(); + i->type = MIXITEM_QUEUE; + + luaL_setmetatable(L, "k3mixqueue"); + + return 1; +} + +static int game_queue_add(lua_State *L) { + struct mixitem *i1 = lua_touserdata(L, 1); + struct mixitem *i2 = lua_touserdata(L, 2); + + if(i1->type != MIXITEM_QUEUE) { + lua_pushliteral(L, "Not queue."); + lua_error(L); + return 0; + } + + if(lua_gettop(L) > 2) { + lua_getfield(L, 3, "loop"); + ((struct k3MixWave*) i2->thing)->loop = lua_toboolean(L, -1); + lua_pop(L, 1); + } else { + ((struct k3MixWave*) i2->thing)->loop = 0; + } + + k3MixQueueAdd(i1->thing, i2->thing); +} + +static int game_queue_clear(lua_State *L) { + struct k3MixWave **ud = lua_touserdata(L, 1); + k3MixQueueClear(*ud); + + return 0; +} + +static int game_queue_gc(lua_State *L) { + struct k3MixWave **ud = lua_touserdata(L, 1); + (*ud)->close(*ud); + + return 0; +} + +static int game_ref(lua_State *L) { + enum ResManType type; + const char *ltype = lua_tolstring(L, 1, NULL); + + const char *meta = NULL; + + int sz; + + if(!strcmp(ltype, "stream")) { + type = RESMAN_STREAM; + meta = "k3mixwave"; + sz = sizeof(struct mixitem); + } else if(!strcmp(ltype, "mat")) { + type = RESMAN_MATERIAL; + meta = "k3mat"; + sz = sizeof(void*); + } else if(!strcmp(ltype, "mdl")) { + type = RESMAN_MODEL; + meta = "k3mdl"; + sz = sizeof(void*); + } else if(!strcmp(ltype, "tex")) { + type = RESMAN_TEXTURE; + meta = "k3tex"; + sz = sizeof(void*); + } else if(!strcmp(ltype, "physics")) { + type = RESMAN_PHYSICS; + meta = "k3physics"; + sz = sizeof(void*); + } else if(!strcmp(ltype, "font")) { + type = RESMAN_FONT; + meta = NULL; + sz = sizeof(void*); + } else return 0; + + const char *lname = lua_tostring(L, 2); + + void **ref = lua_newuserdata(L, sz); + + *ref = resman_ref(type, lname); + + if(type == RESMAN_STREAM) { + ((struct mixitem*) ref)->type = MIXITEM_SOURCE; + } + + if(meta) luaL_setmetatable(L, meta); + + return 1; +} + +static int game_batch(lua_State *L) { + void **r = lua_touserdata(L, 1); + + struct k3Mdl *mdl; + if(luaL_testudata(L, 1, "k3water")) { + mdl = ((struct k3Water*) *r)->mdl; + } else if(luaL_testudata(L, 1, "k3mdl")) { + mdl = *r; + } else return 0; + + lua_rawgeti(L, 2, 1); + lua_rawgeti(L, 2, 2); + lua_rawgeti(L, 2, 3); + + mat4 m = GLM_MAT4_IDENTITY_INIT; + glm_translate(m, (vec3) {lua_tonumber(L, -3), lua_tonumber(L, -2), lua_tonumber(L, -1)}); + + lua_pop(L, 3); + + if(lua_gettop(L) == 3) { + mat4 anchor; + for(int i = 0; i < 16; i++) { + lua_rawgeti(L, 3, i + 1); + ((float*) anchor)[i] = lua_tonumber(L, -1); + } + lua_pop(L, 16); + + glm_mat4_mul(anchor, m, m); + } + + k3Batch(mdl, m, NULL); + + return 0; +} + +static int game_get_component(lua_State *L) { + if(!lua_isinteger(L, 1)) { + return 0; + } + + size_t idx = lua_tointeger(L, 1); + const char *type = lua_tostring(L, 2); + + if(!strcmp(type, "physics")) { + struct CPhysics *c = game_getcomponent(idx, physics); + + if(c) { + struct CPhysics **lc = lua_newuserdata(L, sizeof(*lc)); + *lc = c; + luaL_setmetatable(L, "k3cphysics"); + } else { + lua_pushnil(L); + } + + return 1; + } else if(!strcmp(type, "render")) { + struct CRender *c = game_getcomponent(idx, render); + + if(c) { + struct CRender **lc = lua_newuserdata(L, sizeof(*lc)); + *lc = c; + luaL_setmetatable(L, "k3crender"); + } else { + lua_pushnil(L); + } + + return 1; + } else if(!strcmp(type, "boned")) { + struct CBoned *c = game_getcomponent(idx, boned); + + if(c) { + struct CBoned **lc = lua_newuserdata(L, sizeof(*lc)); + *lc = c; + luaL_setmetatable(L, "k3cboned"); + } else { + lua_pushnil(L); + } + + return 1; + } + + return 0; +} + +static int game_submissive_assign(lua_State *L) { + ENetPeer **ud = lua_touserdata(L, 1); + + net_server_assign(*ud, lua_tointeger(L, 2)); + + return 0; +} + +static int game_submissive_load(lua_State *L) { + ENetPeer **ud = lua_touserdata(L, 1); + + net_server_force_load(*ud, lua_tostring(L, 2)); + + return 0; +} + +static int game_submissive_send(lua_State *L) { + ENetPeer **ud = lua_touserdata(L, 1); + + struct bstr b; + bstr(&b, 64); + + lua_pushvalue(L, 2); + if(!serialize(&b)) { + lua_pushliteral(L, "Object not serializable."); + lua_error(L); + return 0; + } + lua_pop(L, 1); + + net_server_send_msg(*ud, &b); + + free(b.data); + + return 0; +} + +static int game_cphysics_get(lua_State *L) { + struct CPhysics *c = *(struct CPhysics**) lua_touserdata(L, 1); + + const char *k = lua_tostring(L, 2); + + if(!strcmp(k, "trigger")) { + lua_pushinteger(L, c->trigger); + return 1; + } else if(!strcmp(k, "type")) { + lua_pushinteger(L, c->type); + return 1; + } else if(!strcmp(k, "dynamics")) { + lua_pushinteger(L, c->dynamics); + return 1; + } else if(!strcmp(k, "pos")) { + + if(c->geom) { + lua_newtable(L); + + const float *p = dGeomGetPosition(c->geom); + lua_pushnumber(L, p[0]); + lua_pushnumber(L, p[1]); + lua_pushnumber(L, p[2]); + + lua_rawseti(L, -4, 3); + lua_rawseti(L, -3, 2); + lua_rawseti(L, -2, 1); + } else { + lua_pushnil(L); + } + + return 1; + } else if(!strcmp(k, "vel")) { + lua_newtable(L); + + dBodyID bid = dGeomGetBody(c->geom); + if(bid) { + const float *v = dBodyGetLinearVel(bid); + + lua_pushnumber(L, v[0]); + lua_pushnumber(L, v[1]); + lua_pushnumber(L, v[2]); + } else { + lua_pushnumber(L, 0); + lua_pushnumber(L, 0); + lua_pushnumber(L, 0); + } + + lua_rawseti(L, -4, 3); + lua_rawseti(L, -3, 2); + lua_rawseti(L, -2, 1); + + return 1; + } else if(!strcmp(k, "body")) { + if(c->geom) { + dGeomID *g = lua_newuserdata(L, sizeof(*g)); + *g = c->geom; + luaL_setmetatable(L, "k3body"); + } else { + lua_pushnil(L); + } + return 1; + } else if(!strcmp(k, "speed")) { + lua_pushnumber(L, c->speed); + return 1; + } else if(!strcmp(k, "add_force")) { + //lua_pushcfunction(L, ); + return 1; + } + + return 0; +} + +static int game_cphysics_set(lua_State *L) { + struct CPhysics *c = *(struct CPhysics**) lua_touserdata(L, 1); + + const char *k = lua_tostring(L, 2); + + if(!strcmp(k, "dynamics")) { + // Only allow ghost changes, not static/kinematic + if((c->dynamics ^ lua_tointeger(L, 3)) & CPHYSICS_GHOST) { + c->dynamics = (c->dynamics & ~CPHYSICS_GHOST) | (lua_tointeger(L, 3) & CPHYSICS_GHOST); + } + } else if(!strcmp(k, "pos")) { + lua_rawgeti(L, 3, 1); + lua_rawgeti(L, 3, 2); + lua_rawgeti(L, 3, 3); + + dGeomSetPosition(c->geom, lua_tonumber(L, -3), lua_tonumber(L, -2), lua_tonumber(L, -1)); + + lua_pop(L, 3); + } else if(!strcmp(k, "rot")) { + lua_rawgeti(L, 3, 1); + lua_rawgeti(L, 3, 2); + lua_rawgeti(L, 3, 3); + lua_rawgeti(L, 3, 4); + + dGeomSetQuaternion(c->geom, (dQuaternion) {lua_tonumber(L, -1), lua_tonumber(L, -4), lua_tonumber(L, -3), lua_tonumber(L, -2)}); + + lua_pop(L, 4); + } else if(!strcmp(k, "vel")) { + dBodyID bid = dGeomGetBody(c->geom); + + if(bid) { + lua_rawgeti(L, 3, 1); + lua_rawgeti(L, 3, 2); + lua_rawgeti(L, 3, 3); + + dBodySetLinearVel(bid, lua_tonumber(L, -3), lua_tonumber(L, -2), lua_tonumber(L, -1)); + + lua_pop(L, 3); + } + } else if(!strcmp(k, "speed")) { + c->speed = lua_tonumber(L, 3); + } + + return 0; +} + +static int game_crender_get(lua_State *L) { + struct CRender *c = *(struct CRender**) lua_touserdata(L, 1); + + const char *k = lua_tostring(L, 2); + + if(!strcmp(k, "mdl")) { + lua_pushlstring(L, c->mdl, strnlen(c->mdl, MODELNAME_LENGTH)); + return 1; + } else if(!strcmp(k, "mdlcache")) { + struct k3Mdl **cache = lua_newuserdata(L, sizeof(*cache)); + *cache = c->cache; + luaL_setmetatable(L, "k3mdl"); + return 1; + } else if(!strcmp(k, "bones")) { + lua_newtable(L); + return 1; + } + + return 0; +} + +static int game_cboned_get(lua_State *L) { + struct CBoned *c = *(struct CBoned**) lua_touserdata(L, 1); + + const char *k = lua_tostring(L, 2); + + if(!strcmp(k, "bones")) { + lua_newtable(L); + + for(size_t i = 0; i < c->size; i++) { + lua_newtable(L); + lua_newtable(L); + lua_pushnumber(L, c->bones[i].translation[0]); + lua_pushnumber(L, c->bones[i].translation[1]); + lua_pushnumber(L, c->bones[i].translation[2]); + lua_pushnumber(L, c->bones[i].translation[3]); + lua_rawseti(L, -5, 4); + lua_rawseti(L, -4, 3); + lua_rawseti(L, -3, 2); + lua_rawseti(L, -2, 1); + lua_rawseti(L, -2, 1); + + lua_newtable(L); + lua_pushnumber(L, c->bones[i].rotation[0]); + lua_pushnumber(L, c->bones[i].rotation[1]); + lua_pushnumber(L, c->bones[i].rotation[2]); + lua_pushnumber(L, c->bones[i].rotation[3]); + lua_rawseti(L, -5, 4); + lua_rawseti(L, -4, 3); + lua_rawseti(L, -3, 2); + lua_rawseti(L, -2, 1); + lua_rawseti(L, -2, 2); + lua_rawseti(L, -2, i + 1); + } + + return 1; + } else if(!strcmp(k, "anim")) { + struct CBoned **c2 = lua_newuserdata(L, sizeof(*c2)); + *c2 = c; + luaL_setmetatable(L, "k3cbonedanim"); + + return 1; + } + + return 0; +} + +static int game_cboned_set(lua_State *L) { + struct CBoned *c = *(struct CBoned**) lua_touserdata(L, 1); + + const char *k = lua_tostring(L, 2); + + if(!strcmp(k, "bones")) { + size_t newlen = luaL_len(L, 3); + + if(newlen != c->size) { + c->bones = realloc(c->bones, sizeof(*c->bones) * newlen); + } + + for(size_t i = 0; i < newlen; i++) { + lua_rawgeti(L, 3, i + 1); + + lua_rawgeti(L, -1, 1); + lua_rawgeti(L, -1, 1); + lua_rawgeti(L, -2, 2); + lua_rawgeti(L, -3, 3); + lua_rawgeti(L, -4, 4); + c->bones[i].translation[0] = lua_tonumber(L, -4); + c->bones[i].translation[1] = lua_tonumber(L, -3); + c->bones[i].translation[2] = lua_tonumber(L, -2); + c->bones[i].translation[3] = lua_tonumber(L, -1); + lua_pop(L, 5); + + lua_rawgeti(L, -1, 2); + lua_rawgeti(L, -1, 1); + lua_rawgeti(L, -2, 2); + lua_rawgeti(L, -3, 3); + lua_rawgeti(L, -4, 4); + c->bones[i].rotation[0] = lua_tonumber(L, -4); + c->bones[i].rotation[1] = lua_tonumber(L, -3); + c->bones[i].rotation[2] = lua_tonumber(L, -2); + c->bones[i].rotation[3] = lua_tonumber(L, -1); + lua_pop(L, 5); + + lua_pop(L, 1); + } + } + + return 0; +} + +static int game_cbonedanim_set(lua_State *L) { + struct CBoned *c = *(struct CBoned**) lua_touserdata(L, 1); + + const char *k = lua_tostring(L, 2); + + if(!strcmp(k, "id")) { + c->anim.id = lua_tointeger(L, 3); + c->anim.cache.base = NULL; + } else if(!strcmp(k, "standard")) { + c->anim.standard = lua_toboolean(L, 3); + } + + return 0; +} + +int LuaapiCamFocus; +vec3 LuaapiCamFocusPos; +vec3 LuaapiCamFocusDir; +int LuaapiFirstPerson; + +static int game_camfocus(lua_State *L) { + if(lua_gettop(L) < 3 || lua_isnil(L, 2) || lua_isnil(L, 3)) { + LuaapiCamFocus = 0; + } else if(lua_gettop(L) == 3) { + LuaapiCamFocus = 1; + + lua_rawgeti(L, 2, 1); + lua_rawgeti(L, 2, 2); + lua_rawgeti(L, 2, 3); + + LuaapiCamFocusPos[0] = lua_tonumber(L, -3); + LuaapiCamFocusPos[1] = lua_tonumber(L, -2); + LuaapiCamFocusPos[2] = lua_tonumber(L, -1); + + lua_rawgeti(L, 3, 1); + lua_rawgeti(L, 3, 2); + lua_rawgeti(L, 3, 3); + + LuaapiCamFocusDir[0] = lua_tonumber(L, -3); + LuaapiCamFocusDir[1] = lua_tonumber(L, -2); + LuaapiCamFocusDir[2] = lua_tonumber(L, -1); + + lua_pop(L, 6); + } + return 0; +} + +#define MENUITEM_SCREEN 0 +#define MENUITEM_LABEL 1 +#define MENUITEM_TEXTBUTTON 2 +#define MENUITEM_TEXTINPUT 3 +struct menuitem { + int type; + struct k3MObj *ptr; +}; + +mat4 LuaapiCamMatrix; +static int game_get(lua_State *L) { + const char *i = lua_tostring(L, 2); + if(!strcmp(i, "mp")) { + lua_pushboolean(L, Game.isMultiplayer); + } else if(!strcmp(i, "authority")) { + lua_pushboolean(L, Game.isAuthority); + } else if(!strcmp(i, "spectated")) { + lua_pushinteger(L, Game.spectated); + } else if(!strcmp(i, "fov")) { + lua_pushnumber(L, LuaapiFov); + } else if(!strcmp(i, "rate")) { + lua_pushinteger(L, GAME_TPS); + } else if(!strcmp(i, "camera")) { + lua_newtable(L); + for(int i = 0; i < 16; i++) { + lua_pushnumber(L, ((float*) LuaapiCamMatrix)[i]); + lua_rawseti(L, -2, i + 1); + } + } else if(!strcmp(i, "menu")) { + if(UiActive) { + struct menuitem *item = lua_newuserdata(L, sizeof(*item)); + item->type = MENUITEM_SCREEN; + item->ptr = UiActive; + } else { + lua_pushnil(L); + } + } else { + lua_pushvalue(L, 2); + lua_rawget(L, 1); + } + return 1; +} + +static int game_set(lua_State *L) { + const char *i = lua_tostring(L, 2); + if(!strcmp(i, "spectated")) { + Game.spectated = lua_isnil(L, 3) ? ENT_ID_INVALID : lua_tointeger(L, 3); + } else if(!strcmp(i, "fov")) { + LuaapiFov = lua_tonumber(L, 3); + } else if(!strcmp(i, "menu")) { + struct menuitem *item = lua_touserdata(L, 3); + UiActive = item ? item->ptr : NULL; + set_ui_mode(!!UiActive); + } else { + lua_pushvalue(L, 2); + lua_pushvalue(L, 3); + lua_rawset(L, 1); + } + return 0; +} + +static int game_k3mdl_addmesh(lua_State *L) { + struct k3Mdl *mdl = *(struct k3Mdl**) lua_touserdata(L, 1); + + lua_getfield(L, 2, "material"); + struct k3Mat mat; + memset(&mat, 0, sizeof(mat)); + luaapi_fillmaterial_direct(&mat); + + lua_getfield(L, 2, "start"); + size_t start = lua_tointeger(L, -1); + + lua_getfield(L, 2, "count"); + size_t count = lua_tointeger(L, -1); + + lua_pop(L, 3); + + k3MdlAddMesh(mdl, &mat, start, count); +} + +static int game_k3mdl_get(lua_State *L) { + struct k3Mdl *mdl = *(struct k3Mdl**) lua_touserdata(L, 1); + + size_t count; + struct k3Mesh *meshes = k3MdlGetMeshes(mdl, &count); + + if(lua_type(L, 2) == LUA_TNUMBER) { + lua_Integer i = lua_tointeger(L, 2); + if(i >= 1 && i <= count) { + struct k3Mat **m = lua_newuserdata(L, sizeof(*m)); + *m = &meshes[i - 1].mat; + luaL_setmetatable(L, "k3mat"); + } else { + lua_pushnil(L); + } + } else if(!strcmp(lua_tostring(L, 2), "addmesh")) { + lua_pushcfunction(L, game_k3mdl_addmesh); + } + + return 1; +} + +static int game_k3mat_get(lua_State *L) { + struct k3Mat *mat = *(struct k3Mat**) lua_touserdata(L, 1); + const char *k = lua_tostring(L, 2); + if(!strcmp(k, "uniforms")) { + if(mat->passes[0].glsl.hp) { + struct k3Mat **again = lua_newuserdata(L, sizeof(*again)); + *again = mat; + luaL_setmetatable(L, "k3matuniforms"); + } else { + lua_pushnil(L); + } + } else { + lua_pushnil(L); + } + return 1; +} + +static int game_k3matuniforms_set(lua_State *L) { + struct k3Mat *mat = *(struct k3Mat**) lua_touserdata(L, 1); + + const char *key = lua_tostring(L, 2); + + for(int i = 0; i < mat->passes[0].glsl.uCount; i++) { + if(!strncmp(key, mat->passes[0].glsl.u[i].name, sizeof(mat->passes[0].glsl.u[i].name))) { + if(mat->passes[0].glsl.u[i].type == k3_MAT_UNIFORM_I1) { + mat->passes[0].glsl.u[i].i1 = lua_tointeger(L, 3); + } else if(mat->passes[0].glsl.u[i].type == k3_MAT_UNIFORM_F1) { + mat->passes[0].glsl.u[i].f1 = lua_tonumber(L, 3); + } + } + } + + return 0; +} + +static int game_k3matuniforms_get(lua_State *L) { + struct k3Mat *mat = *(struct k3Mat**) lua_touserdata(L, 1); + + const char *key = lua_tostring(L, 2); + + for(int i = 0; i < mat->passes[0].glsl.uCount; i++) { + if(!strncmp(key, mat->passes[0].glsl.u[i].name, sizeof(mat->passes[0].glsl.u[i].name))) { + if(mat->passes[0].glsl.u[i].type == k3_MAT_UNIFORM_I1) { + lua_pushinteger(L, mat->passes[0].glsl.u[i].i1); + return 1; + } else if(mat->passes[0].glsl.u[i].type == k3_MAT_UNIFORM_F1) { + lua_pushnumber(L, mat->passes[0].glsl.u[i].f1); + return 1; + } + } + } + + return 0; +} + +static size_t moduleCount; +static struct Module { + //uint64_t hash; + char *name; + int ref; +} *modules; +static int luaapi_require(lua_State *L) { + const char *name = lua_tostring(L, 1); + + for(size_t i = 0; i < moduleCount; i++) { + if(!strcmp(modules[i].name, name)) { + lua_rawgeti(L, LUA_REGISTRYINDEX, modules[i].ref); + return 1; + } + } + + char buf[128]; + snprintf(buf, sizeof(buf), "%s.lua", name); + buf[127] = 0; + for(size_t i = 0; buf[i] && i < strlen(buf) - 4; i++) { + if(buf[i] == '.') buf[i] = '/'; + } + + struct ResManBin *bin = resman_ref(RESMAN_BIN, buf); + + if(luaL_dostring(L, bin->data)) { + puts(lua_tolstring(L, -1, NULL)); + lua_pop(L, 1); + } + + resman_unref(RESMAN_BIN, buf); + + lua_pushvalue(L, -1); + modules = realloc(modules, sizeof(*modules) * (moduleCount + 1)); + modules[moduleCount++] = (struct Module) { + .name = strdup(name), + .ref = luaL_ref(L, LUA_REGISTRYINDEX), + }; + + return 1; +} + +static int game_load(lua_State *L) { + luaapi_load(lua_tostring(L, 1)); + return 0; +} + +static int dagame_cleanup(lua_State *L) { + luaapi_cleanup(); + return 0; +} + +static int dagame_joint(lua_State *L) { + lua_getfield(L, 1, "type"); + const char *type = lua_tostring(L, -1); + lua_pop(L, 1); + + if(!strcmp(type, "ballsocket")) { + lua_geti(L, 1, 1); + lua_geti(L, 1, 2); + dGeomID *gid1 = lua_touserdata(L, -2); + dGeomID *gid2 = lua_touserdata(L, -1); + lua_pop(L, 2); + + dBodyID bid1 = dGeomGetBody(*gid1); + dBodyID bid2 = dGeomGetBody(*gid2); + + if(bid1 && bid2) { + dJointID jid = dJointCreateBall(Game.phys, 0); + lua_getfield(L, 1, "anchor"); + lua_rawgeti(L, -1, 1); + lua_rawgeti(L, -2, 2); + lua_rawgeti(L, -3, 3); + dJointSetBallAnchor(jid, lua_tonumber(L, -3), lua_tonumber(L, -2), lua_tonumber(L, -1)); + lua_pop(L, 4); + dJointAttach(jid, bid1, bid2); + } + } else if(!strcmp(type, "slider")) { + lua_geti(L, 1, 1); + lua_geti(L, 1, 2); + dGeomID *gid1 = lua_touserdata(L, -2); + dGeomID *gid2 = lua_touserdata(L, -1); + lua_pop(L, 2); + + dBodyID bid1 = dGeomGetBody(*gid1); + dBodyID bid2 = dGeomGetBody(*gid2); + + if(bid1 && bid2) { + dJointID jid = dJointCreateSlider(Game.phys, 0); + dJointAttach(jid, bid1, bid2); + + lua_getfield(L, 1, "axis"); + lua_rawgeti(L, -1, 1); + lua_rawgeti(L, -2, 2); + lua_rawgeti(L, -3, 3); + dJointSetSliderAxis(jid, lua_tonumber(L, -3), lua_tonumber(L, -2), lua_tonumber(L, -1)); + lua_pop(L, 4); + } + } + + return 0; +} + +static int dagame_setphys(lua_State *L) { + game_setphys(*(struct TrimeshData**) lua_touserdata(L, 1)); + + return 0; +} + +static int dagame_controls_get(lua_State *L) { + const char *k = lua_tostring(L, 2); + + int btn = k4_control_get_by_name(k); + + if(btn == -1) { + lua_pushnil(L); + } else { + lua_pushinteger(L, btn); + } + + return 1; +} + +static int dagame_controls_set(lua_State *L) { + const char *k = lua_tostring(L, 2); + + int btn; + + // lua_isstring returns true for numbers because yes + if(lua_type(L, 3) == LUA_TSTRING) { + btn = lua_tostring(L, 3)[0]; + } else { + btn = lua_tointeger(L, 3); + } + + k4_control_set(k, btn); + + return 0; +} + +static int dagame_mdl(lua_State *L) { + vec3 *positions = NULL; + int8_t *normals = NULL; + uint16_t *indices = NULL; + vec2 *uvs = NULL; + + size_t vertexCount = 0; + size_t indexCount = 0; + + lua_getfield(L, 1, "positions"); + lua_len(L, -1); + vertexCount = lua_tointeger(L, -1) / 3; + lua_pop(L, 1); + + positions = malloc(sizeof(*positions) * vertexCount); + + for(size_t i = 0; i < vertexCount; i++) { + lua_geti(L, -1, i * 3 + 1); + lua_geti(L, -2, i * 3 + 2); + lua_geti(L, -3, i * 3 + 3); + positions[i][0] = lua_tonumber(L, -3); + positions[i][1] = lua_tonumber(L, -2); + positions[i][2] = lua_tonumber(L, -1); + lua_pop(L, 3); + } + lua_pop(L, 1); + + lua_getfield(L, 1, "indices"); + lua_len(L, -1); + indexCount = lua_tointeger(L, -1); + lua_pop(L, 1); + + indices = malloc(sizeof(*indices) * indexCount); + + for(size_t i = 0; i < indexCount; i++) { + lua_geti(L, -1, i + 1); + indices[i] = lua_tointeger(L, -1); + if(indices[i] >= vertexCount) { + k3Log(k3_ERR, "Index goes over vertex count!"); + } + lua_pop(L, 1); + } + lua_pop(L, 1); + + lua_getfield(L, 1, "normals"); + lua_len(L, -1); + size_t c = lua_tointeger(L, -1) / 3; + lua_pop(L, 1); + + if(c != vertexCount) { + // TODO: free + return 0; + } + + normals = malloc(sizeof(*normals) * 3 * vertexCount); + + for(size_t i = 0; i < vertexCount; i++) { + lua_geti(L, -1, i * 3 + 1); + lua_geti(L, -2, i * 3 + 2); + lua_geti(L, -3, i * 3 + 3); + normals[i * 3 + 0] = lua_tonumber(L, -3) * 127; + normals[i * 3 + 1] = lua_tonumber(L, -2) * 127; + normals[i * 3 + 2] = lua_tonumber(L, -1) * 127; + lua_pop(L, 3); + } + lua_pop(L, 1); + + lua_getfield(L, 1, "uvs"); + lua_len(L, -1); + c = lua_tointeger(L, -1) / 2; + lua_pop(L, 1); + + if(c != vertexCount) { + // TODO: free + return 0; + } + + uvs = malloc(sizeof(*uvs) * vertexCount); + + for(size_t i = 0; i < vertexCount; i++) { + lua_geti(L, -1, i * 2 + 1); + lua_geti(L, -2, i * 2 + 2); + uvs[i][0] = lua_tonumber(L, -2); + uvs[i][1] = lua_tonumber(L, -1); + lua_pop(L, 2); + } + lua_pop(L, 1); + + struct k3Mdl *mdl = k3MdlCreate(vertexCount, indexCount, 0, positions, normals, uvs, NULL, NULL, NULL, indices, NULL, NULL); + + struct k3Mdl **ud = lua_newuserdata(L, sizeof(*ud)); + *ud = mdl; + luaL_setmetatable(L, "k3mdl"); + + return 1; +} + +static int dagame_trimesh(lua_State *L) { + lua_getfield(L, 1, "indices"); + lua_len(L, -1); + size_t indexCount = lua_tointeger(L, -1); + lua_pop(L, 1); + + int *indices = malloc(sizeof(*indices) * indexCount); + + for(size_t i = 0; i < indexCount; i++) { + lua_geti(L, -1, i + 1); + indices[i] = lua_tointeger(L, -1); + lua_pop(L, 1); + } + lua_pop(L, 1); + + lua_getfield(L, 1, "positions"); + lua_len(L, -1); + size_t vertexCount = lua_tointeger(L, -1) / 3; + lua_pop(L, 1); + + vec3 *positions = malloc(sizeof(*positions) * vertexCount); + + for(size_t i = 0; i < vertexCount; i++) { + lua_geti(L, -1, i * 3 + 1); + lua_geti(L, -2, i * 3 + 2); + lua_geti(L, -3, i * 3 + 3); + positions[i][0] = lua_tonumber(L, -3); + positions[i][1] = lua_tonumber(L, -2); + positions[i][2] = lua_tonumber(L, -1); + lua_pop(L, 3); + } + lua_pop(L, 1); + + dTriMeshDataID trid = dGeomTriMeshDataCreate(); + dGeomTriMeshDataBuildSingle(trid, positions, sizeof(vec3), vertexCount, indices, indexCount, 3 * sizeof(int)); + + struct TrimeshData *ret = malloc(sizeof(*ret)); + ret->vdata = positions; + ret->idata = indices; + ret->trid = trid; + + struct TrimeshData **ud = lua_newuserdata(L, sizeof(*ud)); + *ud = ret; + + luaL_setmetatable(L, "k3physics"); + + return 1; +} + +static int dagame_firstperson(lua_State *L) { + LuaapiFirstPerson = lua_toboolean(L, 1); + return 0; +} + +static int dagame_ray(lua_State *L) { + struct LocalRay *lr = lua_newuserdata(L, sizeof(*lr)); + luaL_setmetatable(L, "k4ray"); + + struct CPhysics *cp = game_getcomponent(Game.spectated, physics); + struct CPlayerCtrl *cc = game_getcomponent(Game.spectated, playerctrl); + + memcpy(lr->pos, dGeomGetPosition(cp->geom), sizeof(vec3)); + + lr->dir[0] = 0; + lr->dir[1] = 0; + lr->dir[2] = -1; + + glm_vec3_rotate(lr->dir, cc->pitch, (vec3) {1, 0, 0}); + glm_vec3_rotate(lr->dir, cc->yaw, (vec3) {0, 1, 0}); + + lr->ignore = Game.spectated; + + lr->hit = ENT_ID_INVALID; + lr->out[0] = NAN; + lr->out[1] = NAN; + lr->out[2] = NAN; + + lr->maxlen = lua_type(L, 1) == LUA_TNUMBER ? lua_tonumber(L, 1) : 3; + + game_raycast(lr, 1); + + return 1; +} + +static int dagame_ray_get(lua_State *L) { + struct LocalRay *lr = luaL_checkudata(L, 1, "k4ray"); + + const char *key = lua_tostring(L, 2); + + if(!strcmp(key, "pos")) { + lua_newtable(L); + + lua_pushnumber(L, lr->out[0]); + lua_rawseti(L, -2, 1); + + lua_pushnumber(L, lr->out[1]); + lua_rawseti(L, -2, 2); + + lua_pushnumber(L, lr->out[2]); + lua_rawseti(L, -2, 3); + + return 1; + } else if(!strcmp(key, "dir")) { + lua_newtable(L); + + lua_pushnumber(L, lr->dir[0]); + lua_rawseti(L, -2, 1); + + lua_pushnumber(L, lr->dir[1]); + lua_rawseti(L, -2, 2); + + lua_pushnumber(L, lr->dir[2]); + lua_rawseti(L, -2, 3); + + return 1; + } else if(!strcmp(key, "hit")) { + if(lr->hit == ENT_ID_INVALID) { + lua_pushnil(L); + } else { + lua_pushinteger(L, lr->hit); + } + + return 1; + } else if(!strcmp(key, "ready")) { + lua_pushboolean(L, !isnanf(lr->out[0])); + + return 1; + } + + return 0; +} + +#include"k3font.h" +static int dagame_draw(lua_State *L) { + lua_getfield(L, 1, "fill"); + + if(lua_toboolean(L, -1)) { + lua_pop(L, 1); + + lua_getfield(L, 1, "tex"); + + lua_getfield(L, 1, "sx"); + lua_getfield(L, 1, "sy"); + + lua_getfield(L, 1, "sw"); + lua_getfield(L, 1, "sh"); + + lua_getfield(L, 1, "x"); + lua_getfield(L, 1, "y"); + + lua_getfield(L, 1, "w"); + lua_getfield(L, 1, "h"); + + lua_getfield(L, 1, "r"); + lua_getfield(L, 1, "g"); + lua_getfield(L, 1, "b"); + lua_getfield(L, 1, "a"); + + void *texptr = lua_touserdata(L, -13); + struct k3Tex *tex = texptr ? *(void**)texptr : NULL; + + float sx = lua_type(L, -12) == LUA_TNUMBER ? lua_tonumber(L, -12) : 0; + float sy = lua_type(L, -11) == LUA_TNUMBER ? lua_tonumber(L, -11) : 0; + + float sw = lua_type(L, -10) == LUA_TNUMBER ? lua_tonumber(L, -10) : 1; + float sh = lua_type(L, -9) == LUA_TNUMBER ? lua_tonumber(L, -9) : 1; + + float x = lua_tonumber(L, -8); + float y = lua_tonumber(L, -7); + + float w = lua_tonumber(L, -6); + float h = lua_tonumber(L, -5); + + float r = lua_type(L, -4) == LUA_TNUMBER ? lua_tonumber(L, -4) : 1; + float g = lua_type(L, -3) == LUA_TNUMBER ? lua_tonumber(L, -3) : 1; + float b = lua_type(L, -2) == LUA_TNUMBER ? lua_tonumber(L, -2) : 1; + float a = lua_type(L, -1) == LUA_TNUMBER ? lua_tonumber(L, -1) : 1; + + k3BatchAdd(tex, (struct k3RectF) {.x = sx, .y = sy, .w = sw, .h = sh}, (struct k3RectF) {.x = x, .y = y, .w = w, .h = h}, 0, (vec4) {r, g, b, a}); + + lua_pop(L, 13); + } else { + lua_pop(L, 1); + + lua_getfield(L, 1, "align"); + + lua_getfield(L, 1, "r"); + lua_getfield(L, 1, "g"); + lua_getfield(L, 1, "b"); + lua_getfield(L, 1, "a"); + + lua_getfield(L, 1, "sz"); + + lua_getfield(L, 1, "text"); + + lua_getfield(L, 1, "x"); + lua_getfield(L, 1, "y"); + + lua_getfield(L, 1, "font"); + struct k3Font *font = *(void**) lua_touserdata(L, 1); + + struct k3RectF rect; + k3FontSz(font, lua_tonumber(L, -4), lua_tostring(L, -3), &rect); + + if(!strcmp(lua_tostring(L, -9), "bottommiddle")) { + rect.x -= rect.w / 2; + } else if(!strcmp(lua_tostring(L, -9), "bottomright")) { + rect.x -= rect.w; + } else if(!strcmp(lua_tostring(L, -9), "middlemiddle")) { + rect.x -= rect.w / 2; + rect.y -= rect.h / 2; + } + + k3FontDraw(font, lua_tonumber(L, -2) + rect.x, lua_tonumber(L, -1) + rect.y, lua_tonumber(L, -4), lua_tostring(L, -3), (vec4) {lua_tonumber(L, -8), lua_tonumber(L, -7), lua_tonumber(L, -6), lua_tonumber(L, -5)}); + + lua_pop(L, 9); + } + + return 0; +} + +struct k3Tex *LuaapiSkybox; +vec4 LuaapiSkyboxRotation; +bool LuaapiSkyboxRotationFunky; +static int dagame_skybox(lua_State *L) { + LuaapiSkybox = *(struct k3Tex**) lua_touserdata(L, 1); + + if(lua_gettop(L) >= 2) { + lua_geti(L, 2, 1); + lua_geti(L, 2, 2); + lua_geti(L, 2, 3); + lua_geti(L, 2, 4); + + LuaapiSkyboxRotation[0] = lua_tonumber(L, -4); + LuaapiSkyboxRotation[1] = lua_tonumber(L, -3); + LuaapiSkyboxRotation[2] = lua_tonumber(L, -2); + LuaapiSkyboxRotation[3] = lua_tonumber(L, -1); + + lua_pop(L, 4); + + if(lua_gettop(L) == 3) { + LuaapiSkyboxRotationFunky = lua_toboolean(L, 3); + } + } else { + glm_vec4_zero(LuaapiSkyboxRotation); + LuaapiSkyboxRotationFunky = false; + } +} + +static int dagame_send(lua_State *L) { + struct bstr b; + bstr(&b, 64); + + lua_pushvalue(L, 1); + if(!serialize(&b)) { + lua_pushliteral(L, "Object not serializable."); + lua_error(L); + return 0; + } + lua_pop(L, 1); + + if(Game.isAuthority) { + net_server_broadcast_msg(&b); + } else { + net_client_send_msg(&b); + } + + free(b.data); + + return 0; +} + +static int dagame_ui_screen(lua_State *L) { + struct menuitem *item = lua_newuserdata(L, sizeof(*item)); + item->type = MENUITEM_SCREEN; + item->ptr = (void*) k3MScreen(); + luaL_setmetatable(L, "k3menuitem"); + return 1; +} + +static int dagame_ui_label(lua_State *L) { + struct menuitem *item = lua_newuserdata(L, sizeof(*item)); + item->type = MENUITEM_LABEL; + item->ptr = (void*) k3MLabel(*(void**) lua_touserdata(L, 1), lua_tonumber(L, 2), strdup(lua_tostring(L, 3))); + luaL_setmetatable(L, "k3menuitem"); + return 1; +} + +static int dagame_ui_textbutton(lua_State *L) { + struct menuitem *item = lua_newuserdata(L, sizeof(*item)); + item->type = MENUITEM_TEXTBUTTON; + item->ptr = (void*) k3MTextButton(*(void**) lua_touserdata(L, 1), lua_tonumber(L, 2), strdup(lua_tostring(L, 3))); + luaL_setmetatable(L, "k3menuitem"); + return 1; +} + +static int dagame_ui_textinput(lua_State *L) { + struct menuitem *item = lua_newuserdata(L, sizeof(*item)); + item->type = MENUITEM_TEXTINPUT; + item->ptr = (void*) k3MTextInput(*(void**) lua_touserdata(L, 1), lua_tonumber(L, 2), strdup(lua_tostring(L, 3)), strdup(lua_tostring(L, 4))); + luaL_setmetatable(L, "k3menuitem"); + return 1; +} + +static int dagame_k3menuitem_set_bounds(lua_State *L) { + struct menuitem *item = lua_touserdata(L, 1); + + item->ptr->x = lua_tonumber(L, 2); + item->ptr->y = lua_tonumber(L, 3); + item->ptr->w = lua_tonumber(L, 4); + item->ptr->h = lua_tonumber(L, 5); + + lua_pushvalue(L, 1); + + return 1; +} + +static int dagame_k3menuitem_add_child(lua_State *L) { + struct menuitem *parent = lua_touserdata(L, 1); + struct menuitem *child = lua_touserdata(L, 2); + + k3MAddChild(parent->ptr, child->ptr); + + lua_pushvalue(L, 1); + + return 1; +} + +static bool k3menuitem_event_callback(struct k3MEvent *ev, uint8_t *ud_) { + void **ud = ud_; + + lua_State *L = ud[0]; + intptr_t luaref = (intptr_t) ud[1]; + + int oldtop = lua_gettop(L); + + lua_rawgeti(L, LUA_REGISTRYINDEX, luaref); + + if(lua_pcall(L, 0, 1, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 1); + return false; + } + + bool handled = lua_toboolean(L, -1); + + lua_pop(L, 1); + + assert(lua_gettop(L) == oldtop); + + return handled; +} +static int dagame_k3menuitem_on(lua_State *L) { + struct menuitem *item = lua_touserdata(L, 1); + + uint16_t evcode = 0xFFFF; + + if(!strcmp(lua_tostring(L, 2), "mouse_enter")) { + evcode = k3M_EVENT_MOUSE_ENTER; + } else if(!strcmp(lua_tostring(L, 2), "mouse_motion")) { + evcode = k3M_EVENT_MOUSE_MOTION; + } else if(!strcmp(lua_tostring(L, 2), "mouse_leave")) { + evcode = k3M_EVENT_MOUSE_RELEASE; + } else if(!strcmp(lua_tostring(L, 2), "mouse_press")) { + evcode = k3M_EVENT_MOUSE_PRESS; + } else if(!strcmp(lua_tostring(L, 2), "mouse_release")) { + evcode = k3M_EVENT_MOUSE_RELEASE; + } else if(!strcmp(lua_tostring(L, 2), "click")) { + evcode = k3M_EVENT_MOUSE_CLICK; + } else if(!strcmp(lua_tostring(L, 2), "key_press")) { + evcode = k3M_EVENT_KEY_PRESS; + } else if(!strcmp(lua_tostring(L, 2), "key_release")) { + evcode = k3M_EVENT_KEY_RELEASE; + } else if(!strcmp(lua_tostring(L, 2), "input")) { + evcode = k3M_EVENT_INPUT; + } else if(!strcmp(lua_tostring(L, 2), "draw")) { + evcode = k3M_EVENT_DRAW; + } else if(!strcmp(lua_tostring(L, 2), "complete")) { + evcode = k3M_EVENT_COMPLETE; + } else if(!strcmp(lua_tostring(L, 2), "all")) { + evcode = k3M_EVENT_ALL; + } + + if(evcode != 0xFFFF) { + lua_pushvalue(L, 3); + void *ud[2] = {L, (intptr_t) luaL_ref(L, LUA_REGISTRYINDEX)}; + + k3MRegisterEventHandler(item->ptr, evcode, k3menuitem_event_callback, ud, sizeof(ud)); + } + + lua_pushvalue(L, 1); + return 1; +} + +static int dagame_k3menuitem_get(lua_State *L) { + struct menuitem *item = lua_touserdata(L, 1); + + if(!strcmp(lua_tostring(L, 2), "invisible")) { + lua_pushboolean(L, item->ptr->invisible); + } else if(!strcmp(lua_tostring(L, 2), "disabled")) { + lua_pushboolean(L, item->ptr->disabled); + } else if(!strcmp(lua_tostring(L, 2), "set_bounds")) { + lua_pushcfunction(L, dagame_k3menuitem_set_bounds); + } else if(!strcmp(lua_tostring(L, 2), "add_child")) { + lua_pushcfunction(L, dagame_k3menuitem_add_child); + } else if(!strcmp(lua_tostring(L, 2), "on")) { + lua_pushcfunction(L, dagame_k3menuitem_on); + } else if(!strcmp(lua_tostring(L, 2), "text")) { + + char *txt = NULL; + + if(item->type == MENUITEM_LABEL) { + txt = ((struct k3MLabel*) item->ptr)->txt; + } else if(item->type == MENUITEM_TEXTBUTTON) { + txt = ((struct k3MTextButton*) item->ptr)->txt; + } else if(item->type == MENUITEM_TEXTINPUT) { + txt = ((struct k3MTextInput*) item->ptr)->txt; + } + + if(txt) { + lua_pushstring(L, txt); + } else { + lua_pushnil(L); + } + + } else lua_pushnil(L); + + return 1; +} + +static int dagame_k3menuitem_set(lua_State *L) { + struct menuitem *item = lua_touserdata(L, 1); + + if(!strcmp(lua_tostring(L, 2), "invisible")) { + item->ptr->invisible = lua_toboolean(L, 3); + } else if(!strcmp(lua_tostring(L, 2), "disabled")) { + item->ptr->disabled = lua_toboolean(L, 3); + } else if(!strcmp(lua_tostring(L, 2), "text")) { + char **txt = NULL; + + if(item->type == MENUITEM_LABEL) { + txt = &((struct k3MLabel*) item->ptr)->txt; + } else if(item->type == MENUITEM_TEXTBUTTON) { + txt = &((struct k3MTextButton*) item->ptr)->txt; + } else if(item->type == MENUITEM_TEXTINPUT) { + txt = &((struct k3MTextInput*) item->ptr)->txt; + } + + if(txt) { + if(*txt) { + free(*txt); + } + + const char *new = lua_tostring(L, 3); + + *txt = strdup(new ? new : "nil"); + } + } + + return 0; +} + +static int dagame_set_reduction(lua_State *L) { + float f = lua_type(L, 1) == LUA_TNUMBER ? lua_tonumber(L, 1) : 1; + k4_set_reduction(f); + return 0; +} + +static int dagame_set_texture_reduction(lua_State *L) { + int i = lua_type(L, 1) == LUA_TNUMBER ? lua_tointeger(L, 1) : 1; + k4_set_texture_reduction(i); + return 0; +} + +int PeercodeHandler = LUA_NOREF; +static int dagame_net_gen_peercode(lua_State *L) { + if(NetWrap.stage != 0 || PeercodeHandler != LUA_NOREF) { + lua_pushliteral(L, "Peercode generation already in progress"); + lua_error(L); + return 0; + } + + NetWrap.stoon = stoon_init("stun.easybell.de", 3478, 26656); + NetWrap.stage = 1; + + lua_pushvalue(L, 1); + PeercodeHandler = luaL_ref(L, LUA_REGISTRYINDEX); + + return 0; +} + +static int dagame_clipboard_set(lua_State *L) { + const char *k = lua_tostring(L, 2); + + if(!strcmp(k, "text")) { + k4_set_clipboard_text(lua_tostring(L, 3)); + } + + return 0; +} + +static int dagame_clipboard_get(lua_State *L) { + const char *k = lua_tostring(L, 2); + + if(!strcmp(k, "text")) { + const char *str = k4_get_clipboard_text(); + + if(str) { + lua_pushstring(L, str); + } else { + lua_pushnil(L); + } + + return 1; + } + + return 0; +} + +#define CONN_INVALID_PEERCODE 1 +static int conn(const char *peercode, bool host) { + for(int i = 0; i < STOON_CONN_INFO_SIZE; i++) { + int b = 0; + + if(peercode[i * 2 + 0] >= '0' && peercode[i * 2 + 0] <= '9') { + b |= (peercode[i * 2 + 0] - '0') << 4; + } else if(peercode[i * 2 + 0] >= 'a' && peercode[i * 2 + 0] <= 'f') { + b |= (peercode[i * 2 + 0] - 'a' + 10) << 4; + } else return CONN_INVALID_PEERCODE; + + if(peercode[i * 2 + 1] >= '0' && peercode[i * 2 + 1] <= '9') { + b |= (peercode[i * 2 + 1] - '0') << 0; + } else if(peercode[i * 2 + 1] >= 'a' && peercode[i * 2 + 1] <= 'f') { + b |= (peercode[i * 2 + 1] - 'a' + 10) << 0; + } else return CONN_INVALID_PEERCODE; + + NetWrap.otherpeer[i] = b; + } + + NetWrap.isHost = host; + NetWrap.stage = 3; + + return 0; +} + +static int dagame_net_host(lua_State *L) { + int status = conn(lua_tostring(L, 1), true); + + lua_pushboolean(L, !status); + + if(status) { + if(status == CONN_INVALID_PEERCODE) { + lua_pushliteral(L, "peercode"); + } else { + lua_pushliteral(L, "unknown"); + } + return 2; + } + + return 1; +} + +static int dagame_net_join(lua_State *L) { + int status = conn(lua_tostring(L, 1), false); + + lua_pushboolean(L, !status); + + if(status) { + if(status == CONN_INVALID_PEERCODE) { + lua_pushliteral(L, "peercode"); + } else { + lua_pushliteral(L, "unknown"); + } + return 2; + } + + return 1; +} + +#include +static int os_time(lua_State *L) { + lua_pushnumber(L, glfwGetTime() - LuaapiStartTime); + return 1; +} + +void luaapi_init() { + k3Log(k3_DEBUG, "Creating Lua environment"); + + L = luaL_newstate(); + + /*lua_newtable(L); + lua_newtable(L); + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS); + lua_setfield(L, -2, "__index"); + lua_setmetatable(L, -2); + consoleEnvironment = luaL_ref(L, LUA_REGISTRYINDEX);*/ + + k3Log(k3_DEBUG, "Loading Lua stdlib"); + + luaL_requiref(L, "_G", luaopen_base, 1); + luaL_requiref(L, LUA_TABLIBNAME, luaopen_table, 1); + luaL_requiref(L, LUA_STRLIBNAME, luaopen_string, 1); + luaL_requiref(L, LUA_MATHLIBNAME, luaopen_math, 1); + luaL_requiref(L, LUA_DBLIBNAME, luaopen_debug, 1); + lua_pop(L, 5); + + k3Log(k3_DEBUG, "Setting custom require"); + + lua_pushcfunction(L, luaapi_require); + lua_setglobal(L, "require"); + + k3Log(k3_DEBUG, "Creating table game"); + + lua_newtable(L); + + lua_pushcfunction(L, game_addentity); + lua_setfield(L, -2, "addentity"); + + k3Log(k3_DEBUG, "Creating table game.triggers"); + lua_newtable(L); + lua_pushvalue(L, -1); + gametriggersref = luaL_ref(L, LUA_REGISTRYINDEX); + + lua_newtable(L); + lua_pushcfunction(L, game_triggers_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, game_triggers_get); + lua_setfield(L, -2, "__index"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "triggers"); + + k3Log(k3_DEBUG, "Creating table game.conveyors"); + lua_newtable(L); + lua_newtable(L); + lua_pushcfunction(L, game_conveyors_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, game_conveyors_get); + lua_setfield(L, -2, "__index"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + + lua_pushvalue(L, -1); + gameconveyorsref = luaL_ref(L, LUA_REGISTRYINDEX); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "conveyors"); + + lua_pushcfunction(L, game_water); + lua_setfield(L, -2, "water"); + + k3Log(k3_DEBUG, "Creating table game.mix"); + lua_newtable(L); + lua_pushcfunction(L, dagame_mixsound); + lua_setfield(L, -2, "sound"); + + lua_pushcfunction(L, game_mixplay); + lua_setfield(L, -2, "play"); + + lua_pushcfunction(L, dagame_mixstop); + lua_setfield(L, -2, "stop"); + + lua_pushcfunction(L, game_mixqueue); + lua_setfield(L, -2, "queue"); + + lua_pushcfunction(L, dagame_mixpower); + lua_setfield(L, -2, "power"); + lua_setfield(L, -2, "mix"); + + lua_pushcfunction(L, game_ref); + lua_setfield(L, -2, "ref"); + + lua_pushcfunction(L, game_batch); + lua_setfield(L, -2, "batch"); + + lua_pushcfunction(L, game_get_component); + lua_setfield(L, -2, "getcomponent"); + + lua_pushcfunction(L, game_camfocus); + lua_setfield(L, -2, "camfocus"); + + lua_pushcfunction(L, game_load); + lua_setfield(L, -2, "load"); + + lua_pushcfunction(L, dagame_cleanup); + lua_setfield(L, -2, "cleanup"); + + lua_pushcfunction(L, dagame_joint); + lua_setfield(L, -2, "joint"); + + lua_pushcfunction(L, dagame_setphys); + lua_setfield(L, -2, "setphys"); + + lua_pushcfunction(L, dagame_mdl); + lua_setfield(L, -2, "mdl"); + + lua_pushcfunction(L, dagame_trimesh); + lua_setfield(L, -2, "trimesh"); + + lua_pushcfunction(L, dagame_firstperson); + lua_setfield(L, -2, "firstperson"); + + lua_pushcfunction(L, dagame_ray); + lua_setfield(L, -2, "ray"); + + lua_pushcfunction(L, dagame_draw); + lua_setfield(L, -2, "draw"); + + lua_pushcfunction(L, dagame_skybox); + lua_setfield(L, -2, "skybox"); + + lua_pushcfunction(L, dagame_send); + lua_setfield(L, -2, "send"); + + lua_pushcfunction(L, dagame_set_reduction); + lua_setfield(L, -2, "set_reduction"); + + lua_pushcfunction(L, dagame_set_texture_reduction); + lua_setfield(L, -2, "set_texture_reduction"); + + k3Log(k3_DEBUG, "Creating table game.ui"); + lua_newtable(L); + lua_pushcfunction(L, dagame_ui_screen); + lua_setfield(L, -2, "screen"); + + lua_pushcfunction(L, dagame_ui_label); + lua_setfield(L, -2, "label"); + + lua_pushcfunction(L, dagame_ui_textbutton); + lua_setfield(L, -2, "textbutton"); + + lua_pushcfunction(L, dagame_ui_textinput); + lua_setfield(L, -2, "textinput"); + lua_setfield(L, -2, "ui"); + + k3Log(k3_DEBUG, "Creating table game.net"); + lua_newtable(L); + lua_pushcfunction(L, dagame_net_gen_peercode); + lua_setfield(L, -2, "gen_peercode"); + + lua_pushcfunction(L, dagame_net_host); + lua_setfield(L, -2, "host"); + + lua_pushcfunction(L, dagame_net_join); + lua_setfield(L, -2, "join"); + lua_setfield(L, -2, "net"); + + k3Log(k3_DEBUG, "Creating table game.controls"); + lua_newtable(L); + lua_newtable(L); + lua_pushcfunction(L, dagame_controls_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, dagame_controls_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "controls"); + + k3Log(k3_DEBUG, "Creating table game.clipboard"); + lua_newtable(L); + lua_newtable(L); + lua_pushcfunction(L, dagame_clipboard_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, dagame_clipboard_get); + lua_setfield(L, -2, "__index"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_setmetatable(L, -2); + lua_setfield(L, -2, "clipboard"); + + k3Log(k3_DEBUG, "Creating metatable for game"); + lua_newtable(L); + lua_pushcfunction(L, game_get); + lua_setfield(L, -2, "__index"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + + lua_pushcfunction(L, game_set); + lua_setfield(L, -2, "__newindex"); + lua_setmetatable(L, -2); + + lua_setglobal(L, "game"); + + luaL_newmetatable(L, "k3water"); + lua_pushcfunction(L, game_water_simulate); + lua_setfield(L, -2, "simulate"); + + lua_pushcfunction(L, game_water_update); + lua_setfield(L, -2, "update"); + + lua_pushcfunction(L, game_water_disturb); + lua_setfield(L, -2, "disturb"); + + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3mixwave"); + lua_pushcfunction(L, game_mixwave_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, game_mixwave_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, dagame_mixwave_gc); + lua_setfield(L, -2, "__gc"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3mixqueue"); + lua_pushcfunction(L, game_queue_add); + lua_setfield(L, -2, "add"); + + lua_pushcfunction(L, game_queue_clear); + lua_setfield(L, -2, "clear"); + + lua_pushcfunction(L, game_queue_gc); + lua_setfield(L, -2, "__gc"); + + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, game_mixwave_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3submissive"); + lua_pushcfunction(L, game_submissive_assign); + lua_setfield(L, -2, "assign"); + + lua_pushcfunction(L, game_submissive_load); + lua_setfield(L, -2, "load"); + + lua_pushcfunction(L, game_submissive_send); + lua_setfield(L, -2, "send"); + + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3cphysics"); + lua_pushcfunction(L, game_cphysics_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, game_cphysics_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3crender"); + lua_pushcfunction(L, game_crender_get); + lua_setfield(L, -2, "__index"); + + //lua_pushcfunction(L, game_crender_set); + //lua_setfield(L, -2, "__newindex"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3cboned"); + lua_pushcfunction(L, game_cboned_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, game_cboned_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3cbonedanim"); + lua_pushcfunction(L, game_cbonedanim_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3mdl"); + lua_pushcfunction(L, game_k3mdl_get); + lua_setfield(L, -2, "__index"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3mat"); + lua_pushcfunction(L, game_k3mat_get); + lua_setfield(L, -2, "__index"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3physics"); + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3matuniforms"); + lua_pushcfunction(L, game_k3matuniforms_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, game_k3matuniforms_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3body"); + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3conveyor"); + lua_pushcfunction(L, game_conveyor_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, game_conveyor_get); + lua_setfield(L, -2, "__index"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k4ray"); + lua_pushcfunction(L, dagame_ray_get); + lua_setfield(L, -2, "__index"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3menuitem"); + lua_pushcfunction(L, dagame_k3menuitem_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, dagame_k3menuitem_get); + lua_setfield(L, -2, "__index"); + + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + luaL_newmetatable(L, "k3mixsource"); + lua_pushboolean(L, 0); + lua_setfield(L, -2, "__metatable"); + lua_pop(L, 1); + + lua_newtable(L); + lua_pushcfunction(L, os_time); + lua_setfield(L, -2, "time"); + lua_setglobal(L, "os"); +} + +void luaapi_load(const char *name) { + lua_getglobal(L, "require"); + lua_pushstring(L, name); + if(lua_pcall(L, 1, 1, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 1); + return; + } + + lua_getfield(L, -1, "load"); + if(lua_pcall(L, 0, 0, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 1); + return; + } + + if(Game.isAuthority) { + luaapi_join(NULL, 0); + } +} + +void luaapi_render(double dt, double alpha) { + lua_getglobal(L, "game"); + lua_getfield(L, -1, "render"); + if(!lua_isfunction(L, -1)) { + lua_pop(L, 1); + } else { + lua_pushnumber(L, dt); + lua_pushnumber(L, alpha); + if(lua_pcall(L, 2, 0, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 1); + } + } + lua_pop(L, 1); +} + +static int game_me_assign(lua_State *L) { + Game.controlled = lua_tointeger(L, 2); + Game.spectated = lua_tointeger(L, 2); + + return 0; +} + +int luaapi_join(ENetPeer *peer, int oldlua) { + int ret; + + lua_getglobal(L, "game"); + lua_getfield(L, -1, "join"); + if(lua_isfunction(L, -1)) { + if(oldlua) { + ret = oldlua; + lua_rawgeti(L, LUA_REGISTRYINDEX, oldlua); + } else if (peer) { + ENetPeer **ud = lua_newuserdata(L, sizeof(peer)); + *ud = peer; + luaL_setmetatable(L, "k3submissive"); + lua_pushvalue(L, -1); + ret = luaL_ref(L, LUA_REGISTRYINDEX); + } else { + lua_newtable(L); + lua_pushcfunction(L, game_me_assign); + lua_setfield(L, -2, "assign"); + lua_pushvalue(L, -1); + ret = luaL_ref(L, LUA_REGISTRYINDEX); + } + + if(lua_pcall(L, 1, 0, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 1); + } + } else { + lua_pop(L, 1); + } + lua_pop(L, 1); + return ret; +} + +void luaapi_leave(int ref) { + lua_getglobal(L, "game"); + lua_getfield(L, -1, "leave"); + if(lua_isfunction(L, -1)) { + lua_rawgeti(L, LUA_REGISTRYINDEX, ref); + if(lua_pcall(L, 1, 0, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 1); + } + } else { + lua_pop(L, 1); + } + lua_pop(L, 1); +} + +static char *read_full_file(const char *prepend, const char *fnprefix, const char *fn, const char *append) { + char namebuf[256]; + snprintf(namebuf, sizeof(namebuf), "%s%s", fnprefix, fn); + + FILE *f = fopen(namebuf, "rb"); + if(!f) return NULL; + + fseek(f, 0, SEEK_END); + size_t sz = ftell(f); + fseek(f, 0, SEEK_SET); + + char *ret = malloc(strlen(prepend) + sz + strlen(append) + 1); + strcpy(ret, prepend); + fread(ret + strlen(prepend), 1, sz, f); + strcpy(ret + strlen(prepend) + sz, append); + ret[strlen(prepend) + sz + strlen(append)] = 0; + + fclose(f); + + return ret; +} + +static int glsl_version_supported(const char *gl, size_t lua) { + if((k3IsCore && lua < 330) || (!k3IsCore && lua >= 330)) { + return 0; + } + + char buf[16]; + snprintf(buf, sizeof(buf), "%u", lua); + + if(gl[0] < buf[0]) { + return 0; + } + + return strcmp(buf + 1, gl + 2) <= 0; +} + +static const char *k3glslloader(const char *fn) { + char buf[512]; + snprintf(buf, sizeof(buf), "assets/mdl/%s", fn); + + FILE *f = fopen(buf, "rb"); + + fseek(f, 0, SEEK_END); + + size_t len = ftell(f); + + char *data = malloc(len + 1); + + fseek(f, 0, SEEK_SET); + + fread(data, 1, len, f); + + data[len] = 0; + + fclose(f); + + return data; +} + +// The glsl field of a material table is cached and stored +// in the resource manager. This function generates its name. +static char *glsl_table_fullname() { + lua_getfield(L, -1, "vs"); + lua_geti(L, -1, 1); // Version + size_t vsVer = lua_tointeger(L, -1); + lua_geti(L, -2, 2); // Filename + char *vsFile = strdup(lua_tostring(L, -1)); + lua_pop(L, 3); + + lua_getfield(L, -1, "fs"); + lua_geti(L, -1, 1); // Version + size_t fsVer = lua_tointeger(L, -1); + lua_geti(L, -2, 2); // Filename + char *fsFile = strdup(lua_tostring(L, -1)); + lua_pop(L, 3); + + char ret[1024]; + snprintf(ret, sizeof(ret), "\x1E%u\x1E%s\x1E%u\x1E%s\x1E", vsVer, vsFile, fsVer, fsFile); + + lua_getfield(L, -1, "defs"); + lua_pushnil(L); + while(lua_next(L, -2)) { + if(!lua_isstring(L, -2)) { + puts("Ignoring non-string define name."); + lua_pop(L, 1); + continue; + } + + char def[128]; + snprintf(def, sizeof(def), "%s\x1F%s\x1E", lua_tostring(L, -2), lua_tostring(L, -1)); + + strncat(ret, def, sizeof(ret) - strlen(ret) - 1); + + lua_pop(L, 1); + } + lua_pop(L, 1); + + free(vsFile); + free(fsFile); + + return strdup(ret); +} + +static int parse_glsl_table(struct k3Mat *mat) { +#ifdef k3_IRREGULAR_SHADOWS + static struct k3GLSLF *irreg1frag, *irreg2frag; + static struct k3GLSLG *irreg2geom; + + if(!irreg1frag) { + char *src = read_full_file("", "", "assets/irregpass1.fs.glsl", ""); + + irreg1frag = k3ShaderGLSLF(src, k3glslloader); + + free(src); + } + if(!irreg2frag) { + char *src = read_full_file("", "", "assets/irregpass2.fs.glsl", ""); + + irreg2frag = k3ShaderGLSLF(src, k3glslloader); + + free(src); + } + if(!irreg2geom) { + char *src = read_full_file("", "", "assets/irregpass2.gs.glsl", ""); + + irreg2geom = k3ShaderGLSLG(src, k3glslloader); + + free(src); + } +#endif + + char *glslfullname = glsl_table_fullname(); + + struct ResManRes *res = resman_reffull(RESMAN_OTHER, glslfullname); + + if(res->thing) { + mat->passes[0].glsl.hp = res->thing; + +#ifdef k3_IRREGULAR_SHADOWS + glslfullname[0]--; + mat->passes[0].glsl.hpIrreg1 = resman_ref(RESMAN_OTHER, glslfullname); + + glslfullname[0]--; + mat->passes[0].glsl.hpIrreg2 = resman_ref(RESMAN_OTHER, glslfullname); +#endif + } else { + const char *maxGLSL = glGetString(GL_SHADING_LANGUAGE_VERSION_ARB); + + int i; + + lua_getfield(L, -1, "vs"); + lua_geti(L, -1, 1); // Version + size_t vsVer = lua_tointeger(L, -1); + lua_geti(L, -2, 2); // Filename + char *vsFile = strdup(lua_tostring(L, -1)); + i = glsl_version_supported(maxGLSL, vsVer); + lua_pop(L, 3); + + if(!i) { + return 0; + } + + lua_getfield(L, -1, "fs"); + lua_geti(L, -1, 1); // Version + size_t fsVer = lua_tointeger(L, -1); + lua_geti(L, -2, 2); // Filename + char *fsFile = strdup(lua_tostring(L, -1)); + i = glsl_version_supported(maxGLSL, fsVer); + lua_pop(L, 3); + + if(!i) { + return 0; + } + + char defs[512] = {}; + + lua_getfield(L, -1, "defs"); + lua_pushnil(L); + while(lua_next(L, -2)) { + if(!lua_isstring(L, -2)) { + puts("Ignoring non-string define name."); + lua_pop(L, 1); + continue; + } + + char def[128]; + snprintf(def, sizeof(def), "#define %s %s\n", lua_tostring(L, -2), lua_tostring(L, -1)); + + strncat(defs, def, sizeof(defs) - strlen(defs) - 1); + + lua_pop(L, 1); + } + lua_pop(L, 1); + + char prefix[272]; + + snprintf(prefix, sizeof(prefix), "#version %lu\n%s", vsVer, defs); + char *vsSrc = read_full_file(prefix, "assets/mdl/", vsFile, ""); + + snprintf(prefix, sizeof(prefix), "#version %lu\n%s", fsVer, defs); + char *fsSrc = read_full_file(prefix, "assets/mdl/", fsFile, ""); + + k3Log(k3_INFO, "Attempting to compile \"%s\" & \"%s\"...", vsFile, fsFile); + + free(vsFile); + free(fsFile); + + struct k3GLSLV *vs = k3ShaderGLSLV(vsSrc, k3glslloader); + struct k3GLSLF *fs = k3ShaderGLSLF(fsSrc, k3glslloader); + + free(vsSrc); + free(fsSrc); + + // FIXME: mark shaders themselves for deletion? + + struct k3GLSLP *p = k3ProgramGLSL(vs, fs, NULL); + + res->thing = p; + + mat->passes[0].glsl.hp = p; + +#ifdef k3_IRREGULAR_SHADOWS + glslfullname[0]--; + mat->passes[0].glsl.hpIrreg1 = k3ProgramGLSL(vs, irreg1frag, NULL); + resman_reffull(RESMAN_OTHER, glslfullname)->thing = mat->passes[0].glsl.hpIrreg1; + + glslfullname[0]--; + mat->passes[0].glsl.hpIrreg2 = k3ProgramGLSL(vs, irreg2frag, irreg2geom); + resman_reffull(RESMAN_OTHER, glslfullname)->thing = mat->passes[0].glsl.hpIrreg2; +#endif + } + + lua_getfield(L, -1, "u"); // Uniforms + lua_pushnil(L); + while(lua_next(L, -2)) { + if(!lua_isstring(L, -2)) { + // Ignore non-string key + k3Log(k3_ERR, "Non-string uniform name in lua material definition."); + lua_pop(L, 1); + continue; + } + + int u = mat->passes[0].glsl.uCount; + if(u == k3_MAX_GLSL_UNIFORMS) { + k3Log(k3_INFO, "Too many uniforms. Skipping."); + } else { + strncpy(mat->passes[0].glsl.u[u].name, lua_tostring(L, -2), sizeof(mat->passes[0].glsl.u[u].name)); + mat->passes[0].glsl.u[u].id = k3ProgramGetUId(res->thing, lua_tostring(L, -2)); + + if(lua_isinteger(L, -1)) { + mat->passes[0].glsl.u[u].type = k3_MAT_UNIFORM_I1; + mat->passes[0].glsl.u[u].i1 = lua_tointeger(L, -1); + mat->passes[0].glsl.uCount++; + } else if(lua_isnumber(L, -1)) { + mat->passes[0].glsl.u[u].type = k3_MAT_UNIFORM_F1; + mat->passes[0].glsl.u[u].f1 = lua_tonumber(L, -1); + mat->passes[0].glsl.uCount++; + } else { + k3Log(k3_ERR, "Only i1 and f1 uniforms are supported at the moment."); + } + + } + + lua_pop(L, 1); + } + lua_pop(L, 1); + + return 1; +} + +void luaapi_fillmaterial_direct(struct k3Mat *mat) { + lua_getfield(L, -1, "primitive"); + lua_getfield(L, -1, "diffuse"); + if(lua_istable(L, -1)) { + lua_geti(L, -1, 1); + lua_geti(L, -2, 2); + lua_geti(L, -3, 3); + lua_geti(L, -4, 4); + mat->primitive.diffuse[0] = lua_tonumber(L, -4); + mat->primitive.diffuse[1] = lua_tonumber(L, -3); + mat->primitive.diffuse[2] = lua_tonumber(L, -2); + mat->primitive.diffuse[3] = lua_tonumber(L, -1); + lua_pop(L, 4); + } + lua_pop(L, 1); + lua_getfield(L, -1, "specular"); + if(lua_istable(L, -1)) { + lua_geti(L, -1, 1); + lua_geti(L, -2, 2); + lua_geti(L, -3, 3); + lua_geti(L, -4, 4); + mat->primitive.specular[0] = lua_tonumber(L, -4); + mat->primitive.specular[1] = lua_tonumber(L, -3); + mat->primitive.specular[2] = lua_tonumber(L, -2); + mat->primitive.specular[3] = lua_tonumber(L, -1); + lua_pop(L, 4); + } + lua_pop(L, 1); + lua_getfield(L, -1, "emission"); + if(lua_istable(L, -1)) { + lua_geti(L, -1, 1); + lua_geti(L, -2, 2); + lua_geti(L, -3, 3); + lua_geti(L, -4, 4); + mat->primitive.emission[0] = lua_tonumber(L, -4); + mat->primitive.emission[1] = lua_tonumber(L, -3); + mat->primitive.emission[2] = lua_tonumber(L, -2); + mat->primitive.emission[3] = lua_tonumber(L, -1); + lua_pop(L, 4); + } + lua_pop(L, 1); + lua_getfield(L, -1, "shininess"); + mat->primitive.shininess = lua_tonumber(L, -1); + lua_pop(L, 1); + lua_pop(L, 1); + + GLuint maxMTUnits = 0, maxGLSLUnits = 0; + if(k3IsCore) { + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxGLSLUnits); + } else { + if(GLAD_GL_ARB_shading_language_100) { + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &maxGLSLUnits); + } + glGetIntegerv(GL_MAX_TEXTURE_UNITS, &maxMTUnits); + } + + for(size_t i = 1; i <= 128; i++) { + int datop = lua_gettop(L); + + lua_geti(L, -1, i); + + if(lua_type(L, -1) != LUA_TTABLE) { + lua_pop(L, 1); + break; + } + + // First pass + lua_geti(L, -1, 1); + + lua_getfield(L, -1, "additive"); + mat->passes[0].additive = lua_toboolean(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "transparent"); + mat->passes[0].transparent = lua_toboolean(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "nocull"); + mat->passes[0].nocull = lua_toboolean(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "alphatest"); + mat->passes[0].alphatest = lua_toboolean(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "aabb"); + mat->passes[0].aabb = lua_isnil(L, -1) ? NAN : lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "glsl"); + lua_getfield(L, -2, "arbvp"); + lua_getfield(L, -3, "arbfp"); + if((lua_istable(L, -1) || lua_istable(L, -2)) + lua_istable(L, -3) > 1) { + k3Log(k3_ERR, "ARB programs and GLSL programs are mutually exclusive."); + lua_settop(L, datop); + continue; + } + lua_pop(L, 3); + + int usesGLSL = 0; + lua_getfield(L, -1, "glsl"); { + if(lua_istable(L, -1)) { + if(!k3IsCore && !GLAD_GL_ARB_shading_language_100) { + // GLSL not supported. + lua_settop(L, datop); + continue; + } else { + if(!parse_glsl_table(mat)) { + lua_settop(L, datop); + continue; + } + } + usesGLSL = 1; + } + } lua_pop(L, 1); + + lua_getfield(L, -1, "arbvp"); { + if(lua_istable(L, -1)) { + lua_geti(L, -1, 2); + char *src = read_full_file("", "assets/mdl/", lua_tostring(L, -1), ""); + mat->passes[0].arbvp.vp = k3ProgramARBVP(src); + free(src); + lua_pop(L, 1); + } + } lua_pop(L, 1); + + lua_getfield(L, -1, "arbfp"); { + if(lua_istable(L, -1)) { + lua_geti(L, -1, 2); + char *src = read_full_file("", "assets/mdl/", lua_tostring(L, -1), ""); + mat->passes[0].arbfp.fp = k3ProgramARBFP(src); + free(src); + lua_pop(L, 1); + } + } lua_pop(L, 1); + + lua_getfield(L, -1, "units"); { + size_t amountOfUnits = lua_rawlen(L, -1); + if(amountOfUnits > (usesGLSL ? maxGLSLUnits : maxMTUnits) || amountOfUnits > k3_MAX_GLSL_UNITS) { + // Too many texture units. + // FIXME: This actually isn't a correct test; it should be done per shader + lua_settop(L, datop); + continue; + } + for(size_t u = 0; u < amountOfUnits; u++) { + lua_geti(L, -1, u + 1); + lua_getfield(L, -1, "tex"); + mat->passes[0].units[u] = resman_ref(RESMAN_TEXTURE, lua_tostring(L, -1)); + lua_pop(L, 2); + } + mat->passes[0].unitsUsed = amountOfUnits; + } lua_pop(L, 1); + + lua_pop(L, 1); + lua_pop(L, 1); + + break; + } +} + +void luaapi_fillmaterial(const char *fn, struct k3Mat *mat) { + memset(mat, 0, sizeof(*mat)); + + k3Log(k3_DEBUG, "Loading material %s", fn); + + if(luaL_loadfilex(L, fn, "t") != LUA_OK || lua_pcall(L, 0, 1, 0) != LUA_OK) { + mat->primitive.diffuse[0] = (float) rand() / RAND_MAX; + mat->primitive.diffuse[1] = (float) rand() / RAND_MAX; + mat->primitive.diffuse[2] = (float) rand() / RAND_MAX; + mat->primitive.diffuse[3] = 1; + + mat->passes[0].aabb = NAN; + + puts(lua_tostring(L, -1)); + + lua_pop(L, 1); + + return; + } + + luaapi_fillmaterial_direct(mat); + + lua_pop(L, 1); +} + +struct k3Light *luaapi_getlights(size_t *count) { + static struct k3Light *ret; + + lua_getglobal(L, "game"); + lua_getfield(L, -1, "lights"); + + if(ret) { + _mm_free(ret); + ret = NULL; + } + + if(!lua_isnil(L, -1)) { + lua_len(L, -1); + *count = lua_tointeger(L, -1); + lua_pop(L, 1); + + ret = _mm_malloc(sizeof(*ret) * *count, 16); + + memset(ret, 0, sizeof(*ret) * *count); + + for(size_t i = 0; i < *count; i++) { + lua_geti(L, -1, i + 1); + lua_geti(L, -1, 1); // TYPE + if(!strcmp(lua_tostring(L, -1), "dir")) { + ret[i].type = k3_DIRECTIONAL; + } else if(!strcmp(lua_tostring(L, -1), "spot")) { + ret[i].type = k3_SPOT; + } else if(!strcmp(lua_tostring(L, -1), "omni")) { + ret[i].type = k3_OMNI; + + lua_getfield(L, -2, "direction"); + if(!lua_isnil(L, -1)) { + ret[i].type = k3_HALF_OMNI; + } + lua_pop(L, 1); + } + lua_pop(L, 1); + + lua_getfield(L, -1, "radius"); + ret[i].radius = lua_tonumber(L, -1); + lua_pop(L, 1); + + lua_getfield(L, -1, "color"); + lua_geti(L, -1, 1); + lua_geti(L, -2, 2); + lua_geti(L, -3, 3); + lua_geti(L, -4, 4); + ret[i].color[0] = lua_tonumber(L, -4); + ret[i].color[1] = lua_tonumber(L, -3); + ret[i].color[2] = lua_tonumber(L, -2); + ret[i].color[3] = lua_tonumber(L, -1); + lua_pop(L, 5); + + if(ret[i].type == k3_OMNI) { + lua_getfield(L, -1, "position"); + lua_geti(L, -1, 1); + lua_geti(L, -2, 2); + lua_geti(L, -3, 3); + lua_geti(L, -4, 4); + ret[i].omni.position[0] = lua_tonumber(L, -4); + ret[i].omni.position[1] = lua_tonumber(L, -3); + ret[i].omni.position[2] = lua_tonumber(L, -2); + ret[i].omni.position[3] = lua_tonumber(L, -1); + lua_pop(L, 5); + } else if(ret[i].type == k3_HALF_OMNI || ret[i].type == k3_SPOT) { + lua_getfield(L, -1, "position"); + lua_geti(L, -1, 1); + lua_geti(L, -2, 2); + lua_geti(L, -3, 3); + lua_geti(L, -4, 4); + ret[i].spot.position[0] = lua_tonumber(L, -4); + ret[i].spot.position[1] = lua_tonumber(L, -3); + ret[i].spot.position[2] = lua_tonumber(L, -2); + ret[i].spot.position[3] = lua_tonumber(L, -1); + lua_pop(L, 5); + + lua_getfield(L, -1, "direction"); + lua_geti(L, -1, 1); + lua_geti(L, -2, 2); + lua_geti(L, -3, 3); + lua_geti(L, -4, 4); + ret[i].spot.direction[0] = lua_tonumber(L, -4); + ret[i].spot.direction[1] = lua_tonumber(L, -3); + ret[i].spot.direction[2] = lua_tonumber(L, -2); + ret[i].spot.direction[3] = lua_tonumber(L, -1); + lua_pop(L, 5); + + lua_getfield(L, -1, "angle"); + ret[i].spot.angle = lua_tonumber(L, -1); + + if(ret[i].spot.angle == 0) { + ret[i].spot.angle = glm_rad(165); + } + lua_pop(L, 1); + } else if(ret[i].type == k3_DIRECTIONAL) { + lua_getfield(L, -1, "direction"); + lua_geti(L, -1, 1); + lua_geti(L, -2, 2); + lua_geti(L, -3, 3); + lua_geti(L, -4, 4); + ret[i].dir.direction[0] = lua_tonumber(L, -4); + ret[i].dir.direction[1] = lua_tonumber(L, -3); + ret[i].dir.direction[2] = lua_tonumber(L, -2); + ret[i].dir.direction[3] = lua_tonumber(L, -1); + glm_vec3_normalize(ret[i].dir.direction); + lua_pop(L, 5); + } + lua_pop(L, 1); + } + } else *count = 0; + + lua_pop(L, 2); + + return ret; +} + +void luaapi_cleanup() { + game_cleanup(); + + lua_getglobal(L, "game"); + lua_pushnil(L); + lua_setfield(L, -2, "lights"); + + lua_pushnil(L); + lua_setfield(L, -2, "render"); + + lua_pushnil(L); + lua_setfield(L, -2, "render2d"); + + lua_pushnil(L); + lua_setfield(L, -2, "join"); + + lua_pushnil(L); + lua_setfield(L, -2, "leave"); + + lua_pushnil(L); + lua_setfield(L, -2, "ctrl"); + lua_pop(L, 1); + + lua_rawgeti(L, LUA_REGISTRYINDEX, gametriggersref); + while(1) { + lua_pushnil(L); + if(lua_next(L, -2) == 0) { + break; + } + lua_pop(L, 1); + lua_pushnil(L); + lua_rawset(L, -3); + } + lua_pop(L, 1); +} + +/*void luaapi_perform(const char *statement) { + puts(statement); + if(luaL_loadstring(L, statement) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 1); + return; + } + lua_rawgeti(L, LUA_REGISTRYINDEX, consoleEnvironment); + lua_setupvalue(L, -2, 1); + if(lua_pcall(L, 0, 0, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 1); + return; + } +}*/ + +void luaapi_ctrlev(int ctrl, int action) { + lua_getglobal(L, "game"); + lua_getfield(L, -1, "ctrl"); + if(lua_isnil(L, -1)) { + lua_pop(L, 2); + return; + } else { + lua_pushstring(L, k4_control_get_name_by_ctrl(ctrl)); + lua_pushinteger(L, action); + if(lua_pcall(L, 2, 0, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 2); + return; + } + } + lua_pop(L, 1); +} + +void luaapi_render2d() { + lua_getglobal(L, "game"); + lua_getfield(L, -1, "render2d"); + if(lua_isnil(L, -1)) { + lua_pop(L, 2); + return; + } else { + if(lua_pcall(L, 0, 0, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 2); + return; + } + } + lua_pop(L, 1); +} + +int luaapi_recvmsg(struct bstr *b, int cli) { + lua_getglobal(L, "game"); + lua_getfield(L, -1, "receive"); + if(cli == LUA_NOREF) { + lua_pushnil(L); + } else { + lua_rawgeti(L, LUA_REGISTRYINDEX, cli); + } + if(!deserialize(b)) { + lua_pop(L, 3); + return 0; + } + if(lua_isnil(L, -3)) { + lua_pop(L, 4); + return 1; + } else { + if(lua_pcall(L, 2, 0, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 2); + return 1; + } + } + lua_pop(L, 1); + + return 1; +} + +void luaapi_escape() { + lua_getglobal(L, "game"); + lua_getfield(L, -1, "escape"); + if(lua_isnil(L, -1)) { + lua_pop(L, 2); + return; + } else { + if(lua_pcall(L, 0, 0, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 2); + return; + } + } + lua_pop(L, 1); +} + +void luaapi_peercode_found(const char *peercode) { + if(PeercodeHandler == LUA_NOREF) { + puts("Peercode found but no handler"); + return; + } + + lua_rawgeti(L, LUA_REGISTRYINDEX, PeercodeHandler); + if(lua_isnil(L, -1)) { + lua_pop(L, 1); + return; + } else { + lua_pushstring(L, peercode); + if(lua_pcall(L, 1, 0, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 1); + return; + } + } + lua_pop(L, 1); + + luaL_unref(L, LUA_REGISTRYINDEX, PeercodeHandler); + PeercodeHandler = LUA_NOREF; +} + +void luaapi_update() { + lua_getglobal(L, "game"); + lua_getfield(L, -1, "update"); + if(lua_isnil(L, -1)) { + lua_pop(L, 2); + return; + } else { + if(lua_pcall(L, 0, 0, 0) != LUA_OK) { + puts(lua_tostring(L, -1)); + lua_pop(L, 2); + return; + } + } + lua_pop(L, 1); +} diff --git a/src/luaapi.h b/src/luaapi.h new file mode 100644 index 0000000..da6a038 --- /dev/null +++ b/src/luaapi.h @@ -0,0 +1,51 @@ +#pragma once + +#include"enet.h" + +#include + +extern int LuaapiCamFocus; +extern vec3 LuaapiCamFocusPos; +extern vec3 LuaapiCamFocusDir; + +extern mat4 LuaapiCamMatrix; + +extern int LuaapiFirstPerson; + +extern double LuaapiStartTime; +extern float LuaapiFov; + +extern struct k3Tex *LuaapiSkybox; +extern vec4 LuaapiSkyboxRotation; +extern bool LuaapiSkyboxRotationFunky; + +void luaapi_init(); +void luaapi_load(const char *name); +void luaapi_render(double dt, double alpha); + +void luaapi_render2d(); + +void luaapi_update(); + +// peer will be NULL if local player +int luaapi_join(ENetPeer *peer, int oldlua); +void luaapi_leave(int); + +struct k3Mat; +void luaapi_fillmaterial_direct(struct k3Mat *mat); +void luaapi_fillmaterial(const char *src, struct k3Mat*); + +struct k3Light *luaapi_getlights(size_t *count); + +void luaapi_cleanup(); + +void luaapi_perform(const char *statement); + +void luaapi_ctrlev(int ctrl, int action); + +struct bstr; +int luaapi_recvmsg(struct bstr *b, int lua); + +void luaapi_escape(); + +void luaapi_peercode_found(const char *peercode); diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..f392bdf --- /dev/null +++ b/src/main.c @@ -0,0 +1,962 @@ +#include"k4.h" + +#ifdef _WIN32 +#include +#endif + +#define ENET_IMPLEMENTATION + +#define GLAD_GL_IMPLEMENTATION +#include"gl.h" + +#pragma GCC push_options +#pragma GCC optimize("Ofast") +#define STB_IMAGE_IMPLEMENTATION +#include"stb_image.h" + +#define STB_IMAGE_RESIZE_IMPLEMENTATION +#include"stb_image_resize.h" +#pragma GCC pop_options + +#include +#include +#include + +#include"k3.h" +#include"k3water.h" +#include"k3mix.h" +#include"k3font.h" +#include"k3menu.h" +#include"k3bloom.h" + +#include"resman.h" + +#include"game.h" + +#include"luaapi.h" + +#include"net_server.h" +#include"net_client.h" + +#include + +struct NetWrap NetWrap; + +GLFWwindow *GameWnd; + +static int TextureResolutionReduction = 0; + +static int IrregularShadows = 0; + +static float CamPitch, CamYaw; +static vec3 CamPos; +static int ThirdPerson = 1; + +struct k3MScreen *UiActive; + +static double CurrentTime; +static double LastTime; + +#include"loaders.inc" + +void set_ui_mode(int yes) { + glfwSetInputMode(GameWnd, GLFW_CURSOR, yes ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED); +} + +static int is_ui_mode() { + return glfwGetInputMode(GameWnd, GLFW_CURSOR) == GLFW_CURSOR_NORMAL; +} + +static double xposold, yposold; +static void buttoncallback(GLFWwindow *GameWnd, int button, int action, int mods) { + if(button == GLFW_MOUSE_BUTTON_LEFT) { + if(UiActive) { + int ww, wh; + glfwGetWindowSize(GameWnd, &ww, &wh); + + struct k3MEvent ev = { + .original = (void*) UiActive, + .target = (void*) UiActive, + + .code = action == GLFW_PRESS ? k3M_EVENT_MOUSE_PRESS : k3M_EVENT_MOUSE_RELEASE, + .mouse = { + .button = k3M_MOUSE_BUTTON_0, + .x = xposold * UiActive->w / ww, + .y = (wh - yposold - 1) * UiActive->h / wh, + }, + }; + + k3MEventSend(&ev); + } + } + + if(!UiActive) { + luaapi_ctrlev(button, action == GLFW_PRESS ? 0 : (action == GLFW_RELEASE ? 2 : 1)); + } +} +static void motioncallback(GLFWwindow *GameWnd, double xpos, double ypos) { + static int first = 1; + if(!first && !is_ui_mode()) { + CamPitch -= (ypos - yposold) / 500.f; + CamYaw -= (xpos - xposold) / 500.f; + + if(CamPitch > 1.5393) { + CamPitch = 1.5393; + } else if(CamPitch < -1.5393) { + CamPitch = -1.5393; + } + } + xposold = xpos; + yposold = ypos; + first = 0; + + if(UiActive) { + int ww, wh; + glfwGetWindowSize(GameWnd, &ww, &wh); + + uint16_t uix = xposold * UiActive->w / ww; + uint16_t uiy = (wh - yposold - 1) * UiActive->h / wh; + + struct k3MEvent ev = { + .original = (void*) UiActive, + .target = (void*) UiActive, + + .code = k3M_EVENT_MOUSE_MOTION, + .mouse = { + .x = uix, + .y = uiy, + }, + }; + + k3MEventSend(&ev); + } +} + +static void keycallback(GLFWwindow *GameWnd, int key, int scancode, int action, int mods) { + if(action == GLFW_RELEASE && key == GLFW_KEY_ESCAPE) { + luaapi_escape(); + set_ui_mode(!!UiActive); + } else { + if(UiActive) { + struct k3MEvent ev = { + .original = (void*) UiActive, + .target = (void*) UiActive, + + .code = action == GLFW_PRESS ? k3M_EVENT_KEY_PRESS : k3M_EVENT_KEY_RELEASE, + .key = { + .num = key, + }, + }; + + k3MEventSend(&ev); + } + } + + luaapi_ctrlev(key, action == GLFW_PRESS ? 0 : (action == GLFW_RELEASE ? 2 : 1)); +} + +static void charcallback(GLFWwindow *window, unsigned int codepoint) { + if(UiActive) { + struct k3MEvent ev = { + .original = (void*) UiActive, + .target = (void*) UiActive, + + .code = k3M_EVENT_INPUT, + .input = { + .code = codepoint + }, + }; + + k3MEventSend(&ev); + } +} + +static void resizecallback(GLFWwindow *window, int width, int height) { + k3Resize(width, height); +} + +static int argc; +static char **argv; +const char *k4_get_arg(const char *name) { + for(int i = 1; i < argc; i++) { + if(strstr(argv[i], name) == argv[i] && strlen(argv[i]) > strlen(name) && argv[i][strlen(name)] == '=') { + return argv[i] + strlen(name) + 1; + } + } + return NULL; +} + +static void netwrap_step() { + if(NetWrap.stage && CurrentTime >= NetWrap.timeout) { + if(NetWrap.stage == 1) { + if(stoon_req(&NetWrap.stoon)) { + if(stoon_listen(&NetWrap.stoon)) { + uint8_t conndata[STOON_CONN_INFO_SIZE] = {}; + stoon_serialize(&NetWrap.stoon, conndata); + + char str[STOON_CONN_INFO_SIZE * 2 + 1] = {}; + for(int i = 0; i < sizeof(conndata); i++) { + snprintf(str + i * 2, 3, "%02x", conndata[i]); + } + + luaapi_peercode_found(str); + + //glfwSetClipboardString(NULL, str); + + //screenMain.lblpeerdata->invisible = 0; + //screenMain.btnconnect->invisible = 0; + + NetWrap.stage = 2; + } else { + k3Log(k3_INFO, "Stoon listen timeout."); + NetWrap.timeout = CurrentTime + 0.5; + } + } else { + k3Log(k3_INFO, "Stoon request failed."); + NetWrap.timeout = CurrentTime + 0.5; + } + } else if(NetWrap.stage == 2) { + stoon_keepalive(&NetWrap.stoon); + + NetWrap.timeout = CurrentTime + 1; + } else if(NetWrap.stage == 3) { + int status = stoon_poonch(&NetWrap.stoon, NetWrap.otherpeer); + + //screenMain.lblpeerdata->txt = strdup("Trying to connect...\nMay not work if both are\nbehind symmetric NATs."); + + if(status == STOON_POONCH_INCOMPATIBLE_NETFAMS) { + NetWrap.stage = 0; + + stoon_kill(&NetWrap.stoon); + + //screenMain.lblpeerdata->txt = strdup("Connection cannot be established:\nIncompatible netfams."); + } else if(status == STOON_POONCH_NO_KNOCK && NetWrap.stoon.poonchstage == POONCH_STAGE_ACK) { + if(NetWrap.gotten++ > 5) { + NetWrap.stage = 0; + stoon_kill(&NetWrap.stoon); + + if(NetWrap.isHost) { + net_server_init(); + } else { + char ip[64]; + int port; + if(*(uint16_t*) (NetWrap.otherpeer + 22) == 0) { + inet_ntop(AF_INET, NetWrap.otherpeer, ip, sizeof(ip)); + port = ntohs(*(uint16_t*) (NetWrap.otherpeer + 4)); + } else { + inet_ntop(AF_INET6, NetWrap.otherpeer + 6, ip, sizeof(ip)); + port = ntohs(*(uint16_t*) (NetWrap.otherpeer + 22)); + } + + printf("Trying [%s]:%u\n", ip, port); + + net_client_init(); + net_client_connect(ip, port); + } + + //screenMain.lblpeerdata->txt = strdup("Connection successful."); + } + } else NetWrap.gotten = 0; + + NetWrap.timeout = CurrentTime + 1; + } + } +} + +#include +void k4k3LogCallback(enum k3LogLevel lvl, const char *str, size_t len) { + static const char *prefixes[] = { + [k3_DEBUG] = "[\x1B[95mDEBUG\x1B[0m]", + [k3_INFO] = "[\x1B[97mINFO\x1B[0m] ", + [k3_WARN] = "[\x1B[93mWARN\x1B[0m] ", + [k3_ERR] = "[\x1B[91mERROR\x1B[0m]", + }; + + //if(lvl == k3_ERR) raise(SIGINT); + + fprintf(stderr, "%s : %s\n", prefixes[lvl], str); +} + +struct k4Control { + const char *name; + int btn; +} Controls[K4_MAX_CONTROLS]; + +static int eng_init() { + glfwInit(); + + glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE); + glfwWindowHint(GLFW_DOUBLEBUFFER, GL_TRUE); + glfwWindowHint(GLFW_SAMPLES, 4); + glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); + +#define START_WIDTH 960 +#define START_HEIGHT 540 +#define START_TITLE "k4" + + // Prefer core + if(!k4_get_arg("core") || strcmp(k4_get_arg("core"), "0")) { + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + GameWnd = glfwCreateWindow(START_WIDTH, START_HEIGHT, START_TITLE, NULL, NULL); + } + + if(!GameWnd) { + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_ANY_PROFILE); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); + GameWnd = glfwCreateWindow(START_WIDTH, START_HEIGHT, START_TITLE, NULL, NULL); + } + + k3MixInit(44100, 2); + k3MixPortAudio(); + + if(glfwRawMouseMotionSupported()) { + glfwSetInputMode(GameWnd, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); + } + + glfwSetMouseButtonCallback(GameWnd, buttoncallback); + glfwSetCursorPosCallback(GameWnd, motioncallback); + glfwSetKeyCallback(GameWnd, keycallback); + glfwSetCharCallback(GameWnd, charcallback); + glfwSetFramebufferSizeCallback(GameWnd, resizecallback); + + glfwMakeContextCurrent(GameWnd); + gladLoadGL(glfwGetProcAddress); + + if(k4_get_arg("shading") && strtol(k4_get_arg("shading"), NULL, 0) == 0) { + GLAD_GL_ARB_shading_language_100 = 0; + GLAD_GL_ARB_vertex_program = 0; + GLAD_GL_ARB_fragment_program = 0; + GLAD_GL_ARB_shader_objects = 0; + } + if(k4_get_arg("srgb") && strtol(k4_get_arg("srgb"), NULL, 0) == 0) { + // Just forget sRGB if the driver doesn't bother with GL_FRAMEBUFFER_SRGB + GLAD_GL_EXT_framebuffer_sRGB = 0; + GLAD_GL_EXT_texture_sRGB = 0; + } + if(k4_get_arg("fbo") && strtol(k4_get_arg("fbo"), NULL, 0) == 0) { + GLAD_GL_ARB_framebuffer_sRGB = 0; + GLAD_GL_EXT_framebuffer_object = 0; + } + + glfwSwapInterval(0); + + printf("GL version: %s\n", glGetString(GL_VERSION)); + printf("GL renderer: %s\n", glGetString(GL_RENDERER)); + printf("GL vendor: %s\n", glGetString(GL_VENDOR)); + + k3SetLogCallback(k4k3LogCallback); + k3Init(); + + k3BatchInit(); + + resizecallback(GameWnd, START_WIDTH, START_HEIGHT); + + enet_initialize(); + + init_res_handlers(); + + luaapi_init(); +} + +static int gr_lowres(int w, int h); + +static int ResolPercentage = 100; +static void fix_resol() { + int w, h; + glfwGetWindowSize(GameWnd, &w, &h); + + gr_lowres(roundf(w * ResolPercentage / 100.f / 4) * 4, roundf(h * ResolPercentage / 100.f / 4) * 4); +} + +static bool onqualitypress(struct k3MEvent *ev, uint8_t *ud) { + k3GraphicalReduction = (k3GraphicalReduction + 1) % 3; + return true; +} +static bool onresolpress(struct k3MEvent *ev, uint8_t *ud) { + struct k3MTextButton *btn = (void*) ev->target; + + ResolPercentage -= 10; + + if(ResolPercentage <= 0) { + ResolPercentage = 100; + } + + const char *txt = NULL; + + switch(ResolPercentage) { + case 10: + txt = "10%"; + break; + case 20: + txt = "20%"; + break; + case 30: + txt = "30%"; + break; + case 40: + txt = "40%"; + break; + case 50: + txt = "50%"; + break; + case 60: + txt = "60%"; + break; + case 70: + txt = "70%"; + break; + case 80: + txt = "80%"; + break; + case 90: + txt = "90%"; + break; + case 100: + txt = "Full Resolution"; + break; + } + + btn->txt = strdup(txt); + + fix_resol(); + + return true; +} +static bool ontexrespress(struct k3MEvent *ev, uint8_t *ud) { + TextureResolutionReduction = (TextureResolutionReduction + 1) % 3; + refresh_textures(); + + return true; +} +static bool onresumepress(struct k3MEvent *ev, uint8_t *ud) { + UiActive = NULL; + set_ui_mode(0); + + return true; +} +#ifdef LOCALHOST_ONLY +static bool onhostpress(struct k3MEvent *ev, uint8_t *ud) { + net_server_init(); + return true; +} +static bool onjoinpress(struct k3MEvent *ev, uint8_t *ud) { + net_client_init(); + net_client_connect("127.0.0.1", 26656); + return true; +} +static bool onconnectpress(struct k3MEvent *ev, uint8_t *ud) { + return true; +} +#else +static bool onhostpress(struct k3MEvent *ev, uint8_t *ud) { + screenMain.btnhost->disabled = 1; + screenMain.btnjoin->disabled = 1; + + NetWrap.stage = 1; + NetWrap.timeout = glfwGetTime() + 0; + NetWrap.isHost = 1; + NetWrap.stoon = stoon_init("stun.easybell.de", 3478, 26656); + + return true; +} +static bool onjoinpress(struct k3MEvent *ev, uint8_t *ud) { + screenMain.btnhost->disabled = 1; + screenMain.btnjoin->disabled = 1; + + NetWrap.stage = 1; + NetWrap.timeout = glfwGetTime() + 0; + NetWrap.isHost = 0; + NetWrap.stoon = stoon_init("stun.easybell.de", 3478, 26656); + + return true; +} +static bool onconnectpress(struct k3MEvent *ev, uint8_t *ud) { + const char *name = glfwGetClipboardString(NULL); + + while(isspace(*name)) name++; + + if(strlen(name) < STOON_CONN_INFO_SIZE * 2) { + goto bad; + } + + for(int i = 0; i < STOON_CONN_INFO_SIZE; i++) { + int b = 0; + + if(name[i * 2 + 0] >= '0' && name[i * 2 + 0] <= '9') { + b |= (name[i * 2 + 0] - '0') << 4; + } else if(name[i * 2 + 0] >= 'a' && name[i * 2 + 0] <= 'f') { + b |= (name[i * 2 + 0] - 'a' + 10) << 4; + } else goto bad; + + if(name[i * 2 + 1] >= '0' && name[i * 2 + 1] <= '9') { + b |= (name[i * 2 + 1] - '0') << 0; + } else if(name[i * 2 + 1] >= 'a' && name[i * 2 + 1] <= 'f') { + b |= (name[i * 2 + 1] - 'a' + 10) << 0; + } else goto bad; + + NetWrap.otherpeer[i] = b; + } + + NetWrap.stage = 3; + screenMain.btnconnect->disabled = 1; + + return true; + +bad: + screenMain.lblpeerdata->txt = strdup("Incorrect peer conndata."); + + return true; +} +#endif +static bool onconsoleenter(struct k3MEvent *ev, uint8_t *ud) { + return true; +} + +static void eng_ui_init() { + set_ui_mode(1); +} + +static void fps_counter_step(double newDT) { + static size_t lastDTidx = 0; + static double lastDTs[30] = {}; + + lastDTs[lastDTidx] = newDT; + lastDTidx = (lastDTidx + 1) % (sizeof(lastDTs) / sizeof(*lastDTs)); + + if(fmodf(CurrentTime, 1) < fmodf(LastTime, 1)) { + double dtSum = 0; + + for(int i = 0; i < sizeof(lastDTs) / sizeof(*lastDTs); i++) { + dtSum += lastDTs[i]; + } + + k3Log(k3_DEBUG, "fps=%05.03f", 1 / (dtSum / (sizeof(lastDTs) / sizeof(*lastDTs)))); + } +} + +static struct k3Tex *shadowmap; +static struct k3Offscreen *shadowmapOffscreen; + +static struct k3ARBFP *shadowmapDebugThing; + +static int gr_shadowmap_init() { + shadowmap = k3TexCreate(k3_DEPTH); + k3TexUpdate(shadowmap, k3_DEPTH, 0, k3TexSzMax() / 2, k3TexSzMax() / 2, NULL); + + shadowmapOffscreen = k3OffscreenCreate(NULL, shadowmap); + if(!shadowmapOffscreen) { + return 0; + } + + shadowmapDebugThing = k3ProgramARBFP( + "!!ARBfp1.0\n" + "TEMP col;\n" + "TEX col, fragment.texcoord, texture[0], 2D;\n" + "MAD col.xyz, -col, 29.9, 30.1;\n" + "RCP col.x, col.x;\n" + "RCP col.y, col.y;\n" + "RCP col.z, col.z;\n" + "MUL col.xyz, col, 0.2;\n" + "MOV result.color, col;\n" + "END\n" + ); + return 1; +} + +static struct k3Tex *bloomTex; +static struct k3Offscreen *bloomOffscr; +static int gr_bloom_init() { + if(!k3BloomInit()) { + return 0; + } + + bloomTex = k3TexCreate(k3_RAWCOLOR); + k3TexUpdate(bloomTex, k3_RAWCOLOR, 0, 1024, 512, NULL); + bloomOffscr = k3OffscreenCreate(bloomTex, NULL); + + return !!bloomOffscr; +} + +static struct k3Tex *lowres, *lowresDepth; +static struct k3Offscreen *lowresOffscreen; +static int gr_lowres(int newW, int newH) { + if(lowresOffscreen) { + k3OffscreenDestroy(lowresOffscreen); + lowresOffscreen = NULL; + } + + if(newW && newH) { + if(!lowres) { + lowres = k3TexCreate(k3_RAWCOLOR); + } + k3TexUpdate(lowres, k3_RAWCOLOR, 0, newW, newH, NULL); + + if(!lowresDepth) { + lowresDepth = k3TexCreate(k3_DEPTH); + } + k3TexUpdate(lowresDepth, k3_DEPTH, 0, newW, newH, NULL); + + lowresOffscreen = k3OffscreenCreate(lowres, lowresDepth); + } + + return !!lowresOffscreen; +} + +#define MAX_RAYS 64 +static struct LocalRay RaysToCast[MAX_RAYS]; +static size_t RaysToCastCount = 0; + +struct LocalRay *request_ray(struct LocalRay *lr) { + if(RaysToCastCount == MAX_RAYS) { + return NULL; + } + + memcpy(RaysToCast + RaysToCastCount, lr, sizeof(*lr)); + + return &RaysToCast[RaysToCastCount++]; +} + +int main(int argc_, char **argv_) { + argc = argc_; + argv = argv_; + + eng_init(); + eng_ui_init(); + + gr_shadowmap_init(); + gr_bloom_init(); + + if(k4_get_arg("res%")) { + ResolPercentage = strtod(k4_get_arg("res%"), NULL); + fix_resol(); + } + + IrregularShadows = 0; + if(k4_get_arg("irsh") && strcmp(k4_get_arg("irsh"), "0")) { + IrregularShadows = 1; + } + + // INIT LEVEL + game_init(); + luaapi_load(k4_get_arg("script") ? k4_get_arg("script") : "lvl1"); + // + + LuaapiStartTime = glfwGetTime(); + + LastTime = glfwGetTime(); + + double accumulator = 0; + + while(!glfwWindowShouldClose(GameWnd)) { + CurrentTime = glfwGetTime(); + double dt = CurrentTime - LastTime; + accumulator += dt; + + fps_counter_step(dt); + + LastTime = CurrentTime; + + glfwPollEvents(); + + netwrap_step(); + + float alpha = fmodf(accumulator * GAME_TPS, 1.f); + + vec3 cameraForwardDir = {0, 0, -1}; + glm_vec3_rotate(cameraForwardDir, CamPitch, (vec3) {1, 0, 0}); + glm_vec3_rotate(cameraForwardDir, CamYaw, (vec3) {0, 1, 0}); + + /* Control translation from keys to game logic */ + struct CPlayerCtrl *cc = Game.controlled == ENT_ID_INVALID ? NULL : game_ensurecomponent(Game.controlled, playerctrl); + if(cc && !is_ui_mode()) { + cc->yaw = CamYaw; + cc->pitch = CamPitch; + cc->keys = 0; + + for(int i = 0; i < K4_MAX_CONTROLS; i++) { + struct k4Control *k = &Controls[i]; + if(k->name) { + if((k->btn <= GLFW_MOUSE_BUTTON_LAST ? glfwGetMouseButton(GameWnd, k->btn) : glfwGetKey(GameWnd, k->btn)) == GLFW_PRESS) { + cc->keys |= 1 << i; + } + } + } + + // This is necessary so the host player would send its own pointing to clients + game_ensurecomponent(Game.controlled, movement)->pointing = cc->yaw; + } + + if(Game.isMultiplayer) { + if(Game.isAuthority) { + net_server_receive(); + } else { + net_client_receive(); + } + } + + game_raycast(RaysToCast, RaysToCastCount); + RaysToCastCount = 0; + + while(accumulator >= 1. / GAME_TPS) { + for(size_t i = 0; i < Game.entities.renderCount; i++) { + glm_vec4_copy(Game.entities.render[i].pos, Game.entities.render[i].posLast); + glm_quat_copy(Game.entities.render[i].rot, Game.entities.render[i].rotLast); + } + + if(Game.isMultiplayer && !Game.isAuthority) { + net_client_dejitter(); + net_client_update(); + } + + accumulator -= 1. / GAME_TPS; + + game_update(); + + luaapi_update(); + + if(Game.isMultiplayer && Game.isAuthority) { + net_server_update(); + } + } + + int width, height; + glfwGetFramebufferSize(GameWnd, &width, &height); + + mat4 proj; + glm_perspective(glm_rad(LuaapiFov), (float) width / height, 0.01f, 100.f, proj); + + /* Third-person camera movement */ + struct LocalRay camray; + if(Game.spectated != ENT_ID_INVALID) { + struct CRender *c = game_getcomponent(Game.spectated, render); + if(c) { + if(!LuaapiFirstPerson) { + glm_vec3_lerp(c->posLast, c->pos, alpha, camray.pos); + camray.pos[1] += 1.5; + + glm_vec3_negate_to(cameraForwardDir, camray.dir); + + camray.ignore = Game.spectated; + + camray.maxlen = 3; + camray.depth = 0; + + game_raycast(&camray, 1); + } + } + } + + mat4 cam; + if(LuaapiFirstPerson) { + struct CRender *c = game_getcomponent(Game.spectated, render); + + if(c) { + vec3 p; + glm_vec3_lerp(c->posLast, c->pos, alpha, p); + + mat4 view; + glm_look(p, cameraForwardDir, (vec3) {0, 1, 0}, view); + + glm_mat4_inv(view, cam); + } + } else if(camray.depth || LuaapiCamFocus) { + glm_mat4_identity(cam); + + vec3 almostThere; + + if(LuaapiCamFocus) { + glm_vec3_copy(LuaapiCamFocusPos, almostThere); + glm_vec3_lerp(CamPos, almostThere, 0.1, CamPos); + glm_look(CamPos, LuaapiCamFocusDir, (vec3) {0, 1, 0}, cam); + } else { + vec3 dirneg; + glm_vec3_negate_to(camray.dir, dirneg); + + glm_vec3_lerp(camray.pos, camray.out, 0.9, almostThere); + glm_vec3_lerp(CamPos, almostThere, 0.2, CamPos); + glm_look(CamPos, dirneg, (vec3) {0, 1, 0}, cam); + } + + glm_mat4_inv(cam, cam); + } + + glm_mat4_copy(cam, LuaapiCamMatrix); + + k3SetTime(glfwGetTime()); + + size_t lightCount; + struct k3Light *lights = luaapi_getlights(&lightCount); + + k3SetLights(lightCount, lights); + + luaapi_render(dt, alpha); + + for(size_t i = 0; i < Game.entities.renderCount; i++) { + struct CRender *c = &Game.entities.render[i]; + + versor interrot; + glm_quat_nlerp(c->rotLast, c->rot, alpha, interrot); + + vec4 interpos; + glm_vec4_lerp(c->posLast, c->pos, alpha, interpos); + + mat4 transform = {}; + glm_quat_mat4(interrot, transform); + glm_vec4_copy(interpos, (float*) transform[3]); + + if(c->cache) { + struct CBoned *b = game_getcomponent(c->entity, boned); + + k3Batch(c->cache, transform, b ? b->bones : NULL); + } + } + + if(!IrregularShadows) { + k3PassShadowmap(proj, cam, shadowmapOffscreen); + } + + if(lowresOffscreen) { + k3BeginOffscreen(lowresOffscreen); + } + + k3Clear(); + + if(LuaapiSkybox) { + mat4 rotation; + glm_quat_mat4(LuaapiSkyboxRotation, rotation); + + mat4 rotated; + glm_mat4_mul(rotation, cam, rotated); + + k3CubemapTraditional(LuaapiSkybox, proj, rotated); + } + + k3PassDepthOnly(proj, cam, true, true);// TRY COMMENTING THIS LINE + + if(IrregularShadows) { + k3PassIrregular(lowresOffscreen, proj, cam); + glEnable(GL_SCISSOR_TEST); + //glScissor(256, 0, 10000, 10000); + } + + k3PassForward(proj, cam); + + glDisable(GL_SCISSOR_TEST); + + k3BatchClear(); + + if(lowresOffscreen) { + k3EndOffscreen(lowresOffscreen); + + k3BlitToScreenEffect(lowresOffscreen, false, k3_GLSL, k3ToneMapper(), NULL); + + if(bloomOffscr) { + k3Bloom(lowresOffscreen, bloomOffscr); + } + } + + glClear(GL_DEPTH_BUFFER_BIT); + + if(!k3IsCore) { + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, 3600, 0, 2025, -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + } + + luaapi_render2d(); + + if(UiActive) { + struct k3MEvent ev = { + .original = UiActive, + .target = UiActive, + + .code = k3M_EVENT_DRAW, + }; + + k3MEventSend(&ev); + } + + k3BatchFlush(); + + // Shadowmap debugging + if(glfwGetKey(GameWnd, GLFW_KEY_F5) == GLFW_PRESS) { + k3BlitToScreen(shadowmapOffscreen, 0); + } + + glfwSwapBuffers(GameWnd); + } +} + +int k4_control_set(const char *name, int btn) { + for(int i = 0; i < K4_MAX_CONTROLS; i++) { + if(!Controls[i].name) { + + Controls[i].name = strdup(name); + Controls[i].btn = btn; + + return i; + } + } + return -1; +} + +int k4_control_get_id(int btn) { + for(int i = 0; i < K4_MAX_CONTROLS; i++) { + if(Controls[i].name && btn == Controls[i].btn) { + return i; + } + } + return -1; +} + +int k4_control_get_by_name(const char *name) { + for(int i = 0; i < K4_MAX_CONTROLS; i++) { + if(Controls[i].name && !strcmp(Controls[i].name, name)) { + return Controls[i].btn; + } + } + return -1; +} + +int k4_control_get_id_by_name(const char *name) { + for(int i = 0; i < K4_MAX_CONTROLS; i++) { + if(Controls[i].name && !strcmp(Controls[i].name, name)) { + return i; + } + } + return -1; +} + +const char *k4_control_get_name_by_ctrl(int btn) { + for(int i = 0; i < K4_MAX_CONTROLS; i++) { + if(Controls[i].name && Controls[i].btn == btn) { + return Controls[i].name; + } + } + return NULL; +} + +void k4_set_reduction(float f) { + ResolPercentage = f * 100; + fix_resol(); +} + +void k4_set_texture_reduction(int i) { + TextureResolutionReduction = i; + refresh_textures(); +} + +void k4_set_clipboard_text(const char *str) { + glfwSetClipboardString(GameWnd, str); +} + +const char *k4_get_clipboard_text() { + return glfwGetClipboardString(GameWnd); +} diff --git a/src/net.h b/src/net.h new file mode 100644 index 0000000..197a20e --- /dev/null +++ b/src/net.h @@ -0,0 +1,206 @@ +#pragma once + +// SC - server to client +// CS - client to server + +#include +#include + +#define PKT_PERFRAME (1<<15) + +#define CMD_SC_ASSIGN 0 +#define CMD_SC_SINGLE_COMPONENT 1 +#define CMD_SC_POSUPDATE 2 +#define CMD_SC_PING 3 +#define CMD_SC_LOAD_SCRIPT 4 +#define CMD_SC_MSG 5 + +#define CMD_CTYPE_PHYSICS 0 +#define CMD_CTYPE_RENDER 1 +#define CMD_CTYPE_MOVEMENT 2 +#define CMD_CTYPE_PLAYERCTRL 3 +#define CMD_CTYPE_BONED 3 + +#define PEER_DISCONNECT_TOO_MANY_PLAYERS 1 + +struct bstr { + uint32_t cap; + uint32_t wi; + uint32_t ri; + uint8_t *data; +}; + +static inline void bstr(struct bstr *dis, size_t cap) { + dis->cap = cap; + dis->wi = dis->ri = 0; + dis->data = malloc(dis->cap); +} + +static inline void bwrap(struct bstr *dis, uint8_t *data, size_t dataLength) { + dis->cap = dataLength; + dis->wi = dis->ri = 0; + dis->data = data; +} + +static inline void b_inc(struct bstr *b, uint32_t i) { + if(b->wi + i > b->cap) { + b->data = realloc(b->data, b->cap = ((b->cap + i + 63) & ~63)); + } +} + +static inline void b_wf32(struct bstr *b, float f) { + b_inc(b, sizeof(f)); + memcpy(b->data + b->wi, &f, sizeof(f)); + b->wi += sizeof(f); +} + +static inline void b_wf64(struct bstr *b, double f) { + b_inc(b, sizeof(f)); + memcpy(b->data + b->wi, &f, sizeof(f)); + b->wi += sizeof(f); +} + +static inline void b_wu8(struct bstr *b, uint8_t i) { + b_inc(b, sizeof(i)); + b->data[b->wi] = i; + b->wi += sizeof(i); +} + +static inline void b_wu16(struct bstr *b, uint16_t i) { + b_inc(b, sizeof(i)); + memcpy(b->data + b->wi, &i, sizeof(i)); + b->wi += sizeof(i); +} + +static inline void b_wu32(struct bstr *b, uint32_t i) { + b_inc(b, sizeof(i)); + memcpy(b->data + b->wi, &i, sizeof(i)); + b->wi += sizeof(i); +} + +static inline void b_wu64(struct bstr *b, uint64_t i) { + b_inc(b, sizeof(i)); + memcpy(b->data + b->wi, &i, sizeof(i)); + b->wi += sizeof(i); +} + +static inline void b_wf16(struct bstr *b, float f) { + uint32_t I = *(uint32_t*) &f; + + uint16_t i = (I >> 16) & 0x8000; + int32_t mant = I & 0x7FFFFF; + uint16_t exp = (I >> 23) & 0xFF; + + if(exp == 0xFF) { + i |= mant ? 0x7E00 : 0x7C00; + } else if(exp >= 0x8F) { + i |= 0x7C00; + } else if(exp >= 0x71) { + i |= ((exp - 0x70) << 10) | (mant >> 13); + } else if(exp >= 0x67) { + i |= (mant | 0x800000) >> (0x7E - exp); + } + + b_wu16(b, i); +} + +// TODO: implement varints +static inline void b_wvu(struct bstr *b, size_t i) { +} + +static inline void b_wzstr(struct bstr *b, const char *str) { + size_t l = strlen(str); + b_inc(b, l + 1); + strcpy((char*) b->data + b->wi, str); + b->wi += l; + b->data[b->wi++] = 0; +} + +static inline void b_wraw(struct bstr *b, const uint8_t *data, size_t len) { + b_inc(b, len); + memcpy(b->data + b->wi, data, len); + b->wi += len; +} + +static inline float b_rf32(struct bstr *b) { + float ret; + memcpy(&ret, b->data + b->ri, sizeof(ret)); + b->ri += sizeof(ret); + return ret; +} + +static inline float b_rf64(struct bstr *b) { + double ret; + memcpy(&ret, b->data + b->ri, sizeof(ret)); + b->ri += sizeof(ret); + return ret; +} + +static inline uint16_t b_ru8(struct bstr *b) { + uint8_t ret; + memcpy(&ret, b->data + b->ri, sizeof(ret)); + b->ri += sizeof(ret); + return ret; +} + +static inline uint16_t b_ru16(struct bstr *b) { + uint16_t ret; + memcpy(&ret, b->data + b->ri, sizeof(ret)); + b->ri += sizeof(ret); + return ret; +} + +static inline uint16_t b_ru32(struct bstr *b) { + uint32_t ret; + memcpy(&ret, b->data + b->ri, sizeof(ret)); + b->ri += sizeof(ret); + return ret; +} + +static inline uint16_t b_ru64(struct bstr *b) { + uint64_t ret; + memcpy(&ret, b->data + b->ri, sizeof(ret)); + b->ri += sizeof(ret); + return ret; +} + +static inline float b_rf16(struct bstr *b) { + uint16_t i = b_ru16(b); + + uint32_t I = (i & 0x8000) << 16; + uint32_t mant = i & 0x3FF; + uint32_t exp = (i & 0x7C00) >> 10; + if(exp == 0x1F) { + I |= mant ? 0x7FC00000 : 0x7F800000; + } else if(exp > 0) { + I |= (exp + 0x70) << 23; + if(mant) { + I |= mant << 13; + } + } else if(mant) { + for(int j = 9; j >= 0; j--) { + if(mant & (1 << j)) { + I |= ((0x67 + j) << 23) | ((mant << (23 - j)) & 0x7FFFFF); + break; + } + } + } + + return *(float*) &I; +} + +static inline const char *b_rzstr(struct bstr *b) { + const char *ret = (char*) b->data + b->ri; + b->ri += strlen(ret) + 1; + return ret; +} + +static inline const uint8_t *b_rraw(struct bstr *b, size_t len) { + const uint8_t *ret = b->data + b->ri; + b->ri += len; + return ret; +} + +static inline void b_rraw_copy(struct bstr *b, uint8_t *data, size_t len) { + memcpy(data, b_rraw(b, len), len); +} diff --git a/src/net_client.c b/src/net_client.c new file mode 100644 index 0000000..0417165 --- /dev/null +++ b/src/net_client.c @@ -0,0 +1,287 @@ +#include"net_server.h" + +#include"enet.h" +#include +#include"luaapi.h" +#include"net.h" +#include"game.h" +#include"resman.h" +#include + +static ENetHost *host; +static ENetPeer *peer; + +static uint16_t serverTick; + +#define RECONBUFSZ 64 +static size_t stateUpdateLastClientTick; +static ENetPacket *stateUpdates[RECONBUFSZ]; +static struct CPlayerCtrl myInputs[RECONBUFSZ]; +static int dejitterLeft = 0; + +void net_client_init() { + host = enet_host_create(NULL, 1, 1, 0, 0); + + Game.isMultiplayer = 1; + Game.isAuthority = 0; +} + +void net_client_connect(const char *addr, uint16_t port) { + ENetAddress eaddr; + enet_address_set_host(&eaddr, addr); + eaddr.port = port; + + peer = enet_host_connect(host, &eaddr, 1, 0); +} + +extern double glfwGetTime(); + +static void interpret_pkt(ENetPacket *pkt) { + struct bstr b; + bwrap(&b, pkt->data, pkt->dataLength); + + uint16_t cmdCount = b_ru16(&b) & ~PKT_PERFRAME; + uint16_t t = b_ru16(&b); + + for(size_t i = 0; i < cmdCount; i++) { + uint16_t cmd = b_ru16(&b); + if(cmd == CMD_SC_ASSIGN) { + Game.spectated = Game.controlled = b_ru16(&b); + } else if(cmd == CMD_SC_SINGLE_COMPONENT) { + uint8_t ctype = b_ru8(&b); + + uint16_t ent = b_ru16(&b); + + if(ctype == CMD_CTYPE_RENDER) { + struct CRender *c = game_ensurecomponent(ent, render); + const char *mdl = b_rzstr(&b); + if(strncmp(c->mdl, mdl, MODELNAME_LENGTH)) { + if(strlen(c->mdl)) { + resman_unref(RESMAN_MODEL, c->mdl); + c->cache = NULL; + } + memcpy(c->mdl, mdl, MODELNAME_LENGTH); + } + } else if(ctype == CMD_CTYPE_PHYSICS) { + struct CPhysics *c = game_ensurecomponent(ent, physics); + c->trigger = b_ru16(&b); + c->type = b_ru8(&b); + c->dynamics = b_ru8(&b); + if(c->type == CPHYSICS_BOX) { + c->box.w = b_rf32(&b); + c->box.h = b_rf32(&b); + c->box.l = b_rf32(&b); + } else if(c->type == CPHYSICS_CAPSULE) { + c->capsule.length = b_rf32(&b); + c->capsule.radius = b_rf32(&b); + } else abort(); + + c->start[0] = b_rf32(&b); + c->start[1] = b_rf32(&b); + c->start[2] = b_rf32(&b); + + if((c->dynamics & ~CPHYSICS_GHOST) == CPHYSICS_DYNAMIC) { + c->vel[0] = b_rf32(&b); + c->vel[1] = b_rf32(&b); + c->vel[2] = b_rf32(&b); + + c->speed = b_rf32(&b); + } + + c->mass = b_rf32(&b); + c->friction = b_rf32(&b); + c->collide = b_ru32(&b); + + if(c->geom) { + dGeomSetPosition(c->geom, c->start[0], c->start[1], c->start[2]); + + if((c->dynamics & ~CPHYSICS_GHOST) == CPHYSICS_DYNAMIC) { + dBodySetLinearVel(dGeomGetBody(c->geom), c->vel[0], c->vel[1], c->vel[2]); + } + } + } else if(ctype == CMD_CTYPE_MOVEMENT) { + struct CMovement *c = game_ensurecomponent(ent, movement); + c->dir[0] = b_rf32(&b); + c->dir[1] = b_rf32(&b); + c->dir[2] = b_rf32(&b); + c->pointing = b_rf32(&b); + c->jump = b_ru8(&b); + c->canJump = b_ru8(&b); + c->holding = b_ru16(&b); + } if(ctype == CMD_CTYPE_BONED) { + struct CBoned *c = game_ensurecomponent(ent, boned); + c->anim.standard = b_ru8(&b); + } + } else if(cmd == CMD_SC_POSUPDATE) { + uint16_t lastOurTick = b_ru16(&b); + + stateUpdateLastClientTick = stateUpdateLastClientTick < lastOurTick ? lastOurTick : stateUpdateLastClientTick + 1; + + uint16_t conveyorCount = b_ru16(&b); + if(conveyorCount > Game.conveyorCount) conveyorCount = Game.conveyorCount; + for(size_t i = 0; i < conveyorCount; i++) { + struct Conveyor *conveyor = Game.conveyors[i]; + conveyor->position = b_rf16(&b); + } + + for(size_t i = 0; i < Game.entities.physicsCount; i++) { + vec3 p = {b_rf16(&b), b_rf16(&b), b_rf16(&b)}; + if(Game.entities.physics[i].geom) { + dGeomSetPosition(Game.entities.physics[i].geom, p[0], p[1], p[2]); + } else { + glm_vec3_copy(p, Game.entities.physics[i].start); + } + + if((Game.entities.physics[i].dynamics & ~CPHYSICS_GHOST) == CPHYSICS_DYNAMIC) { + vec3 v = {b_rf16(&b), b_rf16(&b), b_rf16(&b)}; + + if(Game.entities.physics[i].geom) { + dBodyID bid = dGeomGetBody(Game.entities.physics[i].geom); + dBodySetLinearVel(bid, v[0], v[1], v[2]); + } else { + glm_vec3_copy(v, Game.entities.physics[i].vel); + } + + struct CMovement *cm = game_getcomponent(Game.entities.physics[i].entity, movement); + if(cm) { + glm_vec3_normalize_to(v, cm->dir); + } + + if(Game.entities.physics[i].geom) { + vec4 r = {0, b_rf16(&b), b_rf16(&b), b_rf16(&b)}; + r[0] = b_rf16(&b); + + dGeomSetQuaternion(Game.entities.physics[i].geom, (float*) r); + } else { + Game.entities.physics[i].rot[0] = b_rf16(&b); + Game.entities.physics[i].rot[1] = b_rf16(&b); + Game.entities.physics[i].rot[2] = b_rf16(&b); + Game.entities.physics[i].rot[3] = b_rf16(&b); + } + } + } + + for(size_t i = 0; i < Game.entities.movementCount; i++) { + Game.entities.movement[i].pointing = b_rf16(&b); + } + + if(Game.reconciliate) { + // printf("Recon %lu -> %lu\n", stateUpdateLastClientTick, Game.frame); + if(Game.frame - stateUpdateLastClientTick < RECONBUFSZ) { + size_t properFrame = Game.frame; + + struct CPlayerCtrl *cc = &myInputs[Game.frame - stateUpdateLastClientTick]; + struct CPlayerCtrl *w = game_getcomponent(Game.controlled, playerctrl); + size_t keys = w ? w->keys : 0; + // printf("Currently %X\n", keys); + for(; cc > myInputs + 1; cc--) { + w = game_getcomponent(Game.controlled, playerctrl); + if(w) w->keys = cc->keys; + // printf("pred %X\n", cc->keys); + + game_update(); + } + + w = game_getcomponent(Game.controlled, playerctrl); + if(w) w->keys = keys; + + Game.frame = properFrame; + } + } + } else if(cmd == CMD_SC_LOAD_SCRIPT) { + luaapi_load(b_rzstr(&b)); + } else if(cmd == CMD_SC_MSG) { + if(!luaapi_recvmsg(&b, -2)) { + // Corrupted packet. + break; + } + } + } +} + +void net_client_receive() { + ENetEvent ev; + while(enet_host_service(host, &ev, 0) > 0) { + if(ev.type == ENET_EVENT_TYPE_CONNECT) { + luaapi_cleanup(); + } else if(ev.type == ENET_EVENT_TYPE_RECEIVE) { + struct bstr b; + bwrap(&b, ev.packet->data, ev.packet->dataLength); + + uint16_t cmdCount = b_ru16(&b); + int perframe = cmdCount & PKT_PERFRAME; + cmdCount &= ~PKT_PERFRAME; + + uint16_t t = b_ru16(&b); + + if(perframe) { + if(stateUpdates[RECONBUFSZ - 1]) { + enet_packet_destroy(stateUpdates[RECONBUFSZ - 1]); + } + memmove(stateUpdates + 1, stateUpdates, sizeof(*stateUpdates) * (RECONBUFSZ - 1)); + stateUpdates[0] = ev.packet; + + dejitterLeft++; + if(dejitterLeft > RECONBUFSZ) dejitterLeft = RECONBUFSZ; + } else { + interpret_pkt(ev.packet); + enet_packet_destroy(ev.packet); + } + } + } +} + +void net_client_dejitter() { + if(dejitterLeft) { + interpret_pkt(stateUpdates[--dejitterLeft]); + } +} + +void net_client_update() { + struct CPlayerCtrl *cc = game_getcomponent(Game.controlled, playerctrl); + + memmove(myInputs + 1, myInputs, sizeof(*myInputs) * (RECONBUFSZ - 1)); + + if(cc) { + memcpy(myInputs, cc, sizeof(*cc)); + + struct bstr b; + bstr(&b, 64); + + b_wu16(&b, 1); + b_wu16(&b, Game.frame); + + b_wu16(&b, CMD_SC_SINGLE_COMPONENT); + b_wu8(&b, CMD_CTYPE_PLAYERCTRL); + + b_wu16(&b, Game.controlled); + + b_wf32(&b, cc->yaw); + b_wf32(&b, cc->pitch); + b_wu32(&b, cc->keys); + + enet_peer_send(peer, 0, enet_packet_create(b.data, b.wi, ENET_PACKET_FLAG_RELIABLE)); + free(b.data); + + enet_host_flush(host); + } else { + memset(myInputs, 0, sizeof(*cc)); + } +} + +void net_client_send_msg(struct bstr *data) { + struct bstr b; + bstr(&b, 64); + + b_wu16(&b, 1); + b_wu16(&b, Game.frame); + + b_wu16(&b, CMD_SC_MSG); + b_wraw(&b, data->data, data->wi); + + enet_peer_send(peer, 0, enet_packet_create(b.data, b.wi, ENET_PACKET_FLAG_RELIABLE)); + + free(b.data); + + enet_host_flush(host); +} diff --git a/src/net_client.h b/src/net_client.h new file mode 100644 index 0000000..1c81f90 --- /dev/null +++ b/src/net_client.h @@ -0,0 +1,8 @@ +#pragma once + +void net_client_init(); +void net_client_connect(const char *addr, uint16_t port); +void net_client_receive(); +void net_client_update(); +void net_client_dejitter(); +void net_client_send_msg(struct bstr *data); diff --git a/src/net_server.c b/src/net_server.c new file mode 100644 index 0000000..b0c01d3 --- /dev/null +++ b/src/net_server.c @@ -0,0 +1,344 @@ +#include"net_server.h" + +#include"enet.h" +#include +#include"luaapi.h" +#include"net.h" +#include"game.h" + +static ENetHost *host; + +struct Conn { + ENetPeer *e; + uint16_t lastTick; + uint16_t assigned; + int lua; +}; + +#define MAX_PLAYERS 64 +static struct Conn conns[MAX_PLAYERS]; + +void net_server_init() { + host = enet_host_create(&(ENetAddress) {.host = ENET_HOST_ANY, .port = 26656}, 16, 1, 0, 0); + + Game.isMultiplayer = 1; + Game.isAuthority = 1; + + memset(conns, 0, sizeof(conns)); +} + +static void send_full_state(ENetPeer **peers, size_t peerCount) { + struct bstr b; + bstr(&b, 1024); + + b_wu16(&b, Game.entities.physicsCount + Game.entities.renderCount + Game.entities.movementCount + Game.entities.bonedCount); + b_wu16(&b, Game.frame); + + for(size_t i = 0; i < Game.entities.physicsCount; i++) { + b_wu16(&b, CMD_SC_SINGLE_COMPONENT); + b_wu8(&b, CMD_CTYPE_PHYSICS); + + struct CPhysics *c = Game.entities.physics + i; + + b_wu16(&b, c->entity); + + b_wu16(&b, c->trigger); + b_wu8(&b, c->type); + b_wu8(&b, c->dynamics); + if(c->type == CPHYSICS_BOX) { + b_wf32(&b, c->box.w); + b_wf32(&b, c->box.h); + b_wf32(&b, c->box.l); + } else if(c->type == CPHYSICS_CAPSULE) { + b_wf32(&b, c->capsule.length); + b_wf32(&b, c->capsule.radius); + } else abort(); + + if(c->geom) { + const float *p = dGeomGetPosition(c->geom); + b_wf32(&b, p[0]); + b_wf32(&b, p[1]); + b_wf32(&b, p[2]); + } else { + b_wf32(&b, c->start[0]); + b_wf32(&b, c->start[1]); + b_wf32(&b, c->start[2]); + } + + if((c->dynamics & ~CPHYSICS_GHOST) == CPHYSICS_DYNAMIC) { + if(c->geom) { + const float *p = dBodyGetLinearVel(dGeomGetBody(c->geom)); + b_wf32(&b, p[0]); + b_wf32(&b, p[1]); + b_wf32(&b, p[2]); + } else { + b_wf32(&b, c->vel[0]); + b_wf32(&b, c->vel[1]); + b_wf32(&b, c->vel[2]); + } + + b_wf32(&b, c->speed); + } + + b_wf32(&b, c->mass); + b_wf32(&b, c->friction); + b_wu32(&b, c->collide); + } + + for(size_t i = 0; i < Game.entities.renderCount; i++) { + b_wu16(&b, CMD_SC_SINGLE_COMPONENT); + b_wu8(&b, CMD_CTYPE_RENDER); + + struct CRender *c = Game.entities.render + i; + + b_wu16(&b, c->entity); + + b_wzstr(&b, c->mdl); + } + + for(size_t i = 0; i < Game.entities.movementCount; i++) { + b_wu16(&b, CMD_SC_SINGLE_COMPONENT); + b_wu8(&b, CMD_CTYPE_MOVEMENT); + + struct CMovement *c = Game.entities.movement + i; + + b_wu16(&b, c->entity); + + b_wf32(&b, c->dir[0]); + b_wf32(&b, c->dir[1]); + b_wf32(&b, c->dir[2]); + b_wf32(&b, c->pointing); + b_wu8(&b, c->jump); + b_wu8(&b, c->canJump); + b_wu16(&b, c->holding); + } + + for(size_t i = 0; i < Game.entities.bonedCount; i++) { + b_wu16(&b, CMD_SC_SINGLE_COMPONENT); + b_wu8(&b, CMD_CTYPE_BONED); + + struct CBoned *c = Game.entities.boned + i; + + b_wu16(&b, c->entity); + + b_wu8(&b, c->anim.standard); + } + + if(peers) { + for(size_t i = 0; i < peerCount; i++) { + enet_peer_send(peers[i], 0, enet_packet_create(b.data, b.wi, ENET_PACKET_FLAG_RELIABLE)); + } + } else { + enet_host_broadcast(host, 0, enet_packet_create(b.data, b.wi, ENET_PACKET_FLAG_RELIABLE)); + } + + free(b.data); +} + +static void pos_update() { + struct bstr b; + bstr(&b, 512); + + b_wu16(&b, PKT_PERFRAME | 1); + b_wu16(&b, Game.frame); + + b_wu16(&b, CMD_SC_POSUPDATE); + + b_wu16(&b, 0); // WARNING: THIS INDEX IS EDITED BELOW + + b_wu16(&b, Game.conveyorCount); + for(size_t i = 0; i < Game.conveyorCount; i++) { + b_wf16(&b, Game.conveyors[i]->position); + } + + for(size_t i = 0; i < Game.entities.physicsCount; i++) { + if(Game.entities.physics[i].geom) { + const float *p = dGeomGetPosition(Game.entities.physics[i].geom); + b_wf16(&b, p[0]); + b_wf16(&b, p[1]); + b_wf16(&b, p[2]); + if((Game.entities.physics[i].dynamics & ~CPHYSICS_GHOST) == CPHYSICS_DYNAMIC) { + dBodyID bid = dGeomGetBody(Game.entities.physics[i].geom); + p = dBodyGetLinearVel(bid); + b_wf16(&b, p[0]); + b_wf16(&b, p[1]); + b_wf16(&b, p[2]); + p = dBodyGetQuaternion(bid); + b_wf16(&b, p[1]); + b_wf16(&b, p[2]); + b_wf16(&b, p[3]); + b_wf16(&b, p[0]); + } + } else { + b_wf16(&b, Game.entities.physics[i].start[0]); + b_wf16(&b, Game.entities.physics[i].start[1]); + b_wf16(&b, Game.entities.physics[i].start[2]); + if((Game.entities.physics[i].dynamics & ~CPHYSICS_GHOST) == CPHYSICS_DYNAMIC) { + b_wf16(&b, 0); + b_wf16(&b, 0); + b_wf16(&b, 0); + + b_wf16(&b, 0); + b_wf16(&b, 0); + b_wf16(&b, 0); + b_wf16(&b, 1); + } + } + } + + for(size_t i = 0; i < Game.entities.movementCount; i++) { + b_wf16(&b, Game.entities.movement[i].pointing); + } + + for(struct Conn *c = conns; c != conns + MAX_PLAYERS; c++) { + if(c->e) { + *((uint16_t*) &b.data[6]) = c->lastTick; + + enet_peer_send(c->e, 0, enet_packet_create(b.data, b.wi, 0)); + } + } + + free(b.data); +} + +void net_server_receive() { + ENetEvent ev; + while(enet_host_service(host, &ev, 0) > 0) { + if(ev.type == ENET_EVENT_TYPE_CONNECT) { + puts("Connect!"); + + size_t i; + for(i = 0; i < MAX_PLAYERS; i++) { + if(conns[i].e == NULL) { + break; + } + } + + if(i == MAX_PLAYERS) { + enet_peer_disconnect(ev.peer, PEER_DISCONNECT_TOO_MANY_PLAYERS); + } else { + conns[i] = (struct Conn) { + .e = ev.peer, + .lastTick = 0, + .assigned = ENT_ID_INVALID, + }; + + ev.peer->data = conns + i; + + conns[i].lua = luaapi_join(ev.peer, 0); + + game_synccphysics(); + send_full_state(&ev.peer, 1); + } + } else if(ev.type == ENET_EVENT_TYPE_RECEIVE) { + struct bstr b; + bwrap(&b, ev.packet->data, ev.packet->dataLength); + + uint16_t cmdCount = b_ru16(&b) & ~PKT_PERFRAME; + uint16_t t = b_ru16(&b); + + ((struct Conn*) ev.peer->data)->lastTick = t; + + for(size_t i = 0; i < cmdCount; i++) { + uint16_t cmd = b_ru16(&b); + if(cmd == CMD_SC_SINGLE_COMPONENT) { + uint8_t ctype = b_ru8(&b); + + uint16_t ent = b_ru16(&b); + + if(ctype == CMD_CTYPE_PLAYERCTRL) { + struct CPlayerCtrl *c = game_ensurecomponent(ent, playerctrl); + c->yaw = b_rf32(&b); + c->pitch = b_rf32(&b); + c->keys = b_ru32(&b); + + game_ensurecomponent(ent, movement)->pointing = c->yaw; + } + } else if(cmd == CMD_SC_MSG) { + if(!luaapi_recvmsg(&b, ((struct Conn*) ev.peer->data)->lua)) { + // Corrupted packet. + break; + } + } + } + + enet_packet_destroy(ev.packet); + } else if(ev.type == ENET_EVENT_TYPE_DISCONNECT) { + struct Conn *conn = ev.peer->data; + + luaapi_leave(conn->lua); + conn->e = NULL; + } + } +} + +void net_server_update() { + pos_update(); + enet_host_flush(host); +} + +void net_server_assign(ENetPeer *peer, uint16_t idx) { + struct bstr b; + bstr(&b, 64); + + b_wu16(&b, 1); + b_wu16(&b, Game.frame); + + b_wu16(&b, CMD_SC_ASSIGN); + b_wu16(&b, idx); + + enet_peer_send(peer, 0, enet_packet_create(b.data, b.wi, ENET_PACKET_FLAG_RELIABLE)); + + free(b.data); + + ((struct Conn*) peer->data)->assigned = idx; +} + +void net_server_force_load(ENetPeer *peer, const char *script) { + struct bstr b; + bstr(&b, 64); + + b_wu16(&b, 1); + b_wu16(&b, Game.frame); + + b_wu16(&b, CMD_SC_LOAD_SCRIPT); + b_wzstr(&b, script); + + enet_peer_send(peer, 0, enet_packet_create(b.data, b.wi, ENET_PACKET_FLAG_RELIABLE)); + + free(b.data); +} + +void net_server_send_msg(ENetPeer *peer, struct bstr *data) { + struct bstr b; + bstr(&b, 64); + + b_wu16(&b, 1); + b_wu16(&b, Game.frame); + + b_wu16(&b, CMD_SC_MSG); + b_wraw(&b, data->data, data->wi); + + enet_peer_send(peer, 0, enet_packet_create(b.data, b.wi, ENET_PACKET_FLAG_RELIABLE)); + + free(b.data); +} + +void net_server_broadcast_msg(struct bstr *data) { + struct bstr b; + bstr(&b, 64); + + b_wu16(&b, 1); + b_wu16(&b, Game.frame); + + b_wu16(&b, CMD_SC_MSG); + b_wraw(&b, data->data, data->wi); + + for(size_t i = 0; i < MAX_PLAYERS; i++) { + if(conns[i].e) { + enet_peer_send(conns[i].e, 0, enet_packet_create(b.data, b.wi, ENET_PACKET_FLAG_RELIABLE)); + } + } + + free(b.data); +} diff --git a/src/net_server.h b/src/net_server.h new file mode 100644 index 0000000..a8b875c --- /dev/null +++ b/src/net_server.h @@ -0,0 +1,16 @@ +#pragma once + +#include + +struct _ENetPeer; +struct bstr; + +void net_server_init(); +void net_server_receive(); +void net_server_update(); + +void net_server_assign(struct _ENetPeer *peer, uint16_t idx); +void net_server_force_load(struct _ENetPeer *peer, const char *script); + +void net_server_send_msg(struct _ENetPeer *peer, struct bstr *data); +void net_server_broadcast_msg(struct bstr *data); diff --git a/src/resman.c b/src/resman.c new file mode 100644 index 0000000..4737395 --- /dev/null +++ b/src/resman.c @@ -0,0 +1,160 @@ +#include"resman.h" + +#include +#include +#include +#include"k3.h" + +struct ResMan ResMan; + +static uint64_t fnv1a(const char *str) { + uint64_t ret = 14695981039346656037ULL; + + while(*str) { + ret ^= *(const uint8_t*) str; + ret *= 1099511628211ULL; + + str++; + } + + return ret; +} + +static struct ResManRes *make(enum ResManType type, const char *name, size_t refs) { + struct ResManRes *ret = malloc(sizeof(*ret)); + ret->type = type; + ret->name = strdup(name); + ret->refs = refs; + ret->next = NULL; + ret->thing = NULL; + + if(type != RESMAN_OTHER) { + k3Log(k3_INFO, "Loading %s...", name); + if(!ResMan.handlers[type].loader(ResMan.handlers[type].ud, ret)) { + printf("Failed to load resource %s (%i)\n", name, type); + } + } + + return ret; +} + +struct ResManRes *resman_reffull(enum ResManType type, const char *name) { + size_t bucket = fnv1a(name) % RESMAN_BUCKETS; + + struct ResManRes *ptr = ResMan.buckets[bucket]; + + if(!ptr) { + return (ResMan.buckets[bucket] = make(type, name, 1)); + } + + struct ResManRes *prev = NULL; + while(ptr) { + if(ptr->type == type && !strcmp(name, ptr->name)) { + ptr->refs++; + return ptr; + } + + prev = ptr; + ptr = ptr->next; + } + + return (prev->next = make(type, name, 1)); +} + +void *resman_ref(enum ResManType type, const char *name) { + return resman_reffull(type, name)->thing; +} + +void resman_unref(enum ResManType type, const char *name) { + size_t bucket = fnv1a(name) % RESMAN_BUCKETS; + + struct ResManRes *prev = NULL; + struct ResManRes *ptr = ResMan.buckets[bucket]; + + if(!ptr) goto notfound; + + while(ptr) { + if(ptr->type == type && !strcmp(name, ptr->name)) { + ptr->refs--; + if(ptr->refs == 0) { + if(ResMan.handlers[type].unloader) { + ResMan.handlers[type].unloader(ResMan.handlers[type].ud, name, ptr->thing); + } else { + printf("Memory leak! No unloader for (%i)!\n", type); + } + + if(prev) { + prev->next = ptr->next; + } else { + ResMan.buckets[bucket] = ptr->next; + } + + free(ptr->name); + free(ptr); + } + + return; + } + + prev = ptr; + ptr = ptr->next; + } + +notfound: + printf("Attempt to release unallocated resource %s (%i)!\n", name, type); +} + +void resman_unref_ptr(enum ResManType type, void *v) { + for(size_t bucket = 0; bucket < RESMAN_BUCKETS; bucket++) { + struct ResManRes *prev = NULL; + struct ResManRes *ptr = ResMan.buckets[bucket]; + + while(ptr) { + if(ptr->thing == v) { + ptr->refs--; + if(ptr->refs == 0) { + if(ResMan.handlers[type].unloader) { + ResMan.handlers[type].unloader(ResMan.handlers[type].ud, ptr->name, ptr->thing); + } else { + printf("Memory leak! No unloader for (%i)!\n", type); + } + + if(prev) { + prev->next = ptr->next; + } else { + ResMan.buckets[bucket] = ptr->next; + } + + free(ptr->name); + free(ptr); + } + + return; + } + + prev = ptr; + ptr = ptr->next; + } + } + +notfound: + printf("Attempt to release unnamed unallocated resource (%i)!\n", type); +} + +struct ResManRes *resman_rev(void *v) { + for(size_t bucket = 0; bucket < RESMAN_BUCKETS; bucket++) { + struct ResManRes *prev = NULL; + struct ResManRes *ptr = ResMan.buckets[bucket]; + + while(ptr) { + if(ptr->thing == v) { + return ptr; + } + + prev = ptr; + ptr = ptr->next; + } + } + + return NULL; +} diff --git a/src/resman.h b/src/resman.h new file mode 100644 index 0000000..5e034c8 --- /dev/null +++ b/src/resman.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include + +enum ResManType { + RESMAN_MODEL, RESMAN_MATERIAL, RESMAN_TEXTURE, RESMAN_PHYSICS, RESMAN_BIN, RESMAN_STREAM, RESMAN_FONT, RESMAN_OTHER, RESMAN_MAX +}; + +struct ResManRes { + enum ResManType type; + char *name; + void *thing; + size_t refs; + + struct ResManRes *next; +}; + +struct ResManBin { + size_t length; + uint8_t data[]; +}; + +typedef int(*ResManLoader)(void *ud, struct ResManRes*); +typedef void(*ResManUnloader)(void *ud, const char *name, void *data); + +struct ResManHandler { + ResManLoader loader; + ResManUnloader unloader; + void *ud; +}; + +#define RESMAN_BUCKETS 32 +extern struct ResMan { + struct ResManHandler handlers[RESMAN_MAX]; + struct ResManRes *buckets[RESMAN_BUCKETS]; +} ResMan; + +struct ResManRes *resman_reffull(enum ResManType, const char*); +void *resman_ref(enum ResManType, const char*); +void resman_unref(enum ResManType, const char*); +void resman_unref_ptr(enum ResManType, void*); + +struct ResManRes resman_find(const char*); + +struct ResManRes *resman_rev(void*); diff --git a/src/ssort.h b/src/ssort.h new file mode 100644 index 0000000..c45b2b1 --- /dev/null +++ b/src/ssort.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +/* Stable sorting algorithm */ + +static inline void ssort(void *base, size_t nmemb, size_t size, intmax_t(*compar)(const void*, const void*)) { + void *tmp = alloca(size); + + intmax_t i = 1; + while(i < nmemb) { + memcpy(tmp, base + size * i, size); + + intmax_t j = i - 1; + while(j >= 0 && compar(base + size * j, tmp) > 0) { + memcpy(base + size * (j + 1), base + size * j, size); + j--; + } + + memcpy(base + size * (j + 1), tmp, size); + + i++; + } +} diff --git a/src/stb_image.h b/src/stb_image.h new file mode 100644 index 0000000..5e807a0 --- /dev/null +++ b/src/stb_image.h @@ -0,0 +1,7987 @@ +/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8/16-bit-per-channel + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff + 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes + 2.26 (2020-07-13) many minor fixes + 2.25 (2020-02-02) fix warnings + 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically + 2.23 (2019-08-11) fix clang static analysis warning + 2.22 (2019-03-04) gif fixes, fix warnings + 2.21 (2019-02-25) fix typo in comment + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) + Arseny Kapoulkine Simon Breuss (16-bit PNM) + John-Mark Allen + Carmelo J Fdez-Aguera + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski + Phil Jordan Dave Moore Roy Eltham + Hayaki Saito Nathan Reed Won Chun + Luke Graham Johan Duparc Nick Verigakis the Horde3D community + Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Eugene Golushkov Laurent Gomila Cort Stratton github:snagar + Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex + Cass Everitt Ryamond Barbiero github:grim210 + Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw + Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus + Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo + Julian Raschke Gregory Mullen Christian Floisand github:darealshinji + Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 + Brad Weinberger Matvey Cherevko github:mosra + Luca Sas Alexander Veselov Zack Middleton [reserved] + Ryan C. Gordon [reserved] [reserved] + DO NOT ADD YOUR NAME HERE + + Jacko Dirks + + To add your name to the credits, pick a random blank space in the middle and fill it. + 80% of merge conflicts on stb PRs are due to people adding their name at the end + of the credits. +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data); +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// To query the width, height and component count of an image without having to +// decode the full file, you can use the stbi_info family of functions: +// +// int x,y,n,ok; +// ok = stbi_info(filename, &x, &y, &n); +// // returns ok=1 and sets x, y, n if image is a supported format, +// // 0 otherwise. +// +// Note that stb_image pervasively uses ints in its public API for sizes, +// including sizes of memory buffers. This is now part of the API and thus +// hard to change without causing breakage. As a result, the various image +// loaders all have certain limits on image size; these differ somewhat +// by format but generally boil down to either just under 2GB or just under +// 1GB. When the decoded image would be larger than this, stb_image decoding +// will fail. +// +// Additionally, stb_image will reject image files that have any of their +// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, +// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, +// the only way to have an image with such dimensions load correctly +// is for it to have a rather extreme aspect ratio. Either way, the +// assumption here is that such larger images are likely to be malformed +// or malicious. If you do need to load an image with individual dimensions +// larger than that, and it still fits in the overall size limit, you can +// #define STBI_MAX_DIMENSIONS on your own to be something larger. +// +// =========================================================================== +// +// UNICODE: +// +// If compiling for Windows and you wish to use Unicode filenames, compile +// with +// #define STBI_WINDOWS_UTF8 +// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert +// Windows wchar_t filenames to utf8. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy-to-use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// provide more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small source code footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image supports loading HDR images in general, and currently the Radiance +// .HDR file format specifically. You can still load any file through the existing +// interface; if you attempt to load an HDR file, it will be automatically remapped +// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// We optionally support converting iPhone-formatted PNGs (which store +// premultiplied BGRA) back to RGB, even though they're internally encoded +// differently. To enable this conversion, call +// stbi_convert_iphone_png_to_rgb(1). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// +// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater +// than that size (in either width or height) without further processing. +// This is to let programs in the wild set an upper bound to prevent +// denial-of-service attacks on untrusted data, as one could generate a +// valid image of gigantic dimensions and force stb_image to allocate a +// huge block of memory and spend disproportionate time decoding it. By +// default this is set to (1 << 24), which is 16777216, but that's still +// very big. + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +#include +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STBIDEF +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + +#ifdef STBI_WINDOWS_UTF8 +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif + +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// on most compilers (and ALL modern mainstream compilers) this is threadsafe +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// as above, but only applies to images loaded on the thread that calls the function +// this function is only available if your compiler supports thread-local variables; +// calling it will fail to link if your compiler doesn't +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert); +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + +#ifdef __cplusplus +#define STBI_EXTERN extern "C" +#else +#define STBI_EXTERN extern +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + +#ifndef STBI_NO_THREAD_LOCALS + #if defined(__cplusplus) && __cplusplus >= 201103L + #define STBI_THREAD_LOCAL thread_local + #elif defined(__GNUC__) && __GNUC__ < 5 + #define STBI_THREAD_LOCAL __thread + #elif defined(_MSC_VER) + #define STBI_THREAD_LOCAL __declspec(thread) + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) + #define STBI_THREAD_LOCAL _Thread_local + #endif + + #ifndef STBI_THREAD_LOCAL + #if defined(__GNUC__) + #define STBI_THREAD_LOCAL __thread + #endif + #endif +#endif + +#if defined(_MSC_VER) || defined(__SYMBIAN32__) +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#endif + +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif + +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +#ifdef _MSC_VER +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name +#else +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +#ifndef STBI_MAX_DIMENSIONS +#define STBI_MAX_DIMENSIONS (1 << 24) +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + int callback_already_read; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + int ch; + fseek((FILE*) user, n, SEEK_CUR); + ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */ + if (ch != EOF) { + ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */ + } +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user) || ferror((FILE *) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__pnm_is16(stbi__context *s); +#endif + +static +#ifdef STBI_THREAD_LOCAL +STBI_THREAD_LOCAL +#endif +const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +#ifndef STBI_NO_FAILURE_STRINGS +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} +#endif + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} +#endif + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} +#endif + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow. +static int stbi__addints_valid(int a, int b) +{ + if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow + if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0. + return a <= INT_MAX - b; +} + +// returns 1 if the product of two signed shorts is valid, 0 on overflow. +static int stbi__mul2shorts_valid(short a, short b) +{ + if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow + if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid + if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN + return a >= SHRT_MIN / b; +} + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load_global = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_global = flag_true_if_should_flip; +} + +#ifndef STBI_THREAD_LOCAL +#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global +#else +static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set; + +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_local = flag_true_if_should_flip; + stbi__vertically_flip_on_load_set = 1; +} + +#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \ + ? stbi__vertically_flip_on_load_local \ + : stbi__vertically_flip_on_load_global) +#endif // STBI_THREAD_LOCAL + +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + + // test the formats with a very explicit header first (at least a FOURCC + // or distinctive magic number first) + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #else + STBI_NOTUSED(bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif + + // then the formats that can end up attempting to load with just 1 or 2 + // bytes matching expectations; these are prone to false positives, so + // try them later + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +#ifndef STBI_NO_GIF +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} +#endif + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + + if (ri.bits_per_channel != 8) { + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + + if (ri.bits_per_channel != 16) { + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#ifndef STBI_NO_STDIO + +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); +#endif + +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) + return 0; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} +#endif + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) +// nothing +#else +static void stbi__skip(stbi__context *s, int n) +{ + if (n == 0) return; // already there! + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM) +// nothing +#else +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} +#endif + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} +#endif + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + z += (stbi__uint32)stbi__get16le(s) << 16; + return z; +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + } + if (n < comp) { + for (i=0; i < x*y; ++i) { + output[i*comp + n] = data[i*comp + n]/255.0f; + } + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) { + for (j=0; j < count[i]; ++j) { + h->size[k++] = (stbi_uc) (i+1); + if(k >= 257) return stbi__err("bad size list","Corrupt JPEG"); + } + } + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + if(c < 0 || c >= 256) // symbol id out of bounds! + return -1; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing + + sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & (sgn - 1)); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG"); + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + diff = t ? stbi__extend_receive(j, t) : 0; + + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG"); + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * (1 << j->succ_low)); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * (1 << shift)); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values! + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios + // and I've never seen a non-corrupted JPEG file actually use them + for (i=0; i < s->img_n; ++i) { + if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG"); + if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG"); + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) +{ + // some JPEGs have junk at end, skip over it but if we find what looks + // like a valid marker, resume there + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + while (x == 255) { // might be a marker + if (stbi__at_eof(j->s)) return STBI__MARKER_none; + x = stbi__get8(j->s); + if (x != 0x00 && x != 0xff) { + // not a stuffed zero or lead-in to another marker, looks + // like an actual marker, return it + return x; + } + // stuffed zero has x=0 now which ends the loop, meaning we go + // back to regular scan loop. + // repeated 0xff keeps trying to read the next byte of the marker. + } + } + return STBI__MARKER_none; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + j->marker = stbi__skip_jpeg_junk_at_end(j); + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + m = stbi__get_marker(j); + if (STBI__RESTART(m)) + m = stbi__get_marker(j); + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + m = stbi__get_marker(j); + } else { + if (!stbi__process_marker(j, m)) return 1; + m = stbi__get_marker(j); + } + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + else + decode_n = z->s->img_n; + + // nothing to do if no components requested; check this now to avoid + // accessing uninitialized coutput[0] later + if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; } + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__errpuc("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) +#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[STBI__ZNSYMS]; + stbi__uint16 value[STBI__ZNSYMS]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static int stbi__zeof(stbi__zbuf *z) +{ + return (z->zbuffer >= z->zbuffer_end); +} + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + return stbi__zeof(z) ? 0 : *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + if (z->code_buffer >= (1U << z->num_bits)) { + z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */ + return; + } + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s >= 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere! + if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) { + if (stbi__zeof(a)) { + return -1; /* report error for unexpected end of data. */ + } + stbi__fill_bits(a); + } + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + unsigned int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (unsigned int) (z->zout - z->zout_start); + limit = old_limit = (unsigned) (z->zout_end - z->zout_start); + if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory"); + while (cur + n > limit) { + if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory"); + limit *= 2; + } + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + return 1; + } + if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (zout + len > a->zout_end) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) { + c = stbi__zreceive(a,3)+3; + } else if (c == 18) { + c = stbi__zreceive(a,7)+11; + } else { + return stbi__err("bad codelengths", "Corrupt PNG"); + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG"); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filters used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_paeth_first +}; + +static int stbi__paeth(int a, int b, int c) +{ + int p = a + b - c; + int pa = abs(p-a); + int pb = abs(p-b); + int pc = abs(p-c); + if (pa <= pb && pa <= pc) return a; + if (pb <= pc) return b; + return c; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *prior; + int filter = *raw++; + + if (filter > 4) + return stbi__err("invalid filter","Corrupt PNG"); + + if (depth < 8) { + if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG"); + cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place + filter_bytes = 1; + width = img_width_bytes; + } + prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // handle first byte explicitly + for (k=0; k < filter_bytes; ++k) { + switch (filter) { + case STBI__F_none : cur[k] = raw[k]; break; + case STBI__F_sub : cur[k] = raw[k]; break; + case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; + case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; + case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; + case STBI__F_avg_first : cur[k] = raw[k]; break; + case STBI__F_paeth_first: cur[k] = raw[k]; break; + } + } + + if (depth == 8) { + if (img_n != out_n) + cur[img_n] = 255; // first pixel + raw += img_n; + cur += out_n; + prior += out_n; + } else if (depth == 16) { + if (img_n != out_n) { + cur[filter_bytes] = 255; // first pixel top byte + cur[filter_bytes+1] = 255; // first pixel bottom byte + } + raw += filter_bytes; + cur += output_bytes; + prior += output_bytes; + } else { + raw += 1; + cur += 1; + prior += 1; + } + + // this is a little gross, so that we don't switch per-pixel or per-component + if (depth < 8 || img_n == out_n) { + int nk = (width - 1)*filter_bytes; + #define STBI__CASE(f) \ + case f: \ + for (k=0; k < nk; ++k) + switch (filter) { + // "none" filter turns into a memcpy here; make that explicit. + case STBI__F_none: memcpy(cur, raw, nk); break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break; + } + #undef STBI__CASE + raw += nk; + } else { + STBI_ASSERT(img_n+1 == out_n); + #define STBI__CASE(f) \ + case f: \ + for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \ + for (k=0; k < filter_bytes; ++k) + switch (filter) { + STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break; + STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break; + STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break; + STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break; + STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break; + STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break; + STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break; + } + #undef STBI__CASE + + // the loop above sets the high byte of the pixels' alpha, but for + // 16 bit png files we also need the low byte set. we'll do that here. + if (depth == 16) { + cur = a->out + stride*j; // start at the beginning of the row again + for (i=0; i < x; ++i,cur+=output_bytes) { + cur[filter_bytes+1] = 255; + } + } + } + } + + // we make a separate pass to expand bits to pixels; for performance, + // this could run two scanlines behind the above code, so it won't + // intefere with filtering but will still be in the cache. + if (depth < 8) { + for (j=0; j < y; ++j) { + stbi_uc *cur = a->out + stride*j; + stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; + // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit + // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + + // note that the final byte might overshoot and write more data than desired. + // we can allocate enough data that this never writes out of memory, but it + // could also overwrite the next scanline. can it overwrite non-empty data + // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. + // so we need to explicitly clamp the final ones + + if (depth == 4) { + for (k=x*img_n; k >= 2; k-=2, ++in) { + *cur++ = scale * ((*in >> 4) ); + *cur++ = scale * ((*in ) & 0x0f); + } + if (k > 0) *cur++ = scale * ((*in >> 4) ); + } else if (depth == 2) { + for (k=x*img_n; k >= 4; k-=4, ++in) { + *cur++ = scale * ((*in >> 6) ); + *cur++ = scale * ((*in >> 4) & 0x03); + *cur++ = scale * ((*in >> 2) & 0x03); + *cur++ = scale * ((*in ) & 0x03); + } + if (k > 0) *cur++ = scale * ((*in >> 6) ); + if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); + if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); + } else if (depth == 1) { + for (k=x*img_n; k >= 8; k-=8, ++in) { + *cur++ = scale * ((*in >> 7) ); + *cur++ = scale * ((*in >> 6) & 0x01); + *cur++ = scale * ((*in >> 5) & 0x01); + *cur++ = scale * ((*in >> 4) & 0x01); + *cur++ = scale * ((*in >> 3) & 0x01); + *cur++ = scale * ((*in >> 2) & 0x01); + *cur++ = scale * ((*in >> 1) & 0x01); + *cur++ = scale * ((*in ) & 0x01); + } + if (k > 0) *cur++ = scale * ((*in >> 7) ); + if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); + if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); + if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); + if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); + if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); + if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); + } + if (img_n != out_n) { + int q; + // insert alpha = 255 + cur = a->out + stride*j; + if (img_n == 1) { + for (q=x-1; q >= 0; --q) { + cur[q*2+1] = 255; + cur[q*2+0] = cur[q]; + } + } else { + STBI_ASSERT(img_n == 3); + for (q=x-1; q >= 0; --q) { + cur[q*4+3] = 255; + cur[q*4+2] = cur[q*3+2]; + cur[q*4+1] = cur[q*3+1]; + cur[q*4+0] = cur[q*3+0]; + } + } + } + } + } else if (depth == 16) { + // force the image data from big-endian to platform-native. + // this is done in a separate pass due to the decoding relying + // on the data being untouched, but could probably be done + // per-line during decode if care is taken. + stbi_uc *cur = a->out; + stbi__uint16 *cur16 = (stbi__uint16*)cur; + + for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) { + *cur16 = (cur[0] << 8) | cur[1]; + } + } + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + if (!final) return stbi__err("outofmem", "Out of memory"); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load_global = 0; +static int stbi__de_iphone_flag_global = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_global = flag_true_if_should_convert; +} + +#ifndef STBI_THREAD_LOCAL +#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global +#define stbi__de_iphone_flag stbi__de_iphone_flag_global +#else +static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; +static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; + +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; + stbi__unpremultiply_on_load_set = 1; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_local = flag_true_if_should_convert; + stbi__de_iphone_flag_set = 1; +} + +#define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \ + ? stbi__unpremultiply_on_load_local \ + : stbi__unpremultiply_on_load_global) +#define stbi__de_iphone_flag (stbi__de_iphone_flag_set \ + ? stbi__de_iphone_flag_local \ + : stbi__de_iphone_flag_global) +#endif // STBI_THREAD_LOCAL + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]={0}; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); + s->img_y = stbi__get32be(s); + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + } + // even with SCAN_header, have to scan to see if we have a tRNS + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. + if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } + if (z->depth == 16) { + for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { + // header scan definitely stops at first IDAT + if (pal_img_n) + s->img_n = pal_img_n; + return 1; + } + if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes"); + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth <= 8) + ri->bits_per_channel = 8; + else if (p->depth == 16) + ri->bits_per_channel = 16; + else + return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth"); + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) { n += 16; z >>= 16; } + if (z >= 0x00100) { n += 8; z >>= 8; } + if (z >= 0x00010) { n += 4; z >>= 4; } + if (z >= 0x00004) { n += 2; z >>= 2; } + if (z >= 0x00002) { n += 1;/* >>= 1;*/ } + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. +static int stbi__shiftsigned(unsigned int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; + int extra_read; +} stbi__bmp_data; + +static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) +{ + // BI_BITFIELDS specifies masks explicitly, don't override + if (compress == 3) + return 1; + + if (compress == 0) { + if (info->bpp == 16) { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } else if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + // otherwise, use defaults, which is all-0 + info->mr = info->mg = info->mb = info->ma = 0; + } + return 1; + } + return 0; // error +} + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + info->extra_read = 14; + + if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP"); + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes + if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + stbi__bmp_set_mask_defaults(info, compress); + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->extra_read += 12; + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + // V4/V5 header + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs + stbi__bmp_set_mask_defaults(info, compress); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - info.extra_read - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - info.extra_read - info.hsz) >> 2; + } + if (psize == 0) { + // accept some number of extra bytes after the header, but if the offset points either to before + // the header ends or implies a large amount of extra data, reject the file as malformed + int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original); + int header_limit = 1024; // max we actually read is below 256 bytes currently. + int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size. + if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) { + return stbi__errpuc("bad header", "Corrupt BMP"); + } + // we established that bytes_read_so_far is positive and sensible. + // the first half of this test rejects offsets that are either too small positives, or + // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn + // ensures the number computed in the second half of the test can't overflow. + if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { + return stbi__errpuc("bad offset", "Corrupt BMP"); + } else { + stbi__skip(s, info.offset - bytes_read_so_far); + } + } + + if (info.bpp == 24 && ma == 0xff000000) + s->img_n = 3; + else + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - info.extra_read - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i]; p1[i] = p2[i]; p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); + STBI_NOTUSED(tga_x_origin); // @TODO + STBI_NOTUSED(tga_y_origin); // @TODO + + if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + if (tga_palette_len == 0) { /* you have to have at least one entry! */ + STBI_FREE(tga_data); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + STBI_NOTUSED(tga_palette_start); + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + + if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + if (!result) return stbi__errpuc("outofmem", "Out of memory"); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!g) return stbi__err("outofmem", "Out of memory"); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + STBI_NOTUSED(req_comp); + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) + return stbi__errpuc("too large", "GIF image is too large"); + pcount = g->w * g->h; + g->out = (stbi_uc *) stbi__malloc(4 * pcount); + g->background = (stbi_uc *) stbi__malloc(4 * pcount); + g->history = (stbi_uc *) stbi__malloc(pcount); + if (!g->out || !g->background || !g->history) + return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "transparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to the color that was there the previous frame. + memset(g->out, 0x00, 4 * pcount); + memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) + memset(g->history, 0x00, pcount); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispose of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } + + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + // if the width of the specified rectangle is 0, that means + // we may not see *any* pixels or the image is malformed; + // to make sure this is caught, move the current y down to + // max_y (which is what out_gif_code checks). + if (w == 0) + g->cur_y = g->max_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (!o) return NULL; + + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) +{ + STBI_FREE(g->out); + STBI_FREE(g->history); + STBI_FREE(g->background); + + if (out) STBI_FREE(out); + if (delays && *delays) STBI_FREE(*delays); + return stbi__errpuc("outofmem", "Out of memory"); +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + int out_size = 0; + int delays_size = 0; + + STBI_NOTUSED(out_size); + STBI_NOTUSED(delays_size); + + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride ); + if (!tmp) + return stbi__load_gif_main_outofmem(&g, out, delays); + else { + out = (stbi_uc*) tmp; + out_size = layers * stride; + } + + if (delays) { + int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); + if (!new_delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + *delays = new_delays; + delays_size = layers * sizeof(int); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (!out) + return stbi__load_gif_main_outofmem(&g, out, delays); + out_size = layers * stride; + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + if (!*delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + delays_size = layers * sizeof(int); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + STBI_NOTUSED(ri); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } else if (g.out) { + // if there was an error and we allocated an image buffer, free it! + STBI_FREE(g.out); + } + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + if (p == NULL) { + stbi__rewind( s ); + return 0; + } + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) { + if (info.bpp == 24 && info.ma == 0xff000000) + *comp = 3; + else + *comp = info.ma ? 4 : 3; + } + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + STBI_NOTUSED(stbi__get32be(s)); + STBI_NOTUSED(stbi__get32be(s)); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); + if (ri->bits_per_channel == 0) + return 0; + + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + + if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) { + STBI_FREE(out); + return stbi__errpuc("bad PNM", "PNM file truncated"); + } + + if (req_comp && req_comp != s->img_n) { + if (ri->bits_per_channel == 16) { + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); + } else { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + } + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + if((value > 214748364) || (value == 214748364 && *c > '7')) + return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int"); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + if(*x == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + if (*y == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + if (maxv > 65535) + return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images"); + else if (maxv > 255) + return 16; + else + return 8; +} + +static int stbi__pnm_is16(stbi__context *s) +{ + if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) + return 1; + return 0; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_is16(s)) return 1; + #endif + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +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 OR COPYRIGHT HOLDERS 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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +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. +------------------------------------------------------------------------------ +*/ diff --git a/src/stb_image_resize.h b/src/stb_image_resize.h new file mode 100644 index 0000000..ef9e6fe --- /dev/null +++ b/src/stb_image_resize.h @@ -0,0 +1,2634 @@ +/* stb_image_resize - v0.97 - public domain image resizing + by Jorge L Rodriguez (@VinoBS) - 2014 + http://github.com/nothings/stb + + Written with emphasis on usability, portability, and efficiency. (No + SIMD or threads, so it be easily outperformed by libs that use those.) + Only scaling and translation is supported, no rotations or shears. + Easy API downsamples w/Mitchell filter, upsamples w/cubic interpolation. + + COMPILING & LINKING + In one C/C++ file that #includes this file, do this: + #define STB_IMAGE_RESIZE_IMPLEMENTATION + before the #include. That will create the implementation in that file. + + QUICKSTART + stbir_resize_uint8( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, num_channels) + stbir_resize_float(...) + stbir_resize_uint8_srgb( input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0) + stbir_resize_uint8_srgb_edgemode( + input_pixels , in_w , in_h , 0, + output_pixels, out_w, out_h, 0, + num_channels , alpha_chan , 0, STBIR_EDGE_CLAMP) + // WRAP/REFLECT/ZERO + + FULL API + See the "header file" section of the source for API documentation. + + ADDITIONAL DOCUMENTATION + + SRGB & FLOATING POINT REPRESENTATION + The sRGB functions presume IEEE floating point. If you do not have + IEEE floating point, define STBIR_NON_IEEE_FLOAT. This will use + a slower implementation. + + MEMORY ALLOCATION + The resize functions here perform a single memory allocation using + malloc. To control the memory allocation, before the #include that + triggers the implementation, do: + + #define STBIR_MALLOC(size,context) ... + #define STBIR_FREE(ptr,context) ... + + Each resize function makes exactly one call to malloc/free, so to use + temp memory, store the temp memory in the context and return that. + + ASSERT + Define STBIR_ASSERT(boolval) to override assert() and not use assert.h + + OPTIMIZATION + Define STBIR_SATURATE_INT to compute clamp values in-range using + integer operations instead of float operations. This may be faster + on some platforms. + + DEFAULT FILTERS + For functions which don't provide explicit control over what filters + to use, you can change the compile-time defaults with + + #define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_something + #define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_something + + See stbir_filter in the header-file section for the list of filters. + + NEW FILTERS + A number of 1D filter kernels are used. For a list of + supported filters see the stbir_filter enum. To add a new filter, + write a filter function and add it to stbir__filter_info_table. + + PROGRESS + For interactive use with slow resize operations, you can install + a progress-report callback: + + #define STBIR_PROGRESS_REPORT(val) some_func(val) + + The parameter val is a float which goes from 0 to 1 as progress is made. + + For example: + + static void my_progress_report(float progress); + #define STBIR_PROGRESS_REPORT(val) my_progress_report(val) + + #define STB_IMAGE_RESIZE_IMPLEMENTATION + #include "stb_image_resize.h" + + static void my_progress_report(float progress) + { + printf("Progress: %f%%\n", progress*100); + } + + MAX CHANNELS + If your image has more than 64 channels, define STBIR_MAX_CHANNELS + to the max you'll have. + + ALPHA CHANNEL + Most of the resizing functions provide the ability to control how + the alpha channel of an image is processed. The important things + to know about this: + + 1. The best mathematically-behaved version of alpha to use is + called "premultiplied alpha", in which the other color channels + have had the alpha value multiplied in. If you use premultiplied + alpha, linear filtering (such as image resampling done by this + library, or performed in texture units on GPUs) does the "right + thing". While premultiplied alpha is standard in the movie CGI + industry, it is still uncommon in the videogame/real-time world. + + If you linearly filter non-premultiplied alpha, strange effects + occur. (For example, the 50/50 average of 99% transparent bright green + and 1% transparent black produces 50% transparent dark green when + non-premultiplied, whereas premultiplied it produces 50% + transparent near-black. The former introduces green energy + that doesn't exist in the source image.) + + 2. Artists should not edit premultiplied-alpha images; artists + want non-premultiplied alpha images. Thus, art tools generally output + non-premultiplied alpha images. + + 3. You will get best results in most cases by converting images + to premultiplied alpha before processing them mathematically. + + 4. If you pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, the + resizer does not do anything special for the alpha channel; + it is resampled identically to other channels. This produces + the correct results for premultiplied-alpha images, but produces + less-than-ideal results for non-premultiplied-alpha images. + + 5. If you do not pass the flag STBIR_FLAG_ALPHA_PREMULTIPLIED, + then the resizer weights the contribution of input pixels + based on their alpha values, or, equivalently, it multiplies + the alpha value into the color channels, resamples, then divides + by the resultant alpha value. Input pixels which have alpha=0 do + not contribute at all to output pixels unless _all_ of the input + pixels affecting that output pixel have alpha=0, in which case + the result for that pixel is the same as it would be without + STBIR_FLAG_ALPHA_PREMULTIPLIED. However, this is only true for + input images in integer formats. For input images in float format, + input pixels with alpha=0 have no effect, and output pixels + which have alpha=0 will be 0 in all channels. (For float images, + you can manually achieve the same result by adding a tiny epsilon + value to the alpha channel of every image, and then subtracting + or clamping it at the end.) + + 6. You can suppress the behavior described in #5 and make + all-0-alpha pixels have 0 in all channels by #defining + STBIR_NO_ALPHA_EPSILON. + + 7. You can separately control whether the alpha channel is + interpreted as linear or affected by the colorspace. By default + it is linear; you almost never want to apply the colorspace. + (For example, graphics hardware does not apply sRGB conversion + to the alpha channel.) + + CONTRIBUTORS + Jorge L Rodriguez: Implementation + Sean Barrett: API design, optimizations + Aras Pranckevicius: bugfix + Nathan Reed: warning fixes + + REVISIONS + 0.97 (2020-02-02) fixed warning + 0.96 (2019-03-04) fixed warnings + 0.95 (2017-07-23) fixed warnings + 0.94 (2017-03-18) fixed warnings + 0.93 (2017-03-03) fixed bug with certain combinations of heights + 0.92 (2017-01-02) fix integer overflow on large (>2GB) images + 0.91 (2016-04-02) fix warnings; fix handling of subpixel regions + 0.90 (2014-09-17) first released version + + LICENSE + See end of file for license information. + + TODO + Don't decode all of the image data when only processing a partial tile + Don't use full-width decode buffers when only processing a partial tile + When processing wide images, break processing into tiles so data fits in L1 cache + Installable filters? + Resize that respects alpha test coverage + (Reference code: FloatImage::alphaTestCoverage and FloatImage::scaleAlphaToCoverage: + https://code.google.com/p/nvidia-texture-tools/source/browse/trunk/src/nvimage/FloatImage.cpp ) +*/ + +#ifndef STBIR_INCLUDE_STB_IMAGE_RESIZE_H +#define STBIR_INCLUDE_STB_IMAGE_RESIZE_H + +#ifdef _MSC_VER +typedef unsigned char stbir_uint8; +typedef unsigned short stbir_uint16; +typedef unsigned int stbir_uint32; +#else +#include +typedef uint8_t stbir_uint8; +typedef uint16_t stbir_uint16; +typedef uint32_t stbir_uint32; +#endif + +#ifndef STBIRDEF +#ifdef STB_IMAGE_RESIZE_STATIC +#define STBIRDEF static +#else +#ifdef __cplusplus +#define STBIRDEF extern "C" +#else +#define STBIRDEF extern +#endif +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// Easy-to-use API: +// +// * "input pixels" points to an array of image data with 'num_channels' channels (e.g. RGB=3, RGBA=4) +// * input_w is input image width (x-axis), input_h is input image height (y-axis) +// * stride is the offset between successive rows of image data in memory, in bytes. you can +// specify 0 to mean packed continuously in memory +// * alpha channel is treated identically to other channels. +// * colorspace is linear or sRGB as specified by function name +// * returned result is 1 for success or 0 in case of an error. +// #define STBIR_ASSERT() to trigger an assert on parameter validation errors. +// * Memory required grows approximately linearly with input and output size, but with +// discontinuities at input_w == output_w and input_h == output_h. +// * These functions use a "default" resampling filter defined at compile time. To change the filter, +// you can change the compile-time defaults by #defining STBIR_DEFAULT_FILTER_UPSAMPLE +// and STBIR_DEFAULT_FILTER_DOWNSAMPLE, or you can use the medium-complexity API. + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels); + + +// The following functions interpret image data as gamma-corrected sRGB. +// Specify STBIR_ALPHA_CHANNEL_NONE if you have no alpha channel, +// or otherwise provide the index of the alpha channel. Flags value +// of 0 will probably do the right thing if you're not sure what +// the flags mean. + +#define STBIR_ALPHA_CHANNEL_NONE -1 + +// Set this flag if your texture has premultiplied alpha. Otherwise, stbir will +// use alpha-weighted resampling (effectively premultiplying, resampling, +// then unpremultiplying). +#define STBIR_FLAG_ALPHA_PREMULTIPLIED (1 << 0) +// The specified alpha channel should be handled as gamma-corrected value even +// when doing sRGB operations. +#define STBIR_FLAG_ALPHA_USES_COLORSPACE (1 << 1) + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags); + + +typedef enum +{ + STBIR_EDGE_CLAMP = 1, + STBIR_EDGE_REFLECT = 2, + STBIR_EDGE_WRAP = 3, + STBIR_EDGE_ZERO = 4, +} stbir_edge; + +// This function adds the ability to specify how requests to sample off the edge of the image are handled. +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode); + +////////////////////////////////////////////////////////////////////////////// +// +// Medium-complexity API +// +// This extends the easy-to-use API as follows: +// +// * Alpha-channel can be processed separately +// * If alpha_channel is not STBIR_ALPHA_CHANNEL_NONE +// * Alpha channel will not be gamma corrected (unless flags&STBIR_FLAG_GAMMA_CORRECT) +// * Filters will be weighted by alpha channel (unless flags&STBIR_FLAG_ALPHA_PREMULTIPLIED) +// * Filter can be selected explicitly +// * uint16 image type +// * sRGB colorspace available for all types +// * context parameter for passing to STBIR_MALLOC + +typedef enum +{ + STBIR_FILTER_DEFAULT = 0, // use same filter type that easy-to-use API chooses + STBIR_FILTER_BOX = 1, // A trapezoid w/1-pixel wide ramps, same result as box for integer scale ratios + STBIR_FILTER_TRIANGLE = 2, // On upsampling, produces same results as bilinear texture filtering + STBIR_FILTER_CUBICBSPLINE = 3, // The cubic b-spline (aka Mitchell-Netrevalli with B=1,C=0), gaussian-esque + STBIR_FILTER_CATMULLROM = 4, // An interpolating cubic spline + STBIR_FILTER_MITCHELL = 5, // Mitchell-Netrevalli filter with B=1/3, C=1/3 +} stbir_filter; + +typedef enum +{ + STBIR_COLORSPACE_LINEAR, + STBIR_COLORSPACE_SRGB, + + STBIR_MAX_COLORSPACES, +} stbir_colorspace; + +// The following functions are all identical except for the type of the image data + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context); + + + +////////////////////////////////////////////////////////////////////////////// +// +// Full-complexity API +// +// This extends the medium API as follows: +// +// * uint32 image type +// * not typesafe +// * separate filter types for each axis +// * separate edge modes for each axis +// * can specify scale explicitly for subpixel correctness +// * can specify image source tile using texture coordinates + +typedef enum +{ + STBIR_TYPE_UINT8 , + STBIR_TYPE_UINT16, + STBIR_TYPE_UINT32, + STBIR_TYPE_FLOAT , + + STBIR_MAX_TYPES +} stbir_datatype; + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context); + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset); + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1); +// (s0, t0) & (s1, t1) are the top-left and bottom right corner (uv addressing style: [0, 1]x[0, 1]) of a region of the input image to use. + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBIR_INCLUDE_STB_IMAGE_RESIZE_H + + + + + +#ifdef STB_IMAGE_RESIZE_IMPLEMENTATION + +#ifndef STBIR_ASSERT +#include +#define STBIR_ASSERT(x) assert(x) +#endif + +// For memset +#include + +#include + +#ifndef STBIR_MALLOC +#include +// use comma operator to evaluate c, to avoid "unused parameter" warnings +#define STBIR_MALLOC(size,c) ((void)(c), malloc(size)) +#define STBIR_FREE(ptr,c) ((void)(c), free(ptr)) +#endif + +#ifndef _MSC_VER +#ifdef __cplusplus +#define stbir__inline inline +#else +#define stbir__inline +#endif +#else +#define stbir__inline __forceinline +#endif + + +// should produce compiler error if size is wrong +typedef unsigned char stbir__validate_uint32[sizeof(stbir_uint32) == 4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBIR__NOTUSED(v) (void)(v) +#else +#define STBIR__NOTUSED(v) (void)sizeof(v) +#endif + +#define STBIR__ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0])) + +#ifndef STBIR_DEFAULT_FILTER_UPSAMPLE +#define STBIR_DEFAULT_FILTER_UPSAMPLE STBIR_FILTER_CATMULLROM +#endif + +#ifndef STBIR_DEFAULT_FILTER_DOWNSAMPLE +#define STBIR_DEFAULT_FILTER_DOWNSAMPLE STBIR_FILTER_MITCHELL +#endif + +#ifndef STBIR_PROGRESS_REPORT +#define STBIR_PROGRESS_REPORT(float_0_to_1) +#endif + +#ifndef STBIR_MAX_CHANNELS +#define STBIR_MAX_CHANNELS 64 +#endif + +#if STBIR_MAX_CHANNELS > 65536 +#error "Too many channels; STBIR_MAX_CHANNELS must be no more than 65536." +// because we store the indices in 16-bit variables +#endif + +// This value is added to alpha just before premultiplication to avoid +// zeroing out color values. It is equivalent to 2^-80. If you don't want +// that behavior (it may interfere if you have floating point images with +// very small alpha values) then you can define STBIR_NO_ALPHA_EPSILON to +// disable it. +#ifndef STBIR_ALPHA_EPSILON +#define STBIR_ALPHA_EPSILON ((float)1 / (1 << 20) / (1 << 20) / (1 << 20) / (1 << 20)) +#endif + + + +#ifdef _MSC_VER +#define STBIR__UNUSED_PARAM(v) (void)(v) +#else +#define STBIR__UNUSED_PARAM(v) (void)sizeof(v) +#endif + +// must match stbir_datatype +static unsigned char stbir__type_size[] = { + 1, // STBIR_TYPE_UINT8 + 2, // STBIR_TYPE_UINT16 + 4, // STBIR_TYPE_UINT32 + 4, // STBIR_TYPE_FLOAT +}; + +// Kernel function centered at 0 +typedef float (stbir__kernel_fn)(float x, float scale); +typedef float (stbir__support_fn)(float scale); + +typedef struct +{ + stbir__kernel_fn* kernel; + stbir__support_fn* support; +} stbir__filter_info; + +// When upsampling, the contributors are which source pixels contribute. +// When downsampling, the contributors are which destination pixels are contributed to. +typedef struct +{ + int n0; // First contributing pixel + int n1; // Last contributing pixel +} stbir__contributors; + +typedef struct +{ + const void* input_data; + int input_w; + int input_h; + int input_stride_bytes; + + void* output_data; + int output_w; + int output_h; + int output_stride_bytes; + + float s0, t0, s1, t1; + + float horizontal_shift; // Units: output pixels + float vertical_shift; // Units: output pixels + float horizontal_scale; + float vertical_scale; + + int channels; + int alpha_channel; + stbir_uint32 flags; + stbir_datatype type; + stbir_filter horizontal_filter; + stbir_filter vertical_filter; + stbir_edge edge_horizontal; + stbir_edge edge_vertical; + stbir_colorspace colorspace; + + stbir__contributors* horizontal_contributors; + float* horizontal_coefficients; + + stbir__contributors* vertical_contributors; + float* vertical_coefficients; + + int decode_buffer_pixels; + float* decode_buffer; + + float* horizontal_buffer; + + // cache these because ceil/floor are inexplicably showing up in profile + int horizontal_coefficient_width; + int vertical_coefficient_width; + int horizontal_filter_pixel_width; + int vertical_filter_pixel_width; + int horizontal_filter_pixel_margin; + int vertical_filter_pixel_margin; + int horizontal_num_contributors; + int vertical_num_contributors; + + int ring_buffer_length_bytes; // The length of an individual entry in the ring buffer. The total number of ring buffers is stbir__get_filter_pixel_width(filter) + int ring_buffer_num_entries; // Total number of entries in the ring buffer. + int ring_buffer_first_scanline; + int ring_buffer_last_scanline; + int ring_buffer_begin_index; // first_scanline is at this index in the ring buffer + float* ring_buffer; + + float* encode_buffer; // A temporary buffer to store floats so we don't lose precision while we do multiply-adds. + + int horizontal_contributors_size; + int horizontal_coefficients_size; + int vertical_contributors_size; + int vertical_coefficients_size; + int decode_buffer_size; + int horizontal_buffer_size; + int ring_buffer_size; + int encode_buffer_size; +} stbir__info; + + +static const float stbir__max_uint8_as_float = 255.0f; +static const float stbir__max_uint16_as_float = 65535.0f; +static const double stbir__max_uint32_as_float = 4294967295.0; + + +static stbir__inline int stbir__min(int a, int b) +{ + return a < b ? a : b; +} + +static stbir__inline float stbir__saturate(float x) +{ + if (x < 0) + return 0; + + if (x > 1) + return 1; + + return x; +} + +#ifdef STBIR_SATURATE_INT +static stbir__inline stbir_uint8 stbir__saturate8(int x) +{ + if ((unsigned int) x <= 255) + return x; + + if (x < 0) + return 0; + + return 255; +} + +static stbir__inline stbir_uint16 stbir__saturate16(int x) +{ + if ((unsigned int) x <= 65535) + return x; + + if (x < 0) + return 0; + + return 65535; +} +#endif + +static float stbir__srgb_uchar_to_linear_float[256] = { + 0.000000f, 0.000304f, 0.000607f, 0.000911f, 0.001214f, 0.001518f, 0.001821f, 0.002125f, 0.002428f, 0.002732f, 0.003035f, + 0.003347f, 0.003677f, 0.004025f, 0.004391f, 0.004777f, 0.005182f, 0.005605f, 0.006049f, 0.006512f, 0.006995f, 0.007499f, + 0.008023f, 0.008568f, 0.009134f, 0.009721f, 0.010330f, 0.010960f, 0.011612f, 0.012286f, 0.012983f, 0.013702f, 0.014444f, + 0.015209f, 0.015996f, 0.016807f, 0.017642f, 0.018500f, 0.019382f, 0.020289f, 0.021219f, 0.022174f, 0.023153f, 0.024158f, + 0.025187f, 0.026241f, 0.027321f, 0.028426f, 0.029557f, 0.030713f, 0.031896f, 0.033105f, 0.034340f, 0.035601f, 0.036889f, + 0.038204f, 0.039546f, 0.040915f, 0.042311f, 0.043735f, 0.045186f, 0.046665f, 0.048172f, 0.049707f, 0.051269f, 0.052861f, + 0.054480f, 0.056128f, 0.057805f, 0.059511f, 0.061246f, 0.063010f, 0.064803f, 0.066626f, 0.068478f, 0.070360f, 0.072272f, + 0.074214f, 0.076185f, 0.078187f, 0.080220f, 0.082283f, 0.084376f, 0.086500f, 0.088656f, 0.090842f, 0.093059f, 0.095307f, + 0.097587f, 0.099899f, 0.102242f, 0.104616f, 0.107023f, 0.109462f, 0.111932f, 0.114435f, 0.116971f, 0.119538f, 0.122139f, + 0.124772f, 0.127438f, 0.130136f, 0.132868f, 0.135633f, 0.138432f, 0.141263f, 0.144128f, 0.147027f, 0.149960f, 0.152926f, + 0.155926f, 0.158961f, 0.162029f, 0.165132f, 0.168269f, 0.171441f, 0.174647f, 0.177888f, 0.181164f, 0.184475f, 0.187821f, + 0.191202f, 0.194618f, 0.198069f, 0.201556f, 0.205079f, 0.208637f, 0.212231f, 0.215861f, 0.219526f, 0.223228f, 0.226966f, + 0.230740f, 0.234551f, 0.238398f, 0.242281f, 0.246201f, 0.250158f, 0.254152f, 0.258183f, 0.262251f, 0.266356f, 0.270498f, + 0.274677f, 0.278894f, 0.283149f, 0.287441f, 0.291771f, 0.296138f, 0.300544f, 0.304987f, 0.309469f, 0.313989f, 0.318547f, + 0.323143f, 0.327778f, 0.332452f, 0.337164f, 0.341914f, 0.346704f, 0.351533f, 0.356400f, 0.361307f, 0.366253f, 0.371238f, + 0.376262f, 0.381326f, 0.386430f, 0.391573f, 0.396755f, 0.401978f, 0.407240f, 0.412543f, 0.417885f, 0.423268f, 0.428691f, + 0.434154f, 0.439657f, 0.445201f, 0.450786f, 0.456411f, 0.462077f, 0.467784f, 0.473532f, 0.479320f, 0.485150f, 0.491021f, + 0.496933f, 0.502887f, 0.508881f, 0.514918f, 0.520996f, 0.527115f, 0.533276f, 0.539480f, 0.545725f, 0.552011f, 0.558340f, + 0.564712f, 0.571125f, 0.577581f, 0.584078f, 0.590619f, 0.597202f, 0.603827f, 0.610496f, 0.617207f, 0.623960f, 0.630757f, + 0.637597f, 0.644480f, 0.651406f, 0.658375f, 0.665387f, 0.672443f, 0.679543f, 0.686685f, 0.693872f, 0.701102f, 0.708376f, + 0.715694f, 0.723055f, 0.730461f, 0.737911f, 0.745404f, 0.752942f, 0.760525f, 0.768151f, 0.775822f, 0.783538f, 0.791298f, + 0.799103f, 0.806952f, 0.814847f, 0.822786f, 0.830770f, 0.838799f, 0.846873f, 0.854993f, 0.863157f, 0.871367f, 0.879622f, + 0.887923f, 0.896269f, 0.904661f, 0.913099f, 0.921582f, 0.930111f, 0.938686f, 0.947307f, 0.955974f, 0.964686f, 0.973445f, + 0.982251f, 0.991102f, 1.0f +}; + +static float stbir__srgb_to_linear(float f) +{ + if (f <= 0.04045f) + return f / 12.92f; + else + return (float)pow((f + 0.055f) / 1.055f, 2.4f); +} + +static float stbir__linear_to_srgb(float f) +{ + if (f <= 0.0031308f) + return f * 12.92f; + else + return 1.055f * (float)pow(f, 1 / 2.4f) - 0.055f; +} + +#ifndef STBIR_NON_IEEE_FLOAT +// From https://gist.github.com/rygorous/2203834 + +typedef union +{ + stbir_uint32 u; + float f; +} stbir__FP32; + +static const stbir_uint32 fp32_to_srgb8_tab4[104] = { + 0x0073000d, 0x007a000d, 0x0080000d, 0x0087000d, 0x008d000d, 0x0094000d, 0x009a000d, 0x00a1000d, + 0x00a7001a, 0x00b4001a, 0x00c1001a, 0x00ce001a, 0x00da001a, 0x00e7001a, 0x00f4001a, 0x0101001a, + 0x010e0033, 0x01280033, 0x01410033, 0x015b0033, 0x01750033, 0x018f0033, 0x01a80033, 0x01c20033, + 0x01dc0067, 0x020f0067, 0x02430067, 0x02760067, 0x02aa0067, 0x02dd0067, 0x03110067, 0x03440067, + 0x037800ce, 0x03df00ce, 0x044600ce, 0x04ad00ce, 0x051400ce, 0x057b00c5, 0x05dd00bc, 0x063b00b5, + 0x06970158, 0x07420142, 0x07e30130, 0x087b0120, 0x090b0112, 0x09940106, 0x0a1700fc, 0x0a9500f2, + 0x0b0f01cb, 0x0bf401ae, 0x0ccb0195, 0x0d950180, 0x0e56016e, 0x0f0d015e, 0x0fbc0150, 0x10630143, + 0x11070264, 0x1238023e, 0x1357021d, 0x14660201, 0x156601e9, 0x165a01d3, 0x174401c0, 0x182401af, + 0x18fe0331, 0x1a9602fe, 0x1c1502d2, 0x1d7e02ad, 0x1ed4028d, 0x201a0270, 0x21520256, 0x227d0240, + 0x239f0443, 0x25c003fe, 0x27bf03c4, 0x29a10392, 0x2b6a0367, 0x2d1d0341, 0x2ebe031f, 0x304d0300, + 0x31d105b0, 0x34a80555, 0x37520507, 0x39d504c5, 0x3c37048b, 0x3e7c0458, 0x40a8042a, 0x42bd0401, + 0x44c20798, 0x488e071e, 0x4c1c06b6, 0x4f76065d, 0x52a50610, 0x55ac05cc, 0x5892058f, 0x5b590559, + 0x5e0c0a23, 0x631c0980, 0x67db08f6, 0x6c55087f, 0x70940818, 0x74a007bd, 0x787d076c, 0x7c330723, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float in) +{ + static const stbir__FP32 almostone = { 0x3f7fffff }; // 1-eps + static const stbir__FP32 minval = { (127-13) << 23 }; + stbir_uint32 tab,bias,scale,t; + stbir__FP32 f; + + // Clamp to [2^(-13), 1-eps]; these two values map to 0 and 1, respectively. + // The tests are carefully written so that NaNs map to 0, same as in the reference + // implementation. + if (!(in > minval.f)) // written this way to catch NaNs + in = minval.f; + if (in > almostone.f) + in = almostone.f; + + // Do the table lookup and unpack bias, scale + f.f = in; + tab = fp32_to_srgb8_tab4[(f.u - minval.u) >> 20]; + bias = (tab >> 16) << 9; + scale = tab & 0xffff; + + // Grab next-highest mantissa bits and perform linear interpolation + t = (f.u >> 12) & 0xff; + return (unsigned char) ((bias + scale*t) >> 16); +} + +#else +// sRGB transition values, scaled by 1<<28 +static int stbir__srgb_offset_to_linear_scaled[256] = +{ + 0, 40738, 122216, 203693, 285170, 366648, 448125, 529603, + 611080, 692557, 774035, 855852, 942009, 1033024, 1128971, 1229926, + 1335959, 1447142, 1563542, 1685229, 1812268, 1944725, 2082664, 2226148, + 2375238, 2529996, 2690481, 2856753, 3028870, 3206888, 3390865, 3580856, + 3776916, 3979100, 4187460, 4402049, 4622919, 4850123, 5083710, 5323731, + 5570236, 5823273, 6082892, 6349140, 6622065, 6901714, 7188133, 7481369, + 7781466, 8088471, 8402427, 8723380, 9051372, 9386448, 9728650, 10078021, + 10434603, 10798439, 11169569, 11548036, 11933879, 12327139, 12727857, 13136073, + 13551826, 13975156, 14406100, 14844697, 15290987, 15745007, 16206795, 16676389, + 17153826, 17639142, 18132374, 18633560, 19142734, 19659934, 20185196, 20718552, + 21260042, 21809696, 22367554, 22933648, 23508010, 24090680, 24681686, 25281066, + 25888850, 26505076, 27129772, 27762974, 28404716, 29055026, 29713942, 30381490, + 31057708, 31742624, 32436272, 33138682, 33849884, 34569912, 35298800, 36036568, + 36783260, 37538896, 38303512, 39077136, 39859796, 40651528, 41452360, 42262316, + 43081432, 43909732, 44747252, 45594016, 46450052, 47315392, 48190064, 49074096, + 49967516, 50870356, 51782636, 52704392, 53635648, 54576432, 55526772, 56486700, + 57456236, 58435408, 59424248, 60422780, 61431036, 62449032, 63476804, 64514376, + 65561776, 66619028, 67686160, 68763192, 69850160, 70947088, 72053992, 73170912, + 74297864, 75434880, 76581976, 77739184, 78906536, 80084040, 81271736, 82469648, + 83677792, 84896192, 86124888, 87363888, 88613232, 89872928, 91143016, 92423512, + 93714432, 95015816, 96327688, 97650056, 98982952, 100326408, 101680440, 103045072, + 104420320, 105806224, 107202800, 108610064, 110028048, 111456776, 112896264, 114346544, + 115807632, 117279552, 118762328, 120255976, 121760536, 123276016, 124802440, 126339832, + 127888216, 129447616, 131018048, 132599544, 134192112, 135795792, 137410592, 139036528, + 140673648, 142321952, 143981456, 145652208, 147334208, 149027488, 150732064, 152447968, + 154175200, 155913792, 157663776, 159425168, 161197984, 162982240, 164777968, 166585184, + 168403904, 170234160, 172075968, 173929344, 175794320, 177670896, 179559120, 181458992, + 183370528, 185293776, 187228736, 189175424, 191133888, 193104112, 195086128, 197079968, + 199085648, 201103184, 203132592, 205173888, 207227120, 209292272, 211369392, 213458480, + 215559568, 217672656, 219797792, 221934976, 224084240, 226245600, 228419056, 230604656, + 232802400, 235012320, 237234432, 239468736, 241715280, 243974080, 246245120, 248528464, + 250824112, 253132064, 255452368, 257785040, 260130080, 262487520, 264857376, 267239664, +}; + +static stbir_uint8 stbir__linear_to_srgb_uchar(float f) +{ + int x = (int) (f * (1 << 28)); // has headroom so you don't need to clamp + int v = 0; + int i; + + // Refine the guess with a short binary search. + i = v + 128; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 64; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 32; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 16; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 8; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 4; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 2; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + i = v + 1; if (x >= stbir__srgb_offset_to_linear_scaled[i]) v = i; + + return (stbir_uint8) v; +} +#endif + +static float stbir__filter_trapezoid(float x, float scale) +{ + float halfscale = scale / 2; + float t = 0.5f + halfscale; + STBIR_ASSERT(scale <= 1); + + x = (float)fabs(x); + + if (x >= t) + return 0; + else + { + float r = 0.5f - halfscale; + if (x <= r) + return 1; + else + return (t - x) / scale; + } +} + +static float stbir__support_trapezoid(float scale) +{ + STBIR_ASSERT(scale <= 1); + return 0.5f + scale / 2; +} + +static float stbir__filter_triangle(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x <= 1.0f) + return 1 - x; + else + return 0; +} + +static float stbir__filter_cubic(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (4 + x*x*(3*x - 6))/6; + else if (x < 2.0f) + return (8 + x*(-12 + x*(6 - x)))/6; + + return (0.0f); +} + +static float stbir__filter_catmullrom(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return 1 - x*x*(2.5f - 1.5f*x); + else if (x < 2.0f) + return 2 - x*(4 + x*(0.5f*x - 2.5f)); + + return (0.0f); +} + +static float stbir__filter_mitchell(float x, float s) +{ + STBIR__UNUSED_PARAM(s); + + x = (float)fabs(x); + + if (x < 1.0f) + return (16 + x*x*(21 * x - 36))/18; + else if (x < 2.0f) + return (32 + x*(-60 + x*(36 - 7*x)))/18; + + return (0.0f); +} + +static float stbir__support_zero(float s) +{ + STBIR__UNUSED_PARAM(s); + return 0; +} + +static float stbir__support_one(float s) +{ + STBIR__UNUSED_PARAM(s); + return 1; +} + +static float stbir__support_two(float s) +{ + STBIR__UNUSED_PARAM(s); + return 2; +} + +static stbir__filter_info stbir__filter_info_table[] = { + { NULL, stbir__support_zero }, + { stbir__filter_trapezoid, stbir__support_trapezoid }, + { stbir__filter_triangle, stbir__support_one }, + { stbir__filter_cubic, stbir__support_two }, + { stbir__filter_catmullrom, stbir__support_two }, + { stbir__filter_mitchell, stbir__support_two }, +}; + +stbir__inline static int stbir__use_upsampling(float ratio) +{ + return ratio > 1; +} + +stbir__inline static int stbir__use_width_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->horizontal_scale); +} + +stbir__inline static int stbir__use_height_upsampling(stbir__info* stbir_info) +{ + return stbir__use_upsampling(stbir_info->vertical_scale); +} + +// This is the maximum number of input samples that can affect an output sample +// with the given filter +static int stbir__get_filter_pixel_width(stbir_filter filter, float scale) +{ + STBIR_ASSERT(filter != 0); + STBIR_ASSERT(filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2 / scale); +} + +// This is how much to expand buffers to account for filters seeking outside +// the image boundaries. +static int stbir__get_filter_pixel_margin(stbir_filter filter, float scale) +{ + return stbir__get_filter_pixel_width(filter, scale) / 2; +} + +static int stbir__get_coefficient_width(stbir_filter filter, float scale) +{ + if (stbir__use_upsampling(scale)) + return (int)ceil(stbir__filter_info_table[filter].support(1 / scale) * 2); + else + return (int)ceil(stbir__filter_info_table[filter].support(scale) * 2); +} + +static int stbir__get_contributors(float scale, stbir_filter filter, int input_size, int output_size) +{ + if (stbir__use_upsampling(scale)) + return output_size; + else + return (input_size + stbir__get_filter_pixel_margin(filter, scale) * 2); +} + +static int stbir__get_total_horizontal_coefficients(stbir__info* info) +{ + return info->horizontal_num_contributors + * stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); +} + +static int stbir__get_total_vertical_coefficients(stbir__info* info) +{ + return info->vertical_num_contributors + * stbir__get_coefficient_width (info->vertical_filter, info->vertical_scale); +} + +static stbir__contributors* stbir__get_contributor(stbir__contributors* contributors, int n) +{ + return &contributors[n]; +} + +// For perf reasons this code is duplicated in stbir__resample_horizontal_upsample/downsample, +// if you change it here change it there too. +static float* stbir__get_coefficient(float* coefficients, stbir_filter filter, float scale, int n, int c) +{ + int width = stbir__get_coefficient_width(filter, scale); + return &coefficients[width*n + c]; +} + +static int stbir__edge_wrap_slow(stbir_edge edge, int n, int max) +{ + switch (edge) + { + case STBIR_EDGE_ZERO: + return 0; // we'll decode the wrong pixel here, and then overwrite with 0s later + + case STBIR_EDGE_CLAMP: + if (n < 0) + return 0; + + if (n >= max) + return max - 1; + + return n; // NOTREACHED + + case STBIR_EDGE_REFLECT: + { + if (n < 0) + { + if (n < max) + return -n; + else + return max - 1; + } + + if (n >= max) + { + int max2 = max * 2; + if (n >= max2) + return 0; + else + return max2 - n - 1; + } + + return n; // NOTREACHED + } + + case STBIR_EDGE_WRAP: + if (n >= 0) + return (n % max); + else + { + int m = (-n) % max; + + if (m != 0) + m = max - m; + + return (m); + } + // NOTREACHED + + default: + STBIR_ASSERT(!"Unimplemented edge type"); + return 0; + } +} + +stbir__inline static int stbir__edge_wrap(stbir_edge edge, int n, int max) +{ + // avoid per-pixel switch + if (n >= 0 && n < max) + return n; + return stbir__edge_wrap_slow(edge, n, max); +} + +// What input pixels contribute to this output pixel? +static void stbir__calculate_sample_range_upsample(int n, float out_filter_radius, float scale_ratio, float out_shift, int* in_first_pixel, int* in_last_pixel, float* in_center_of_out) +{ + float out_pixel_center = (float)n + 0.5f; + float out_pixel_influence_lowerbound = out_pixel_center - out_filter_radius; + float out_pixel_influence_upperbound = out_pixel_center + out_filter_radius; + + float in_pixel_influence_lowerbound = (out_pixel_influence_lowerbound + out_shift) / scale_ratio; + float in_pixel_influence_upperbound = (out_pixel_influence_upperbound + out_shift) / scale_ratio; + + *in_center_of_out = (out_pixel_center + out_shift) / scale_ratio; + *in_first_pixel = (int)(floor(in_pixel_influence_lowerbound + 0.5)); + *in_last_pixel = (int)(floor(in_pixel_influence_upperbound - 0.5)); +} + +// What output pixels does this input pixel contribute to? +static void stbir__calculate_sample_range_downsample(int n, float in_pixels_radius, float scale_ratio, float out_shift, int* out_first_pixel, int* out_last_pixel, float* out_center_of_in) +{ + float in_pixel_center = (float)n + 0.5f; + float in_pixel_influence_lowerbound = in_pixel_center - in_pixels_radius; + float in_pixel_influence_upperbound = in_pixel_center + in_pixels_radius; + + float out_pixel_influence_lowerbound = in_pixel_influence_lowerbound * scale_ratio - out_shift; + float out_pixel_influence_upperbound = in_pixel_influence_upperbound * scale_ratio - out_shift; + + *out_center_of_in = in_pixel_center * scale_ratio - out_shift; + *out_first_pixel = (int)(floor(out_pixel_influence_lowerbound + 0.5)); + *out_last_pixel = (int)(floor(out_pixel_influence_upperbound - 0.5)); +} + +static void stbir__calculate_coefficients_upsample(stbir_filter filter, float scale, int in_first_pixel, int in_last_pixel, float in_center_of_out, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + float total_filter = 0; + float filter_scale; + + STBIR_ASSERT(in_last_pixel - in_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(1/scale) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = in_first_pixel; + contributor->n1 = in_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + { + float in_pixel_center = (float)(i + in_first_pixel) + 0.5f; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(in_center_of_out - in_pixel_center, 1 / scale); + + // If the coefficient is zero, skip it. (Don't do the <0 check here, we want the influence of those outside pixels.) + if (i == 0 && !coefficient_group[i]) + { + contributor->n0 = ++in_first_pixel; + i--; + continue; + } + + total_filter += coefficient_group[i]; + } + + // NOTE(fg): Not actually true in general, nor is there any reason to expect it should be. + // It would be true in exact math but is at best approximately true in floating-point math, + // and it would not make sense to try and put actual bounds on this here because it depends + // on the image aspect ratio which can get pretty extreme. + //STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(in_last_pixel + 1) + 0.5f - in_center_of_out, 1/scale) == 0); + + STBIR_ASSERT(total_filter > 0.9); + STBIR_ASSERT(total_filter < 1.1f); // Make sure it's not way off. + + // Make sure the sum of all coefficients is 1. + filter_scale = 1 / total_filter; + + for (i = 0; i <= in_last_pixel - in_first_pixel; i++) + coefficient_group[i] *= filter_scale; + + for (i = in_last_pixel - in_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__calculate_coefficients_downsample(stbir_filter filter, float scale_ratio, int out_first_pixel, int out_last_pixel, float out_center_of_in, stbir__contributors* contributor, float* coefficient_group) +{ + int i; + + STBIR_ASSERT(out_last_pixel - out_first_pixel <= (int)ceil(stbir__filter_info_table[filter].support(scale_ratio) * 2)); // Taken directly from stbir__get_coefficient_width() which we can't call because we don't know if we're horizontal or vertical. + + contributor->n0 = out_first_pixel; + contributor->n1 = out_last_pixel; + + STBIR_ASSERT(contributor->n1 >= contributor->n0); + + for (i = 0; i <= out_last_pixel - out_first_pixel; i++) + { + float out_pixel_center = (float)(i + out_first_pixel) + 0.5f; + float x = out_pixel_center - out_center_of_in; + coefficient_group[i] = stbir__filter_info_table[filter].kernel(x, scale_ratio) * scale_ratio; + } + + // NOTE(fg): Not actually true in general, nor is there any reason to expect it should be. + // It would be true in exact math but is at best approximately true in floating-point math, + // and it would not make sense to try and put actual bounds on this here because it depends + // on the image aspect ratio which can get pretty extreme. + //STBIR_ASSERT(stbir__filter_info_table[filter].kernel((float)(out_last_pixel + 1) + 0.5f - out_center_of_in, scale_ratio) == 0); + + for (i = out_last_pixel - out_first_pixel; i >= 0; i--) + { + if (coefficient_group[i]) + break; + + // This line has no weight. We can skip it. + contributor->n1 = contributor->n0 + i - 1; + } +} + +static void stbir__normalize_downsample_coefficients(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, int input_size, int output_size) +{ + int num_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + int num_coefficients = stbir__get_coefficient_width(filter, scale_ratio); + int i, j; + int skip; + + for (i = 0; i < output_size; i++) + { + float scale; + float total = 0; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + { + float coefficient = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0); + total += coefficient; + } + else if (i < contributors[j].n0) + break; + } + + STBIR_ASSERT(total > 0.9f); + STBIR_ASSERT(total < 1.1f); + + scale = 1 / total; + + for (j = 0; j < num_contributors; j++) + { + if (i >= contributors[j].n0 && i <= contributors[j].n1) + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i - contributors[j].n0) *= scale; + else if (i < contributors[j].n0) + break; + } + } + + // Optimize: Skip zero coefficients and contributions outside of image bounds. + // Do this after normalizing because normalization depends on the n0/n1 values. + for (j = 0; j < num_contributors; j++) + { + int range, max, width; + + skip = 0; + while (*stbir__get_coefficient(coefficients, filter, scale_ratio, j, skip) == 0) + skip++; + + contributors[j].n0 += skip; + + while (contributors[j].n0 < 0) + { + contributors[j].n0++; + skip++; + } + + range = contributors[j].n1 - contributors[j].n0 + 1; + max = stbir__min(num_coefficients, range); + + width = stbir__get_coefficient_width(filter, scale_ratio); + for (i = 0; i < max; i++) + { + if (i + skip >= width) + break; + + *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i) = *stbir__get_coefficient(coefficients, filter, scale_ratio, j, i + skip); + } + + continue; + } + + // Using min to avoid writing into invalid pixels. + for (i = 0; i < num_contributors; i++) + contributors[i].n1 = stbir__min(contributors[i].n1, output_size - 1); +} + +// Each scan line uses the same kernel values so we should calculate the kernel +// values once and then we can use them for every scan line. +static void stbir__calculate_filters(stbir__contributors* contributors, float* coefficients, stbir_filter filter, float scale_ratio, float shift, int input_size, int output_size) +{ + int n; + int total_contributors = stbir__get_contributors(scale_ratio, filter, input_size, output_size); + + if (stbir__use_upsampling(scale_ratio)) + { + float out_pixels_radius = stbir__filter_info_table[filter].support(1 / scale_ratio) * scale_ratio; + + // Looping through out pixels + for (n = 0; n < total_contributors; n++) + { + float in_center_of_out; // Center of the current out pixel in the in pixel space + int in_first_pixel, in_last_pixel; + + stbir__calculate_sample_range_upsample(n, out_pixels_radius, scale_ratio, shift, &in_first_pixel, &in_last_pixel, &in_center_of_out); + + stbir__calculate_coefficients_upsample(filter, scale_ratio, in_first_pixel, in_last_pixel, in_center_of_out, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + } + else + { + float in_pixels_radius = stbir__filter_info_table[filter].support(scale_ratio) / scale_ratio; + + // Looping through in pixels + for (n = 0; n < total_contributors; n++) + { + float out_center_of_in; // Center of the current out pixel in the in pixel space + int out_first_pixel, out_last_pixel; + int n_adjusted = n - stbir__get_filter_pixel_margin(filter, scale_ratio); + + stbir__calculate_sample_range_downsample(n_adjusted, in_pixels_radius, scale_ratio, shift, &out_first_pixel, &out_last_pixel, &out_center_of_in); + + stbir__calculate_coefficients_downsample(filter, scale_ratio, out_first_pixel, out_last_pixel, out_center_of_in, stbir__get_contributor(contributors, n), stbir__get_coefficient(coefficients, filter, scale_ratio, n, 0)); + } + + stbir__normalize_downsample_coefficients(contributors, coefficients, filter, scale_ratio, input_size, output_size); + } +} + +static float* stbir__get_decode_buffer(stbir__info* stbir_info) +{ + // The 0 index of the decode buffer starts after the margin. This makes + // it okay to use negative indexes on the decode buffer. + return &stbir_info->decode_buffer[stbir_info->horizontal_filter_pixel_margin * stbir_info->channels]; +} + +#define STBIR__DECODE(type, colorspace) ((int)(type) * (STBIR_MAX_COLORSPACES) + (int)(colorspace)) + +static void stbir__decode_scanline(stbir__info* stbir_info, int n) +{ + int c; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int input_w = stbir_info->input_w; + size_t input_stride_bytes = stbir_info->input_stride_bytes; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir_edge edge_horizontal = stbir_info->edge_horizontal; + stbir_edge edge_vertical = stbir_info->edge_vertical; + size_t in_buffer_row_offset = stbir__edge_wrap(edge_vertical, n, stbir_info->input_h) * input_stride_bytes; + const void* input_data = (char *) stbir_info->input_data + in_buffer_row_offset; + int max_x = input_w + stbir_info->horizontal_filter_pixel_margin; + int decode = STBIR__DECODE(type, colorspace); + + int x = -stbir_info->horizontal_filter_pixel_margin; + + // special handling for STBIR_EDGE_ZERO because it needs to return an item that doesn't appear in the input, + // and we want to avoid paying overhead on every pixel if not STBIR_EDGE_ZERO + if (edge_vertical == STBIR_EDGE_ZERO && (n < 0 || n >= stbir_info->input_h)) + { + for (; x < max_x; x++) + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + return; + } + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned char*)input_data)[input_pixel_index + c]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_uchar_to_linear_float[((const unsigned char*)input_data)[input_pixel_index + c]]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned char*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint8_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((float)((const unsigned short*)input_data)[input_pixel_index + c]) / stbir__max_uint16_as_float); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((float)((const unsigned short*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint16_as_float; + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear((float)(((double)((const unsigned int*)input_data)[input_pixel_index + c]) / stbir__max_uint32_as_float)); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = (float)(((double)((const unsigned int*)input_data)[input_pixel_index + alpha_channel]) / stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = ((const float*)input_data)[input_pixel_index + c]; + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (; x < max_x; x++) + { + int decode_pixel_index = x * channels; + int input_pixel_index = stbir__edge_wrap(edge_horizontal, x, input_w) * channels; + for (c = 0; c < channels; c++) + decode_buffer[decode_pixel_index + c] = stbir__srgb_to_linear(((const float*)input_data)[input_pixel_index + c]); + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + decode_buffer[decode_pixel_index + alpha_channel] = ((const float*)input_data)[input_pixel_index + alpha_channel]; + } + + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < max_x; x++) + { + int decode_pixel_index = x * channels; + + // If the alpha value is 0 it will clobber the color values. Make sure it's not. + float alpha = decode_buffer[decode_pixel_index + alpha_channel]; +#ifndef STBIR_NO_ALPHA_EPSILON + if (stbir_info->type != STBIR_TYPE_FLOAT) { + alpha += STBIR_ALPHA_EPSILON; + decode_buffer[decode_pixel_index + alpha_channel] = alpha; + } +#endif + for (c = 0; c < channels; c++) + { + if (c == alpha_channel) + continue; + + decode_buffer[decode_pixel_index + c] *= alpha; + } + } + } + + if (edge_horizontal == STBIR_EDGE_ZERO) + { + for (x = -stbir_info->horizontal_filter_pixel_margin; x < 0; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + for (x = input_w; x < max_x; x++) + { + for (c = 0; c < channels; c++) + decode_buffer[x*channels + c] = 0; + } + } +} + +static float* stbir__get_ring_buffer_entry(float* ring_buffer, int index, int ring_buffer_length) +{ + return &ring_buffer[index * ring_buffer_length]; +} + +static float* stbir__add_empty_ring_buffer_entry(stbir__info* stbir_info, int n) +{ + int ring_buffer_index; + float* ring_buffer; + + stbir_info->ring_buffer_last_scanline = n; + + if (stbir_info->ring_buffer_begin_index < 0) + { + ring_buffer_index = stbir_info->ring_buffer_begin_index = 0; + stbir_info->ring_buffer_first_scanline = n; + } + else + { + ring_buffer_index = (stbir_info->ring_buffer_begin_index + (stbir_info->ring_buffer_last_scanline - stbir_info->ring_buffer_first_scanline)) % stbir_info->ring_buffer_num_entries; + STBIR_ASSERT(ring_buffer_index != stbir_info->ring_buffer_begin_index); + } + + ring_buffer = stbir__get_ring_buffer_entry(stbir_info->ring_buffer, ring_buffer_index, stbir_info->ring_buffer_length_bytes / sizeof(float)); + memset(ring_buffer, 0, stbir_info->ring_buffer_length_bytes); + + return ring_buffer; +} + + +static void stbir__resample_horizontal_upsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int output_w = stbir_info->output_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + + for (x = 0; x < output_w; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int out_pixel_index = x * channels; + int coefficient_group = coefficient_width * x; + int coefficient_counter = 0; + + STBIR_ASSERT(n1 >= n0); + STBIR_ASSERT(n0 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 >= -stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n0 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + STBIR_ASSERT(n1 < stbir_info->input_w + stbir_info->horizontal_filter_pixel_margin); + + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + STBIR_ASSERT(coefficient != 0); + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (k = n0; k <= n1; k++) + { + int in_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + coefficient_counter++]; + int c; + STBIR_ASSERT(coefficient != 0); + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__resample_horizontal_downsample(stbir__info* stbir_info, float* output_buffer) +{ + int x, k; + int input_w = stbir_info->input_w; + int channels = stbir_info->channels; + float* decode_buffer = stbir__get_decode_buffer(stbir_info); + stbir__contributors* horizontal_contributors = stbir_info->horizontal_contributors; + float* horizontal_coefficients = stbir_info->horizontal_coefficients; + int coefficient_width = stbir_info->horizontal_coefficient_width; + int filter_pixel_margin = stbir_info->horizontal_filter_pixel_margin; + int max_x = input_w + filter_pixel_margin * 2; + + STBIR_ASSERT(!stbir__use_width_upsampling(stbir_info)); + + switch (channels) { + case 1: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 1; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 1; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + } + } + break; + + case 2: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 2; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 2; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + } + } + break; + + case 3: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 3; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 3; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + } + } + break; + + case 4: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * 4; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int out_pixel_index = k * 4; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + output_buffer[out_pixel_index + 0] += decode_buffer[in_pixel_index + 0] * coefficient; + output_buffer[out_pixel_index + 1] += decode_buffer[in_pixel_index + 1] * coefficient; + output_buffer[out_pixel_index + 2] += decode_buffer[in_pixel_index + 2] * coefficient; + output_buffer[out_pixel_index + 3] += decode_buffer[in_pixel_index + 3] * coefficient; + } + } + break; + + default: + for (x = 0; x < max_x; x++) + { + int n0 = horizontal_contributors[x].n0; + int n1 = horizontal_contributors[x].n1; + + int in_x = x - filter_pixel_margin; + int in_pixel_index = in_x * channels; + int max_n = n1; + int coefficient_group = coefficient_width * x; + + for (k = n0; k <= max_n; k++) + { + int c; + int out_pixel_index = k * channels; + float coefficient = horizontal_coefficients[coefficient_group + k - n0]; + for (c = 0; c < channels; c++) + output_buffer[out_pixel_index + c] += decode_buffer[in_pixel_index + c] * coefficient; + } + } + break; + } +} + +static void stbir__decode_and_resample_upsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + // Now resample it into the ring buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + else + stbir__resample_horizontal_downsample(stbir_info, stbir__add_empty_ring_buffer_entry(stbir_info, n)); + + // Now it's sitting in the ring buffer ready to be used as source for the vertical sampling. +} + +static void stbir__decode_and_resample_downsample(stbir__info* stbir_info, int n) +{ + // Decode the nth scanline from the source image into the decode buffer. + stbir__decode_scanline(stbir_info, n); + + memset(stbir_info->horizontal_buffer, 0, stbir_info->output_w * stbir_info->channels * sizeof(float)); + + // Now resample it into the horizontal buffer. + if (stbir__use_width_upsampling(stbir_info)) + stbir__resample_horizontal_upsample(stbir_info, stbir_info->horizontal_buffer); + else + stbir__resample_horizontal_downsample(stbir_info, stbir_info->horizontal_buffer); + + // Now it's sitting in the horizontal buffer ready to be distributed into the ring buffers. +} + +// Get the specified scan line from the ring buffer. +static float* stbir__get_ring_buffer_scanline(int get_scanline, float* ring_buffer, int begin_index, int first_scanline, int ring_buffer_num_entries, int ring_buffer_length) +{ + int ring_buffer_index = (begin_index + (get_scanline - first_scanline)) % ring_buffer_num_entries; + return stbir__get_ring_buffer_entry(ring_buffer, ring_buffer_index, ring_buffer_length); +} + + +static void stbir__encode_scanline(stbir__info* stbir_info, int num_pixels, void *output_buffer, float *encode_buffer, int channels, int alpha_channel, int decode) +{ + int x; + int n; + int num_nonalpha; + stbir_uint16 nonalpha[STBIR_MAX_CHANNELS]; + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) + { + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + float alpha = encode_buffer[pixel_index + alpha_channel]; + float reciprocal_alpha = alpha ? 1.0f / alpha : 0; + + // unrolling this produced a 1% slowdown upscaling a large RGBA linear-space image on my machine - stb + for (n = 0; n < channels; n++) + if (n != alpha_channel) + encode_buffer[pixel_index + n] *= reciprocal_alpha; + + // We added in a small epsilon to prevent the color channel from being deleted with zero alpha. + // Because we only add it for integer types, it will automatically be discarded on integer + // conversion, so we don't need to subtract it back out (which would be problematic for + // numeric precision reasons). + } + } + + // build a table of all channels that need colorspace correction, so + // we don't perform colorspace correction on channels that don't need it. + for (x = 0, num_nonalpha = 0; x < channels; ++x) + { + if (x != alpha_channel || (stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + { + nonalpha[num_nonalpha++] = (stbir_uint16)x; + } + } + + #define STBIR__ROUND_INT(f) ((int) ((f)+0.5)) + #define STBIR__ROUND_UINT(f) ((stbir_uint32) ((f)+0.5)) + + #ifdef STBIR__SATURATE_INT + #define STBIR__ENCODE_LINEAR8(f) stbir__saturate8 (STBIR__ROUND_INT((f) * stbir__max_uint8_as_float )) + #define STBIR__ENCODE_LINEAR16(f) stbir__saturate16(STBIR__ROUND_INT((f) * stbir__max_uint16_as_float)) + #else + #define STBIR__ENCODE_LINEAR8(f) (unsigned char ) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint8_as_float ) + #define STBIR__ENCODE_LINEAR16(f) (unsigned short) STBIR__ROUND_INT(stbir__saturate(f) * stbir__max_uint16_as_float) + #endif + + switch (decode) + { + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned char*)output_buffer)[index] = STBIR__ENCODE_LINEAR8(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT8, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned char*)output_buffer)[index] = stbir__linear_to_srgb_uchar(encode_buffer[index]); + } + + if (!(stbir_info->flags & STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned char *)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR8(encode_buffer[pixel_index+alpha_channel]); + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned short*)output_buffer)[index] = STBIR__ENCODE_LINEAR16(encode_buffer[index]); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT16, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned short*)output_buffer)[index] = (unsigned short)STBIR__ROUND_INT(stbir__linear_to_srgb(stbir__saturate(encode_buffer[index])) * stbir__max_uint16_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned short*)output_buffer)[pixel_index + alpha_channel] = STBIR__ENCODE_LINEAR16(encode_buffer[pixel_index + alpha_channel]); + } + + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__saturate(encode_buffer[index])) * stbir__max_uint32_as_float); + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_UINT32, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((unsigned int*)output_buffer)[index] = (unsigned int)STBIR__ROUND_UINT(((double)stbir__linear_to_srgb(stbir__saturate(encode_buffer[index]))) * stbir__max_uint32_as_float); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((unsigned int*)output_buffer)[pixel_index + alpha_channel] = (unsigned int)STBIR__ROUND_INT(((double)stbir__saturate(encode_buffer[pixel_index + alpha_channel])) * stbir__max_uint32_as_float); + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_LINEAR): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < channels; n++) + { + int index = pixel_index + n; + ((float*)output_buffer)[index] = encode_buffer[index]; + } + } + break; + + case STBIR__DECODE(STBIR_TYPE_FLOAT, STBIR_COLORSPACE_SRGB): + for (x=0; x < num_pixels; ++x) + { + int pixel_index = x*channels; + + for (n = 0; n < num_nonalpha; n++) + { + int index = pixel_index + nonalpha[n]; + ((float*)output_buffer)[index] = stbir__linear_to_srgb(encode_buffer[index]); + } + + if (!(stbir_info->flags&STBIR_FLAG_ALPHA_USES_COLORSPACE)) + ((float*)output_buffer)[pixel_index + alpha_channel] = encode_buffer[pixel_index + alpha_channel]; + } + break; + + default: + STBIR_ASSERT(!"Unknown type/colorspace/channels combination."); + break; + } +} + +static void stbir__resample_vertical_upsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + void* output_data = stbir_info->output_data; + float* encode_buffer = stbir_info->encode_buffer; + int decode = STBIR__DECODE(type, colorspace); + int coefficient_width = stbir_info->vertical_coefficient_width; + int coefficient_counter; + int contributor = n; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + int n0,n1, output_row_start; + int coefficient_group = coefficient_width * contributor; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + output_row_start = n * stbir_info->output_stride_bytes; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + memset(encode_buffer, 0, output_w * sizeof(float) * channels); + + // I tried reblocking this for better cache usage of encode_buffer + // (using x_outer, k, x_inner), but it lost speed. -- stb + + coefficient_counter = 0; + switch (channels) { + case 1: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 1; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + } + } + break; + case 2: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 2; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + } + } + break; + case 3: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 3; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + } + } + break; + case 4: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * 4; + encode_buffer[in_pixel_index + 0] += ring_buffer_entry[in_pixel_index + 0] * coefficient; + encode_buffer[in_pixel_index + 1] += ring_buffer_entry[in_pixel_index + 1] * coefficient; + encode_buffer[in_pixel_index + 2] += ring_buffer_entry[in_pixel_index + 2] * coefficient; + encode_buffer[in_pixel_index + 3] += ring_buffer_entry[in_pixel_index + 3] * coefficient; + } + } + break; + default: + for (k = n0; k <= n1; k++) + { + int coefficient_index = coefficient_counter++; + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + for (x = 0; x < output_w; ++x) + { + int in_pixel_index = x * channels; + int c; + for (c = 0; c < channels; c++) + encode_buffer[in_pixel_index + c] += ring_buffer_entry[in_pixel_index + c] * coefficient; + } + } + break; + } + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, encode_buffer, channels, alpha_channel, decode); +} + +static void stbir__resample_vertical_downsample(stbir__info* stbir_info, int n) +{ + int x, k; + int output_w = stbir_info->output_w; + stbir__contributors* vertical_contributors = stbir_info->vertical_contributors; + float* vertical_coefficients = stbir_info->vertical_coefficients; + int channels = stbir_info->channels; + int ring_buffer_entries = stbir_info->ring_buffer_num_entries; + float* horizontal_buffer = stbir_info->horizontal_buffer; + int coefficient_width = stbir_info->vertical_coefficient_width; + int contributor = n + stbir_info->vertical_filter_pixel_margin; + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_begin_index = stbir_info->ring_buffer_begin_index; + int ring_buffer_first_scanline = stbir_info->ring_buffer_first_scanline; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + int n0,n1; + + n0 = vertical_contributors[contributor].n0; + n1 = vertical_contributors[contributor].n1; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (k = n0; k <= n1; k++) + { + int coefficient_index = k - n0; + int coefficient_group = coefficient_width * contributor; + float coefficient = vertical_coefficients[coefficient_group + coefficient_index]; + + float* ring_buffer_entry = stbir__get_ring_buffer_scanline(k, ring_buffer, ring_buffer_begin_index, ring_buffer_first_scanline, ring_buffer_entries, ring_buffer_length); + + switch (channels) { + case 1: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 1; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + } + break; + case 2: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 2; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + } + break; + case 3: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 3; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + } + break; + case 4: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * 4; + ring_buffer_entry[in_pixel_index + 0] += horizontal_buffer[in_pixel_index + 0] * coefficient; + ring_buffer_entry[in_pixel_index + 1] += horizontal_buffer[in_pixel_index + 1] * coefficient; + ring_buffer_entry[in_pixel_index + 2] += horizontal_buffer[in_pixel_index + 2] * coefficient; + ring_buffer_entry[in_pixel_index + 3] += horizontal_buffer[in_pixel_index + 3] * coefficient; + } + break; + default: + for (x = 0; x < output_w; x++) + { + int in_pixel_index = x * channels; + + int c; + for (c = 0; c < channels; c++) + ring_buffer_entry[in_pixel_index + c] += horizontal_buffer[in_pixel_index + c] * coefficient; + } + break; + } + } +} + +static void stbir__buffer_loop_upsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + float out_scanlines_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(1/scale_ratio) * scale_ratio; + + STBIR_ASSERT(stbir__use_height_upsampling(stbir_info)); + + for (y = 0; y < stbir_info->output_h; y++) + { + float in_center_of_out = 0; // Center of the current out scanline in the in scanline space + int in_first_scanline = 0, in_last_scanline = 0; + + stbir__calculate_sample_range_upsample(y, out_scanlines_radius, scale_ratio, stbir_info->vertical_shift, &in_first_scanline, &in_last_scanline, &in_center_of_out); + + STBIR_ASSERT(in_last_scanline - in_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (in_first_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__decode_and_resample_upsample(stbir_info, in_first_scanline); + + while (in_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__decode_and_resample_upsample(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now all buffers should be ready to write a row of vertical sampling. + stbir__resample_vertical_upsample(stbir_info, y); + + STBIR_PROGRESS_REPORT((float)y / stbir_info->output_h); + } +} + +static void stbir__empty_ring_buffer(stbir__info* stbir_info, int first_necessary_scanline) +{ + int output_stride_bytes = stbir_info->output_stride_bytes; + int channels = stbir_info->channels; + int alpha_channel = stbir_info->alpha_channel; + int type = stbir_info->type; + int colorspace = stbir_info->colorspace; + int output_w = stbir_info->output_w; + void* output_data = stbir_info->output_data; + int decode = STBIR__DECODE(type, colorspace); + + float* ring_buffer = stbir_info->ring_buffer; + int ring_buffer_length = stbir_info->ring_buffer_length_bytes/sizeof(float); + + if (stbir_info->ring_buffer_begin_index >= 0) + { + // Get rid of whatever we don't need anymore. + while (first_necessary_scanline > stbir_info->ring_buffer_first_scanline) + { + if (stbir_info->ring_buffer_first_scanline >= 0 && stbir_info->ring_buffer_first_scanline < stbir_info->output_h) + { + int output_row_start = stbir_info->ring_buffer_first_scanline * output_stride_bytes; + float* ring_buffer_entry = stbir__get_ring_buffer_entry(ring_buffer, stbir_info->ring_buffer_begin_index, ring_buffer_length); + stbir__encode_scanline(stbir_info, output_w, (char *) output_data + output_row_start, ring_buffer_entry, channels, alpha_channel, decode); + STBIR_PROGRESS_REPORT((float)stbir_info->ring_buffer_first_scanline / stbir_info->output_h); + } + + if (stbir_info->ring_buffer_first_scanline == stbir_info->ring_buffer_last_scanline) + { + // We just popped the last scanline off the ring buffer. + // Reset it to the empty state. + stbir_info->ring_buffer_begin_index = -1; + stbir_info->ring_buffer_first_scanline = 0; + stbir_info->ring_buffer_last_scanline = 0; + break; + } + else + { + stbir_info->ring_buffer_first_scanline++; + stbir_info->ring_buffer_begin_index = (stbir_info->ring_buffer_begin_index + 1) % stbir_info->ring_buffer_num_entries; + } + } + } +} + +static void stbir__buffer_loop_downsample(stbir__info* stbir_info) +{ + int y; + float scale_ratio = stbir_info->vertical_scale; + int output_h = stbir_info->output_h; + float in_pixels_radius = stbir__filter_info_table[stbir_info->vertical_filter].support(scale_ratio) / scale_ratio; + int pixel_margin = stbir_info->vertical_filter_pixel_margin; + int max_y = stbir_info->input_h + pixel_margin; + + STBIR_ASSERT(!stbir__use_height_upsampling(stbir_info)); + + for (y = -pixel_margin; y < max_y; y++) + { + float out_center_of_in; // Center of the current out scanline in the in scanline space + int out_first_scanline, out_last_scanline; + + stbir__calculate_sample_range_downsample(y, in_pixels_radius, scale_ratio, stbir_info->vertical_shift, &out_first_scanline, &out_last_scanline, &out_center_of_in); + + STBIR_ASSERT(out_last_scanline - out_first_scanline + 1 <= stbir_info->ring_buffer_num_entries); + + if (out_last_scanline < 0 || out_first_scanline >= output_h) + continue; + + stbir__empty_ring_buffer(stbir_info, out_first_scanline); + + stbir__decode_and_resample_downsample(stbir_info, y); + + // Load in new ones. + if (stbir_info->ring_buffer_begin_index < 0) + stbir__add_empty_ring_buffer_entry(stbir_info, out_first_scanline); + + while (out_last_scanline > stbir_info->ring_buffer_last_scanline) + stbir__add_empty_ring_buffer_entry(stbir_info, stbir_info->ring_buffer_last_scanline + 1); + + // Now the horizontal buffer is ready to write to all ring buffer rows. + stbir__resample_vertical_downsample(stbir_info, y); + } + + stbir__empty_ring_buffer(stbir_info, stbir_info->output_h); +} + +static void stbir__setup(stbir__info *info, int input_w, int input_h, int output_w, int output_h, int channels) +{ + info->input_w = input_w; + info->input_h = input_h; + info->output_w = output_w; + info->output_h = output_h; + info->channels = channels; +} + +static void stbir__calculate_transform(stbir__info *info, float s0, float t0, float s1, float t1, float *transform) +{ + info->s0 = s0; + info->t0 = t0; + info->s1 = s1; + info->t1 = t1; + + if (transform) + { + info->horizontal_scale = transform[0]; + info->vertical_scale = transform[1]; + info->horizontal_shift = transform[2]; + info->vertical_shift = transform[3]; + } + else + { + info->horizontal_scale = ((float)info->output_w / info->input_w) / (s1 - s0); + info->vertical_scale = ((float)info->output_h / info->input_h) / (t1 - t0); + + info->horizontal_shift = s0 * info->output_w / (s1 - s0); + info->vertical_shift = t0 * info->output_h / (t1 - t0); + } +} + +static void stbir__choose_filter(stbir__info *info, stbir_filter h_filter, stbir_filter v_filter) +{ + if (h_filter == 0) + h_filter = stbir__use_upsampling(info->horizontal_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + if (v_filter == 0) + v_filter = stbir__use_upsampling(info->vertical_scale) ? STBIR_DEFAULT_FILTER_UPSAMPLE : STBIR_DEFAULT_FILTER_DOWNSAMPLE; + info->horizontal_filter = h_filter; + info->vertical_filter = v_filter; +} + +static stbir_uint32 stbir__calculate_memory(stbir__info *info) +{ + int pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + int filter_height = stbir__get_filter_pixel_width(info->vertical_filter, info->vertical_scale); + + info->horizontal_num_contributors = stbir__get_contributors(info->horizontal_scale, info->horizontal_filter, info->input_w, info->output_w); + info->vertical_num_contributors = stbir__get_contributors(info->vertical_scale , info->vertical_filter , info->input_h, info->output_h); + + // One extra entry because floating point precision problems sometimes cause an extra to be necessary. + info->ring_buffer_num_entries = filter_height + 1; + + info->horizontal_contributors_size = info->horizontal_num_contributors * sizeof(stbir__contributors); + info->horizontal_coefficients_size = stbir__get_total_horizontal_coefficients(info) * sizeof(float); + info->vertical_contributors_size = info->vertical_num_contributors * sizeof(stbir__contributors); + info->vertical_coefficients_size = stbir__get_total_vertical_coefficients(info) * sizeof(float); + info->decode_buffer_size = (info->input_w + pixel_margin * 2) * info->channels * sizeof(float); + info->horizontal_buffer_size = info->output_w * info->channels * sizeof(float); + info->ring_buffer_size = info->output_w * info->channels * info->ring_buffer_num_entries * sizeof(float); + info->encode_buffer_size = info->output_w * info->channels * sizeof(float); + + STBIR_ASSERT(info->horizontal_filter != 0); + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + STBIR_ASSERT(info->vertical_filter != 0); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); // this now happens too late + + if (stbir__use_height_upsampling(info)) + // The horizontal buffer is for when we're downsampling the height and we + // can't output the result of sampling the decode buffer directly into the + // ring buffers. + info->horizontal_buffer_size = 0; + else + // The encode buffer is to retain precision in the height upsampling method + // and isn't used when height downsampling. + info->encode_buffer_size = 0; + + return info->horizontal_contributors_size + info->horizontal_coefficients_size + + info->vertical_contributors_size + info->vertical_coefficients_size + + info->decode_buffer_size + info->horizontal_buffer_size + + info->ring_buffer_size + info->encode_buffer_size; +} + +static int stbir__resize_allocated(stbir__info *info, + const void* input_data, int input_stride_in_bytes, + void* output_data, int output_stride_in_bytes, + int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace, + void* tempmem, size_t tempmem_size_in_bytes) +{ + size_t memory_required = stbir__calculate_memory(info); + + int width_stride_input = input_stride_in_bytes ? input_stride_in_bytes : info->channels * info->input_w * stbir__type_size[type]; + int width_stride_output = output_stride_in_bytes ? output_stride_in_bytes : info->channels * info->output_w * stbir__type_size[type]; + +#ifdef STBIR_DEBUG_OVERWRITE_TEST +#define OVERWRITE_ARRAY_SIZE 8 + unsigned char overwrite_output_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_before_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_output_after_pre[OVERWRITE_ARRAY_SIZE]; + unsigned char overwrite_tempmem_after_pre[OVERWRITE_ARRAY_SIZE]; + + size_t begin_forbidden = width_stride_output * (info->output_h - 1) + info->output_w * info->channels * stbir__type_size[type]; + memcpy(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE); + memcpy(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE); +#endif + + STBIR_ASSERT(info->channels >= 0); + STBIR_ASSERT(info->channels <= STBIR_MAX_CHANNELS); + + if (info->channels < 0 || info->channels > STBIR_MAX_CHANNELS) + return 0; + + STBIR_ASSERT(info->horizontal_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + STBIR_ASSERT(info->vertical_filter < STBIR__ARRAY_SIZE(stbir__filter_info_table)); + + if (info->horizontal_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + if (info->vertical_filter >= STBIR__ARRAY_SIZE(stbir__filter_info_table)) + return 0; + + if (alpha_channel < 0) + flags |= STBIR_FLAG_ALPHA_USES_COLORSPACE | STBIR_FLAG_ALPHA_PREMULTIPLIED; + + if (!(flags&STBIR_FLAG_ALPHA_USES_COLORSPACE) || !(flags&STBIR_FLAG_ALPHA_PREMULTIPLIED)) { + STBIR_ASSERT(alpha_channel >= 0 && alpha_channel < info->channels); + } + + if (alpha_channel >= info->channels) + return 0; + + STBIR_ASSERT(tempmem); + + if (!tempmem) + return 0; + + STBIR_ASSERT(tempmem_size_in_bytes >= memory_required); + + if (tempmem_size_in_bytes < memory_required) + return 0; + + memset(tempmem, 0, tempmem_size_in_bytes); + + info->input_data = input_data; + info->input_stride_bytes = width_stride_input; + + info->output_data = output_data; + info->output_stride_bytes = width_stride_output; + + info->alpha_channel = alpha_channel; + info->flags = flags; + info->type = type; + info->edge_horizontal = edge_horizontal; + info->edge_vertical = edge_vertical; + info->colorspace = colorspace; + + info->horizontal_coefficient_width = stbir__get_coefficient_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_coefficient_width = stbir__get_coefficient_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_width = stbir__get_filter_pixel_width (info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_width = stbir__get_filter_pixel_width (info->vertical_filter , info->vertical_scale ); + info->horizontal_filter_pixel_margin = stbir__get_filter_pixel_margin(info->horizontal_filter, info->horizontal_scale); + info->vertical_filter_pixel_margin = stbir__get_filter_pixel_margin(info->vertical_filter , info->vertical_scale ); + + info->ring_buffer_length_bytes = info->output_w * info->channels * sizeof(float); + info->decode_buffer_pixels = info->input_w + info->horizontal_filter_pixel_margin * 2; + +#define STBIR__NEXT_MEMPTR(current, newtype) (newtype*)(((unsigned char*)current) + current##_size) + + info->horizontal_contributors = (stbir__contributors *) tempmem; + info->horizontal_coefficients = STBIR__NEXT_MEMPTR(info->horizontal_contributors, float); + info->vertical_contributors = STBIR__NEXT_MEMPTR(info->horizontal_coefficients, stbir__contributors); + info->vertical_coefficients = STBIR__NEXT_MEMPTR(info->vertical_contributors, float); + info->decode_buffer = STBIR__NEXT_MEMPTR(info->vertical_coefficients, float); + + if (stbir__use_height_upsampling(info)) + { + info->horizontal_buffer = NULL; + info->ring_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->encode_buffer = STBIR__NEXT_MEMPTR(info->ring_buffer, float); + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->encode_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + else + { + info->horizontal_buffer = STBIR__NEXT_MEMPTR(info->decode_buffer, float); + info->ring_buffer = STBIR__NEXT_MEMPTR(info->horizontal_buffer, float); + info->encode_buffer = NULL; + + STBIR_ASSERT((size_t)STBIR__NEXT_MEMPTR(info->ring_buffer, unsigned char) == (size_t)tempmem + tempmem_size_in_bytes); + } + +#undef STBIR__NEXT_MEMPTR + + // This signals that the ring buffer is empty + info->ring_buffer_begin_index = -1; + + stbir__calculate_filters(info->horizontal_contributors, info->horizontal_coefficients, info->horizontal_filter, info->horizontal_scale, info->horizontal_shift, info->input_w, info->output_w); + stbir__calculate_filters(info->vertical_contributors, info->vertical_coefficients, info->vertical_filter, info->vertical_scale, info->vertical_shift, info->input_h, info->output_h); + + STBIR_PROGRESS_REPORT(0); + + if (stbir__use_height_upsampling(info)) + stbir__buffer_loop_upsample(info); + else + stbir__buffer_loop_downsample(info); + + STBIR_PROGRESS_REPORT(1); + +#ifdef STBIR_DEBUG_OVERWRITE_TEST + STBIR_ASSERT(memcmp(overwrite_output_before_pre, &((unsigned char*)output_data)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_output_after_pre, &((unsigned char*)output_data)[begin_forbidden], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_before_pre, &((unsigned char*)tempmem)[-OVERWRITE_ARRAY_SIZE], OVERWRITE_ARRAY_SIZE) == 0); + STBIR_ASSERT(memcmp(overwrite_tempmem_after_pre, &((unsigned char*)tempmem)[tempmem_size_in_bytes], OVERWRITE_ARRAY_SIZE) == 0); +#endif + + return 1; +} + + +static int stbir__resize_arbitrary( + void *alloc_context, + const void* input_data, int input_w, int input_h, int input_stride_in_bytes, + void* output_data, int output_w, int output_h, int output_stride_in_bytes, + float s0, float t0, float s1, float t1, float *transform, + int channels, int alpha_channel, stbir_uint32 flags, stbir_datatype type, + stbir_filter h_filter, stbir_filter v_filter, + stbir_edge edge_horizontal, stbir_edge edge_vertical, stbir_colorspace colorspace) +{ + stbir__info info; + int result; + size_t memory_required; + void* extra_memory; + + stbir__setup(&info, input_w, input_h, output_w, output_h, channels); + stbir__calculate_transform(&info, s0,t0,s1,t1,transform); + stbir__choose_filter(&info, h_filter, v_filter); + memory_required = stbir__calculate_memory(&info); + extra_memory = STBIR_MALLOC(memory_required, alloc_context); + + if (!extra_memory) + return 0; + + result = stbir__resize_allocated(&info, input_data, input_stride_in_bytes, + output_data, output_stride_in_bytes, + alpha_channel, flags, type, + edge_horizontal, edge_vertical, + colorspace, extra_memory, memory_required); + + STBIR_FREE(extra_memory, alloc_context); + + return result; +} + +STBIRDEF int stbir_resize_uint8( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_float( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,-1,0, STBIR_TYPE_FLOAT, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_LINEAR); +} + +STBIRDEF int stbir_resize_uint8_srgb(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_srgb_edgemode(const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode) +{ + return stbir__resize_arbitrary(NULL, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, STBIR_FILTER_DEFAULT, STBIR_FILTER_DEFAULT, + edge_wrap_mode, edge_wrap_mode, STBIR_COLORSPACE_SRGB); +} + +STBIRDEF int stbir_resize_uint8_generic( const unsigned char *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + unsigned char *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT8, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + +STBIRDEF int stbir_resize_uint16_generic(const stbir_uint16 *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + stbir_uint16 *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_UINT16, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize_float_generic( const float *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + float *output_pixels , int output_w, int output_h, int output_stride_in_bytes, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_wrap_mode, stbir_filter filter, stbir_colorspace space, + void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, STBIR_TYPE_FLOAT, filter, filter, + edge_wrap_mode, edge_wrap_mode, space); +} + + +STBIRDEF int stbir_resize( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + + +STBIRDEF int stbir_resize_subpixel(const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float x_scale, float y_scale, + float x_offset, float y_offset) +{ + float transform[4]; + transform[0] = x_scale; + transform[1] = y_scale; + transform[2] = x_offset; + transform[3] = y_offset; + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + 0,0,1,1,transform,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +STBIRDEF int stbir_resize_region( const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes, + void *output_pixels, int output_w, int output_h, int output_stride_in_bytes, + stbir_datatype datatype, + int num_channels, int alpha_channel, int flags, + stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical, + stbir_filter filter_horizontal, stbir_filter filter_vertical, + stbir_colorspace space, void *alloc_context, + float s0, float t0, float s1, float t1) +{ + return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes, + output_pixels, output_w, output_h, output_stride_in_bytes, + s0,t0,s1,t1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical, + edge_mode_horizontal, edge_mode_vertical, space); +} + +#endif // STB_IMAGE_RESIZE_IMPLEMENTATION + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +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 OR COPYRIGHT HOLDERS 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. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +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. +------------------------------------------------------------------------------ +*/ diff --git a/src/stoon.c b/src/stoon.c new file mode 100644 index 0000000..394ca9f --- /dev/null +++ b/src/stoon.c @@ -0,0 +1,395 @@ +#include"stoon.h" + +#ifdef _WIN32 +#include +#include +#include +#else +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#define STUN_BINDING_REQUEST 0x0001 +#define STUN_BINDING_INDICATION 0x1100 +#define STUN_BINDING_RESPONSE 0x0101 +#define STUN_XOR_MAPPED_ADDRESS 0x0020 + +#define STUN_MAGIC 0x2112A442 + +#define MAX_ATTRIB_BUFFER_SIZE 128 + +#define STUN_NETFAM_IPV4 1 +#define STUN_NETFAM_IPV6 2 + +#ifdef _WIN32 +#define RAND(b, i) RtlGenRandom(b, i) +#else +#define RAND(b, i) getrandom(b, i, 0) +#endif + +struct StunMsg { + uint16_t type; + uint16_t len; + uint32_t magic; + uint8_t id[12]; +}; + +static int stoon_init_mini(struct addrinfo *serv, uint16_t myport) { +#ifdef _WIN32 + errno = 0; + int fd = socket(serv->ai_family, serv->ai_socktype, serv->ai_protocol); + ioctlsocket(fd, FIONBIO, &(unsigned long) {1}); +#else + int fd = socket(serv->ai_family, serv->ai_socktype | SOCK_NONBLOCK, serv->ai_protocol); +#endif + + if(serv->ai_family == AF_INET6) { + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void*) &(int) {1}, sizeof(int)); + } + + char p[6]; + sprintf(p, "%u", myport); + + struct addrinfo *myaddr; + if(getaddrinfo(NULL, p, &(struct addrinfo) {.ai_family = serv->ai_family, .ai_socktype = SOCK_DGRAM, .ai_protocol = IPPROTO_UDP, .ai_flags = AI_PASSIVE}, &myaddr)) { + close(fd); + return -1; + } + if(bind(fd, myaddr->ai_addr, myaddr->ai_addrlen)) { + close(fd); + return -2; + } + freeaddrinfo(myaddr); + + return fd; +} +struct Stoon stoon_init(const char *stunhost, uint16_t stunport, uint16_t myport) { + struct addrinfo *stunaddrs; + struct addrinfo *v4 = NULL; + struct addrinfo *v6 = NULL; + + { + char p[6]; + sprintf(p, "%u", stunport); + + getaddrinfo(stunhost, p, &(struct addrinfo) {.ai_family = AF_UNSPEC, .ai_socktype = SOCK_DGRAM, .ai_protocol = IPPROTO_UDP}, &stunaddrs); + + for(struct addrinfo *addr = stunaddrs; addr; addr = addr->ai_next) { + if(addr->ai_family == AF_INET6) { + v6 = addr; + } else { + v4 = addr; + } + } + } + + struct Stoon ret; + + memset(&ret.my4, 0, sizeof(ret.my4)); + if(v4) { + memcpy(&ret.stu4, v4->ai_addr, v4->ai_addrlen); + ret.fd4 = stoon_init_mini(v4, myport); + } else ret.fd4 = -1; + + memset(&ret.my6, 0, sizeof(ret.my6)); + if(v6) { + memcpy(&ret.stu6, v6->ai_addr, v6->ai_addrlen); + ret.fd6 = stoon_init_mini(v6, myport); + } else ret.fd6 = -1; + + ret.poonchstage = 0; + + freeaddrinfo(stunaddrs); + + return ret; +} + +static int stoon_req_mini(struct Stoon *this, int *fd, struct sockaddr *serv, int servlen) { + struct StunMsg req = {.type = htons(STUN_BINDING_REQUEST), .len = htons(0), .magic = htonl(STUN_MAGIC)}; + RAND(req.id, sizeof(req.id)); + + if(sendto(*fd, (void*) &req, sizeof(req), 0, serv, servlen) == -1) { + if(errno == ENETUNREACH) { + close(*fd); + *fd = -1; + } + } +} +int stoon_req(struct Stoon *this) { + if(this->fd4 >= 0) stoon_req_mini(this, &this->fd4, (struct sockaddr*) &this->stu4, sizeof(struct sockaddr_in)); + if(this->fd6 >= 0) stoon_req_mini(this, &this->fd6, (struct sockaddr*) &this->stu6, sizeof(struct sockaddr_in6)); +} + +static int stoon_listen_mini(struct Stoon *this, int fd, struct sockaddr *serv, int servlen) { + struct { + struct StunMsg base; + uint8_t attribs[MAX_ATTRIB_BUFFER_SIZE]; + } res; + + if(recvfrom(fd, (void*) &res, sizeof(res), 0, NULL, 0) < 0) { + return -1; + } + + if(ntohs(res.base.type) != STUN_BINDING_RESPONSE) { + puts("Not binding response"); + return -3; + } + + uint16_t attribsLen = ntohs(res.base.len); + if(attribsLen > MAX_ATTRIB_BUFFER_SIZE) attribsLen = MAX_ATTRIB_BUFFER_SIZE; + + for(uint8_t *d = res.attribs;;) { + // Overflow check + if((uintmax_t) (d - res.attribs) > MAX_ATTRIB_BUFFER_SIZE - 4) break; + + uint16_t attribType = ntohs(((uint16_t*) d)[0]); + uint16_t attribLen = ntohs(((uint16_t*) d)[1]); + + // Overflow check + if((uintmax_t) (d + 4 + attribLen - res.attribs) > MAX_ATTRIB_BUFFER_SIZE) break; + + if(attribType == STUN_XOR_MAPPED_ADDRESS) { + uint16_t netfam = ntohs(((uint16_t*) d)[2]); + uint16_t publicPort = ntohs(((uint16_t*) d)[3]) ^ (STUN_MAGIC >> 16); + if(netfam == STUN_NETFAM_IPV4) { + uint32_t publicIp = ntohl(((uint32_t*) d)[2]) ^ STUN_MAGIC; + + this->my4.sin_family = AF_INET; + memcpy(&this->my4.sin_addr, &publicIp, 4); + this->my4.sin_port = htons(publicPort); + + return 1; + } else if(netfam == STUN_NETFAM_IPV6) { + uint32_t publicIp[4]; + publicIp[0] = ((uint32_t*) d)[2] ^ htonl(STUN_MAGIC); + publicIp[1] = ((uint32_t*) d)[3] ^ ((uint32_t*) res.base.id)[0]; + publicIp[2] = ((uint32_t*) d)[4] ^ ((uint32_t*) res.base.id)[1]; + publicIp[3] = ((uint32_t*) d)[5] ^ ((uint32_t*) res.base.id)[2]; + + this->my6.sin6_family = AF_INET6; + memcpy(&this->my6.sin6_addr, &publicIp, 16); + this->my6.sin6_port = htons(publicPort); + + return 1; + } else { + puts("Neither ipv4 nor ipv6???"); + } + } + + d += 4 + attribLen; + } + + return 0; +} +int stoon_listen(struct Stoon *this) { + if(this->fd4 >= 0) if(stoon_listen_mini(this, this->fd4, (struct sockaddr*) &this->stu4, sizeof(struct sockaddr_in)) < 0) return 0; + if(this->fd6 >= 0) if(stoon_listen_mini(this, this->fd6, (struct sockaddr*) &this->stu6, sizeof(struct sockaddr_in6)) < 0) return 0; + return 1; +} + +void stoon_keepalive(struct Stoon *this) { + struct StunMsg req = {.type = htons(STUN_BINDING_INDICATION), .len = htons(0), .magic = htonl(STUN_MAGIC)}; + RAND(&req.id, sizeof(req.id)); + + if(this->fd4 >= 0) { + sendto(this->fd4, (void*) &req, sizeof(req), 0, (struct sockaddr*) &this->stu4, sizeof(struct sockaddr_in)); + } + + if(this->fd6 >= 0) { + sendto(this->fd6, (void*) &req, sizeof(req), 0, (struct sockaddr*) &this->stu6, sizeof(struct sockaddr_in6)); + } +} + +void stoon_kill(struct Stoon *this) { + if(this->fd4 >= 0) close(this->fd4); + this->fd4 = -1; + + if(this->fd6 >= 0) close(this->fd6); + this->fd6 = -1; +} + +int stoon_v4_available(struct Stoon *this) { + return this->fd4 >= 0; +} + +int stoon_v6_available(struct Stoon *this) { + return this->fd6 >= 0; +} + +void stoon_serialize(struct Stoon *this, uint8_t ret[static STOON_CONN_INFO_SIZE]) { + if(this->fd4 >= 0) { + memcpy(ret + 0, &this->my4.sin_addr, 4); + memcpy(ret + 4, &this->my4.sin_port, 2); + } else { + memset(ret, 0, 6); + } + + if(this->fd6 >= 0) { + memcpy(ret + 6, &this->my6.sin6_addr, 16); + memcpy(ret + 22, &this->my6.sin6_port, 2); + } else { + memset(ret + 6, 0, 18); + } +} + +int stoon_poonch(struct Stoon *this, const uint8_t peerdata[static STOON_CONN_INFO_SIZE]) { + struct { + uint32_t addr4; + uint16_t port4; + + uint8_t addr6[16]; + uint16_t port6; + } peer; + + memcpy(&peer.addr4, peerdata + 0, 4); + memcpy(&peer.port4, peerdata + 4, 2); + + memcpy(&peer.addr6, peerdata + 6, 16); + memcpy(&peer.port6, peerdata + 22, 2); + + int myfd = -1; + struct sockaddr_storage peeraddr = {}; + int peersz; + + // Prioritize IPv6 + if(this->my6.sin6_family && peer.port6) { + myfd = this->fd6; + + struct sockaddr_in6 *pee = (void*) &peeraddr; + pee->sin6_family = AF_INET6; + memcpy(&pee->sin6_addr, &peer.addr6, 16); + pee->sin6_port = peer.port6; + peersz = sizeof(*pee); + } else if(this->my4.sin_family && peer.port4) { + myfd = this->fd4; + + struct sockaddr_in *pee = (void*) &peeraddr; + pee->sin_family = AF_INET; + memcpy(&pee->sin_addr, &peer.addr4, 4); + pee->sin_port = peer.port4; + peersz = sizeof(*pee); + } else { + return STOON_POONCH_INCOMPATIBLE_NETFAMS; + } + + if(this->poonchstage == POONCH_STAGE_KNOCKING) { + char buf[64]; + inet_ntop(peeraddr.ss_family, peeraddr.ss_family == AF_INET ? peerdata + 0 : peerdata + 6, buf, sizeof(buf)); + printf("Sending knock to %s:%u\n", buf, peeraddr.ss_family == AF_INET ? ntohs(peer.port4) : ntohs(peer.port6)); + struct Poonch cmd = {.magic = POONCH_MAGIC, .stage = POONCH_STAGE_KNOCKING}; + sendto(myfd, (void*) &cmd, sizeof(cmd), 0, (struct sockaddr*) &peeraddr, peersz); + } + + struct Poonch comin; + if(recvfrom(myfd, (void*) &comin, sizeof(comin), 0, NULL, NULL) == sizeof(comin) && comin.magic == POONCH_MAGIC) { + puts("received somethign"); + if(comin.stage == POONCH_STAGE_KNOCKING) { + puts("Received knock"); + struct Poonch ret = {.magic = POONCH_MAGIC, .stage = POONCH_STAGE_ACK}; + this->poonchstage = POONCH_STAGE_ACK; + sendto(myfd, (void*) &ret, sizeof(ret), 0, (struct sockaddr*) &peeraddr, peersz); + + return STOON_POONCH_ACKED; + } + } + + return STOON_POONCH_NO_KNOCK; +} + +#ifdef STOON_STANDALONE +int main() { +#ifdef _WIN32 + WSADATA wsadata; + WSAStartup(MAKEWORD(1, 1), &wsadata); +#endif + + struct Stoon stoon = stoon_init("stun.l.google.com", 19305, 26656); + + stoon_req(&stoon); + + usleep(1000000); + stoon_listen(&stoon); + + stoon_keepalive(&stoon); + + char buf[64]; + + fputs("IPv4: ", stdout); + if(stoon.my4.sin_family) { + inet_ntop(AF_INET, &stoon.my4.sin_addr, buf, sizeof(buf)); + printf("%s:%u\n", buf, ntohs(stoon.my4.sin_port)); + } else { + puts("unavailable"); + } + + fputs("IPv6: ", stdout); + if(stoon.my6.sin6_family) { + inet_ntop(AF_INET6, &stoon.my6.sin6_addr, buf, sizeof(buf)); + printf("[%s]:%u\n", buf, ntohs(stoon.my6.sin6_port)); + } else { + puts("unavailable"); + } + + uint8_t r[STOON_CONN_INFO_SIZE]; + stoon_serialize(&stoon, r); + + fputs("Serialized: ", stdout); + for(int i = 0; i < STOON_CONN_INFO_SIZE; i++) { + printf("%02x", r[i]); + } + fputc(10, stdout); + + puts("Enter peer's connection string:"); + + char peerdatareadable[128]; + fgets(peerdatareadable, sizeof(peerdatareadable), stdin); + + uint8_t peerdata[STOON_CONN_INFO_SIZE] = {}; + for(int i = 0;; i += 2) { + if(peerdatareadable[i] == 0) break; + + int b = 0; + + int c = peerdatareadable[i]; + if(c >= '0' && c <= '9') { + b |= (c - '0') << 4; + } else if(c >= 'a' && c <= 'f') { + b |= (c - 'a' + 10) << 4; + } + + c = peerdatareadable[i + 1]; + if(c >= '0' && c <= '9') { + b |= (c - '0'); + } else if(c >= 'a' && c <= 'f') { + b |= (c - 'a' + 10); + } + + peerdata[i / 2] = b; + } + + int got = 0; + while(1) { + if(stoon_poonch(&stoon, peerdata) == STOON_POONCH_NO_KNOCK) { + got++; + if(got >= 10 && stoon.poonchstage == POONCH_STAGE_ACK) { + puts("Gape successful!"); + break; + } + } else { + got = 0; + } + usleep(500000); + } + + stoon_kill(&stoon); +} +#endif diff --git a/src/stoon.h b/src/stoon.h new file mode 100644 index 0000000..3e173ee --- /dev/null +++ b/src/stoon.h @@ -0,0 +1,64 @@ +#pragma once + +#ifndef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200112L +#endif + +#include +#include + +#ifdef _WIN32 +#include +#include +#else +#include +#endif + +/* Standalone hole punching libary (IPv4 & IPv6 compatible) */ + +#define STOON_CONN_INFO_SIZE (4 + 2 + 16 + 2) + +#define POONCH_MAGIC 0x504F4348 +#define POONCH_STAGE_KNOCKING 0 +#define POONCH_STAGE_ACK 1 +struct Poonch { + uint32_t magic; + uint32_t stage; +}; + +struct Stoon { + struct sockaddr_in stu4; + struct sockaddr_in my4; + int fd4; + + struct sockaddr_in6 stu6; + struct sockaddr_in6 my6; + int fd6; + + uint8_t poonchstage; +}; + +// stunhost: Self-explanatory +// stunport: Self-explanatory +// myport: Local endpoint port +struct Stoon stoon_init(const char *stunhost, uint16_t stunport, uint16_t myport); + +int stoon_req(struct Stoon*); +int stoon_listen(struct Stoon*); + +// This is necessary in order to keep the NAT table entry active +// Some NATs wait as little as 25 seconds, so an interval *less* than +// 25s is recommended +void stoon_keepalive(struct Stoon*); + +void stoon_kill(struct Stoon*); + +int stoon_v4_available(struct Stoon*); +int stoon_v6_available(struct Stoon*); + +void stoon_serialize(struct Stoon*, uint8_t ret[static STOON_CONN_INFO_SIZE]); + +#define STOON_POONCH_INCOMPATIBLE_NETFAMS (-1) +#define STOON_POONCH_NO_KNOCK 0 +#define STOON_POONCH_ACKED 1 +int stoon_poonch(struct Stoon*, const uint8_t peerdata[static STOON_CONN_INFO_SIZE]);