From 96bb3c36114cfb3df19cd36ad7fb3e9b9ede9598 Mon Sep 17 00:00:00 2001 From: VisualGMQ <2142587070@qq.com> Date: Sun, 30 Jan 2022 21:24:16 +0800 Subject: [PATCH] basic framework OK --- Makefile | 18 + engine.cpp | 57 + engine.hpp | 33 + event.cpp | 5 + event.hpp | 5 + glhelpfunc.cpp | 19 + glhelpfunc.hpp | 15 + libmath.cpp | 41 + libmath.hpp | 32 + libs/glad/include/KHR/khrplatform.h | 311 ++ libs/glad/include/glad/gl.h | 2139 ++++++++ libs/glad/src/gl.c | 1127 ++++ libs/glfw/libglfw.3.dylib | Bin 0 -> 233166 bytes libs/glfw/libglfw3.a | Bin 0 -> 308296 bytes libs/stb_image/stb_image.h | 7873 +++++++++++++++++++++++++++ libs/stb_image/stbi_image.cpp | 2 + log.hpp | 5 + main.cpp | 19 + pch.hpp | 11 + renderer.cpp | 41 + renderer.hpp | 18 + shader.cpp | 277 + shader.hpp | 99 + texture.hpp | 5 + tool.hpp | 8 + 25 files changed, 12160 insertions(+) create mode 100644 Makefile create mode 100644 engine.cpp create mode 100644 engine.hpp create mode 100644 event.cpp create mode 100644 event.hpp create mode 100644 glhelpfunc.cpp create mode 100644 glhelpfunc.hpp create mode 100644 libmath.cpp create mode 100644 libmath.hpp create mode 100644 libs/glad/include/KHR/khrplatform.h create mode 100644 libs/glad/include/glad/gl.h create mode 100644 libs/glad/src/gl.c create mode 100755 libs/glfw/libglfw.3.dylib create mode 100644 libs/glfw/libglfw3.a create mode 100644 libs/stb_image/stb_image.h create mode 100644 libs/stb_image/stbi_image.cpp create mode 100644 log.hpp create mode 100644 main.cpp create mode 100644 pch.hpp create mode 100644 renderer.cpp create mode 100644 renderer.hpp create mode 100644 shader.cpp create mode 100644 shader.hpp create mode 100644 texture.hpp create mode 100644 tool.hpp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..20e753e --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +GLFW_DEP = -L./libs/glfw/ -lglfw +GLAD_DEP = -I./libs/glad/include +STB_IMAGE_DEP = -I./libs/stb_image +SRC = $(wildcard ./*.cpp) ./libs/glad/src/gl.c ./libs/stb_image/stbi_image.cpp +CPP_FLAGS = -std=c++17 + +game.out: $(SRC) + $(CXX) $^ ${GLFW_DEP} -o $@ ${GLAD_DEP} ${STB_IMAGE_DEP} ${CPP_FLAGS} + +.PHONY:clean pack +clean: + -rm *.o + -rm *.out +pack: + -rm -r output + -mkdir output + -mv game.out output/ + -cp libs/glfw/libglfw.3.dylib output/ diff --git a/engine.cpp b/engine.cpp new file mode 100644 index 0000000..8704470 --- /dev/null +++ b/engine.cpp @@ -0,0 +1,57 @@ +#include "engine.hpp" +#include "event.hpp" + +void error_callback(int error, const char* description) { + fprintf(stderr, "Error: %s\n", description); +} + +void Engine::Init(const std::string& title, const Size& size) { + if (!glfwInit()) { + throw std::runtime_error("glfw init failed"); + } + glfwSetErrorCallback(error_callback); + + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + // only for MacOS + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + + window_ = glfwCreateWindow(size.x, size.y, + title.c_str(), + NULL, NULL); + + if (!window_) { + glfwTerminate(); + throw std::runtime_error("glfw window create failed"); + } + + glfwMakeContextCurrent(window_); + + glfwSetFramebufferSizeCallback(engine.GetWindow(), OnWindowResize); + + Renderer::Init(); + + Renderer::SetViewport(0, 0, size.x, size.y); +} + +void Engine::SwapContext() { + glfwSwapBuffers(window_); +} + +void Engine::PollEvent() { + glfwPollEvents(); +} + +void Engine::Shutdown() { + glfwDestroyWindow(window_); + glfwTerminate(); +} + +void Engine::Update() { +} + +void Engine::Render() { +} + +Engine engine; diff --git a/engine.hpp b/engine.hpp new file mode 100644 index 0000000..298473b --- /dev/null +++ b/engine.hpp @@ -0,0 +1,33 @@ +#pragma once +#include "pch.hpp" +#include "libmath.hpp" +#include "renderer.hpp" +#include +#include + +class Engine final { +public: + void Init(const std::string& title, const Size& size); + void Shutdown(); + + void Exit() { shouldExit_ = true; } + bool ShouldExit() const { return glfwWindowShouldClose(window_); } + + // TODO implement your logic here + void Update(); + // TODO implement your render here + void Render(); + + GLFWwindow* GetWindow() { return window_; } + + void SwapContext(); + void PollEvent(); + +private: + bool shouldExit_ = false; + + // window + GLFWwindow* window_; +}; + +extern Engine engine; diff --git a/event.cpp b/event.cpp new file mode 100644 index 0000000..67d7572 --- /dev/null +++ b/event.cpp @@ -0,0 +1,5 @@ +#include "event.hpp" + +void OnWindowResize(GLFWwindow* window, int width, int height) { + Renderer::SetViewport(0, 0, width, height); +} diff --git a/event.hpp b/event.hpp new file mode 100644 index 0000000..c72851c --- /dev/null +++ b/event.hpp @@ -0,0 +1,5 @@ +#pragma once +#include "renderer.hpp" + +void OnWindowResize(GLFWwindow* window, int width, int height); +void OnKeyDown(GLFWwindow* window, int key, int scancode, int action, int mods); diff --git a/glhelpfunc.cpp b/glhelpfunc.cpp new file mode 100644 index 0000000..2e95254 --- /dev/null +++ b/glhelpfunc.cpp @@ -0,0 +1,19 @@ +#include "glhelpfunc.hpp" + +#define CASE(e) case e: return #e; + +const char* GLGetErrorString(GLenum err) { + switch (err) { + CASE(GL_NO_ERROR) + CASE(GL_INVALID_ENUM) + CASE(GL_INVALID_VALUE) + CASE(GL_INVALID_OPERATION) + CASE(GL_OUT_OF_MEMORY) + CASE(GL_INVALID_FRAMEBUFFER_OPERATION) + default: + return "Unknown OpenGL Error"; + } + return "Unknown Error"; +} + +#undef CASE diff --git a/glhelpfunc.hpp b/glhelpfunc.hpp new file mode 100644 index 0000000..4fee4e8 --- /dev/null +++ b/glhelpfunc.hpp @@ -0,0 +1,15 @@ +#pragma once +#include "pch.hpp" +#include "log.hpp" + +const char* GLGetErrorString(GLenum); +inline void GLClearError() { + while (glGetError() != GL_NO_ERROR) {} +} + +#define GL_CALL(statement) do { \ + GLClearError(); \ + statement; \ + GLenum ___err_inner_use = glGetError(); \ + if (___err_inner_use != GL_NO_ERROR) Log("OpenGL Error: %s", GLGetErrorString(___err_inner_use)); \ +} while(0) diff --git a/libmath.cpp b/libmath.cpp new file mode 100644 index 0000000..cdf0e0e --- /dev/null +++ b/libmath.cpp @@ -0,0 +1,41 @@ +#include "libmath.hpp" + +Point operator+(const Point& p1, const Point& p2) { + return Point{p1.x + p2.x, p1.y + p2.y}; +} + +Point operator-(const Point& p1, const Point& p2) { + return Point{p1.x - p2.x, p1.y - p2.y}; +} + +Point operator*(const Point& p1, const Point& p2) { + return Point{p1.x * p2.x, p1.y * p2.y}; +} + +Point operator/(const Point& p1, const Point& p2) { + return Point{p1.x / p2.x, p1.y / p2.y}; +} + +Point& operator+=(Point& p1, const Point& p2) { + p1.x += p2.x; + p1.y += p2.y; + return p1; +} + +Point& operator-=(Point& p1, const Point& p2) { + p1.x -= p2.x; + p1.y -= p2.y; + return p1; +} + +Point& operator*=(Point& p1, const Point& p2) { + p1.x *= p2.x; + p1.y *= p2.y; + return p1; +} + +Point& operator/=(Point& p1, const Point& p2) { + p1.x /= p2.x; + p1.y /= p2.y; + return p1; +} diff --git a/libmath.hpp b/libmath.hpp new file mode 100644 index 0000000..cc106f9 --- /dev/null +++ b/libmath.hpp @@ -0,0 +1,32 @@ +#pragma once + +struct Point { + float x; + float y; +}; + +struct Rect { + float x; + float y; + float w; + float h; +}; + +struct Color { + float r; + float g; + float b; + float a; +}; + +using Size = Point; +using Rect = Rect; + +Point operator+(const Point& p1, const Point& p2); +Point operator-(const Point& p1, const Point& p2); +Point operator*(const Point& p1, const Point& p2); +Point operator/(const Point& p1, const Point& p2); +Point& operator+=(Point& p1, const Point& p2); +Point& operator-=(Point& p1, const Point& p2); +Point& operator*=(Point& p1, const Point& p2); +Point& operator/=(Point& p1, const Point& p2); diff --git a/libs/glad/include/KHR/khrplatform.h b/libs/glad/include/KHR/khrplatform.h new file mode 100644 index 0000000..0164644 --- /dev/null +++ b/libs/glad/include/KHR/khrplatform.h @@ -0,0 +1,311 @@ +#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_APIENTRY + * KHRONOS_APIATTRIBUTES + * + * These may be used in function prototypes as: + * + * KHRONOS_APICALL void KHRONOS_APIENTRY 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_APIENTRY + *------------------------------------------------------------------------- + * 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_APIENTRY __stdcall +#else +# define KHRONOS_APIENTRY +#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_ */ diff --git a/libs/glad/include/glad/gl.h b/libs/glad/include/glad/gl.h new file mode 100644 index 0000000..cbb66b0 --- /dev/null +++ b/libs/glad/include/glad/gl.h @@ -0,0 +1,2139 @@ +/** + * Loader generated by glad 2.0.0-beta on Sun Jan 30 12:35:24 2022 + * + * Generator: C/C++ + * Specification: gl + * Extensions: 0 + * + * APIs: + * - gl:core=3.3 + * + * Options: + * - ALIAS = False + * - DEBUG = False + * - HEADER_ONLY = False + * - LOADER = True + * - MX = False + * - MX_GLOBAL = False + * - ON_DEMAND = False + * + * Commandline: + * --api='gl:core=3.3' --extensions='' c --loader + * + * Online: + * http://glad.sh/#api=gl%3Acore%3D3.3&extensions=&generator=c&options=LOADER + * + */ + +#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_LOADER + +#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 + +#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.0-beta" + +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_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#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_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_ALPHA 0x1906 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_ALWAYS 0x0207 +#define GL_AND 0x1501 +#define GL_AND_INVERTED 0x1504 +#define GL_AND_REVERSE 0x1502 +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ATTACHED_SHADERS 0x8B85 +#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_BGR_INTEGER 0x8D9A +#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_BLUE 0x1905 +#define GL_BLUE_INTEGER 0x8D96 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_BUFFER_ACCESS 0x88BB +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_BYTE 0x1400 +#define GL_CCW 0x0901 +#define GL_CLAMP_READ_COLOR 0x891C +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_CLEAR 0x1500 +#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_COLOR 0x1800 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#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_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_LOGIC_OP 0x0BF2 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_COMPILE_STATUS 0x8B81 +#define GL_COMPRESSED_RED 0x8225 +#define GL_COMPRESSED_RED_RGTC1 0x8DBB +#define GL_COMPRESSED_RG 0x8226 +#define GL_COMPRESSED_RGB 0x84ED +#define GL_COMPRESSED_RGBA 0x84EE +#define GL_COMPRESSED_RG_RGTC2 0x8DBD +#define GL_COMPRESSED_SIGNED_RED_RGTC1 0x8DBC +#define GL_COMPRESSED_SIGNED_RG_RGTC2 0x8DBE +#define GL_COMPRESSED_SRGB 0x8C48 +#define GL_COMPRESSED_SRGB_ALPHA 0x8C49 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_CONDITION_SATISFIED 0x911C +#define GL_CONSTANT_ALPHA 0x8003 +#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_FORWARD_COMPATIBLE_BIT 0x00000001 +#define GL_CONTEXT_PROFILE_MASK 0x9126 +#define GL_COPY 0x1503 +#define GL_COPY_INVERTED 0x150C +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_CURRENT_QUERY 0x8865 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_CW 0x0900 +#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_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_FUNC 0x0B74 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DITHER 0x0BD0 +#define GL_DONT_CARE 0x1100 +#define GL_DOUBLE 0x140A +#define GL_DOUBLEBUFFER 0x0C32 +#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_DST_ALPHA 0x0304 +#define GL_DST_COLOR 0x0306 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_EQUAL 0x0202 +#define GL_EQUIV 0x1509 +#define GL_EXTENSIONS 0x1F03 +#define GL_FALSE 0 +#define GL_FASTEST 0x1101 +#define GL_FILL 0x1B02 +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_FIXED_ONLY 0x891D +#define GL_FLOAT 0x1406 +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4 0x8B5C +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#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_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC +#define GL_FRAMEBUFFER_SRGB 0x8DB9 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_FRAMEBUFFER_UNSUPPORTED 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_FUNC_ADD 0x8006 +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_FUNC_SUBTRACT 0x800A +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEQUAL 0x0206 +#define GL_GREATER 0x0204 +#define GL_GREEN 0x1904 +#define GL_GREEN_INTEGER 0x8D95 +#define GL_HALF_FLOAT 0x140B +#define GL_INCR 0x1E02 +#define GL_INCR_WRAP 0x8507 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_INT 0x1404 +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_INT_SAMPLER_1D 0x8DC9 +#define GL_INT_SAMPLER_1D_ARRAY 0x8DCE +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#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_3D 0x8DCB +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_INVALID_INDEX 0xFFFFFFFF +#define GL_INVALID_OPERATION 0x0502 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVERT 0x150A +#define GL_KEEP 0x1E00 +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_LEFT 0x0406 +#define GL_LEQUAL 0x0203 +#define GL_LESS 0x0201 +#define GL_LINE 0x1B01 +#define GL_LINEAR 0x2601 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_LINES 0x0001 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_SMOOTH 0x0B20 +#define GL_LINE_SMOOTH_HINT 0x0C52 +#define GL_LINE_STRIP 0x0003 +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINE_WIDTH_GRANULARITY 0x0B23 +#define GL_LINE_WIDTH_RANGE 0x0B22 +#define GL_LINK_STATUS 0x8B82 +#define GL_LOGIC_OP_MODE 0x0BF0 +#define GL_LOWER_LEFT 0x8CA1 +#define GL_MAJOR_VERSION 0x821B +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAX 0x8008 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MAX_CLIP_DISTANCES 0x0D32 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#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_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#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_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_INTEGER_SAMPLES 0x9110 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE 0x84F8 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MIN 0x8007 +#define GL_MINOR_VERSION 0x821C +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_MULTISAMPLE 0x809D +#define GL_NAND 0x150E +#define GL_NEAREST 0x2600 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_NEVER 0x0200 +#define GL_NICEST 0x1102 +#define GL_NONE 0 +#define GL_NOOP 0x1505 +#define GL_NOR 0x1508 +#define GL_NOTEQUAL 0x0205 +#define GL_NO_ERROR 0 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_NUM_EXTENSIONS 0x821D +#define GL_OBJECT_TYPE 0x9112 +#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_OR 0x1507 +#define GL_OR_INVERTED 0x150D +#define GL_OR_REVERSE 0x150B +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_PACK_ALIGNMENT 0x0D05 +#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_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_FADE_THRESHOLD_SIZE 0x8128 +#define GL_POINT_SIZE 0x0B11 +#define GL_POINT_SIZE_GRANULARITY 0x0B13 +#define GL_POINT_SIZE_RANGE 0x0B12 +#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0 +#define GL_POLYGON_MODE 0x0B40 +#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_PRIMITIVES_GENERATED 0x8C87 +#define GL_PRIMITIVE_RESTART 0x8F9D +#define GL_PRIMITIVE_RESTART_INDEX 0x8F9E +#define GL_PROGRAM_POINT_SIZE 0x8642 +#define GL_PROVOKING_VERTEX 0x8E4F +#define GL_PROXY_TEXTURE_1D 0x8063 +#define GL_PROXY_TEXTURE_1D_ARRAY 0x8C19 +#define GL_PROXY_TEXTURE_2D 0x8064 +#define GL_PROXY_TEXTURE_2D_ARRAY 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_RECTANGLE 0x84F7 +#define GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C +#define GL_QUERY_BY_REGION_NO_WAIT 0x8E16 +#define GL_QUERY_BY_REGION_WAIT 0x8E15 +#define GL_QUERY_COUNTER_BITS 0x8864 +#define GL_QUERY_NO_WAIT 0x8E14 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_QUERY_WAIT 0x8E13 +#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_READ_BUFFER 0x0C02 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_READ_ONLY 0x88B8 +#define GL_READ_WRITE 0x88BA +#define GL_RED 0x1903 +#define GL_RED_INTEGER 0x8D94 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERER 0x1F01 +#define GL_REPEAT 0x2901 +#define GL_REPLACE 0x1E01 +#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_RGB16I 0x8D89 +#define GL_RGB16UI 0x8D77 +#define GL_RGB16_SNORM 0x8F9A +#define GL_RGB32F 0x8815 +#define GL_RGB32I 0x8D83 +#define GL_RGB32UI 0x8D71 +#define GL_RGB4 0x804F +#define GL_RGB5 0x8050 +#define GL_RGB5_A1 0x8057 +#define GL_RGB8 0x8051 +#define GL_RGB8I 0x8D8F +#define GL_RGB8UI 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_RGBA16I 0x8D88 +#define GL_RGBA16UI 0x8D76 +#define GL_RGBA16_SNORM 0x8F9B +#define GL_RGBA2 0x8055 +#define GL_RGBA32F 0x8814 +#define GL_RGBA32I 0x8D82 +#define GL_RGBA32UI 0x8D70 +#define GL_RGBA4 0x8056 +#define GL_RGBA8 0x8058 +#define GL_RGBA8I 0x8D8E +#define GL_RGBA8UI 0x8D7C +#define GL_RGBA8_SNORM 0x8F97 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RG_INTEGER 0x8228 +#define GL_RIGHT 0x0407 +#define GL_SAMPLER_1D 0x8B5D +#define GL_SAMPLER_1D_ARRAY 0x8DC0 +#define GL_SAMPLER_1D_ARRAY_SHADOW 0x8DC3 +#define GL_SAMPLER_1D_SHADOW 0x8B61 +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 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_SHADOW 0x8B64 +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_BINDING 0x8919 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_CUBE_SHADOW 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_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_SET 0x150F +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_TYPE 0x8B4F +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_SHORT 0x1402 +#define GL_SIGNALED 0x9119 +#define GL_SIGNED_NORMALIZED 0x8F9C +#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_SRC1_ALPHA 0x8589 +#define GL_SRC1_COLOR 0x88F9 +#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_SRGB_ALPHA 0x8C42 +#define GL_STATIC_COPY 0x88E6 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STENCIL 0x1802 +#define GL_STENCIL_ATTACHMENT 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_BUFFER_BIT 0x00000400 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#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_INDEX4 0x8D47 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#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_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_SUBPIXEL_BITS 0x0D50 +#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_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_2D 0x0DE1 +#define GL_TEXTURE_2D_ARRAY 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_BASE_LEVEL 0x813C +#define GL_TEXTURE_BINDING_1D 0x8068 +#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_BINDING_2D_ARRAY 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_RECTANGLE 0x84F6 +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0 +#define GL_TEXTURE_COMPRESSION_HINT 0x84EF +#define GL_TEXTURE_CUBE_MAP 0x8513 +#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_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_LOD_BIAS 0x8501 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#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_RECTANGLE 0x84F5 +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#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_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_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLE_FAN 0x0006 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_TRUE 1 +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#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_FRAGMENT_SHADER 0x8A46 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45 +#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_UNPACK_ALIGNMENT 0x0CF5 +#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_SAMPLER_1D 0x8DD1 +#define GL_UNSIGNED_INT_SAMPLER_1D_ARRAY 0x8DD6 +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#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_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_UNSIGNED_NORMALIZED 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_VALIDATE_STATUS 0x8B83 +#define GL_VENDOR 0x1F00 +#define GL_VERSION 0x1F02 +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_PROGRAM_POINT_SIZE 0x8642 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_VIEWPORT 0x0BA2 +#define GL_WAIT_FAILED 0x911D +#define GL_WRITE_ONLY 0x88B9 +#define GL_XOR 0x1506 +#define GL_ZERO 0 + + +#include +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; + + +typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum texture); +typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader); +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 *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode); +typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLBINDFRAGDATALOCATIONPROC)(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 *PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLBINDSAMPLERPROC)(GLuint unit, GLuint sampler); +typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture); +typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYPROC)(GLuint array); +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 *PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +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 *PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void * data, GLenum usage); +typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data); +typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(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 *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 *PFNGLCLEARDEPTHPROC)(GLdouble depth); +typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint s); +typedef GLenum (GLAD_API_PTR *PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout); +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 *PFNGLCOMPILESHADERPROC)(GLuint shader); +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 *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +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 GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void); +typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum type); +typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint * framebuffers); +typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint program); +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 *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 *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 *PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader); +typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum cap); +typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEIPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +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 *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex); +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 *PFNGLENABLEPROC)(GLenum cap); +typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEIPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENDCONDITIONALRENDERPROC)(void); +typedef void (GLAD_API_PTR *PFNGLENDQUERYPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKPROC)(void); +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 *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(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 *PFNGLFRAMEBUFFERTEXTURE2DPROC)(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 *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei n, GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers); +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 *PFNGLGENSAMPLERSPROC)(GLsizei count, GLuint * samplers); +typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei n, GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint * arrays); +typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum target); +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 *PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * 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 *PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders); +typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar * name); +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 *PFNGLGETBUFFERPOINTERVPROC)(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 *PFNGLGETCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint level, void * img); +typedef void (GLAD_API_PTR *PFNGLGETDOUBLEVPROC)(GLenum pname, GLdouble * data); +typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void); +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 void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params); +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 *PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint * data); +typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum pname, GLint * data); +typedef void (GLAD_API_PTR *PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat * val); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint program, 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 *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 *PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * 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 void (GLAD_API_PTR *PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei count, GLsizei * length, GLint * values); +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 *PFNGLGETTEXPARAMETERIUIVPROC)(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 *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name); +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 void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void ** pointer); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBDVPROC)(GLuint index, GLenum pname, GLdouble * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum target, GLenum mode); +typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint buffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum cap); +typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIPROC)(GLenum target, GLuint index); +typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint program); +typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYPROC)(GLuint id); +typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(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 *PFNGLISVERTEXARRAYPROC)(GLuint array); +typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat width); +typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLLOGICOPPROC)(GLenum opcode); +typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERPROC)(GLenum target, GLenum access); +typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GLAD_API_PTR *PFNGLMULTIDRAWARRAYSPROC)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount); +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 *PFNGLPIXELSTOREFPROC)(GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param); +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 *PFNGLPRIMITIVERESTARTINDEXPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLPROVOKINGVERTEXPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLQUERYCOUNTERPROC)(GLuint id, GLenum target); +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 *PFNGLRENDERBUFFERSTORAGEPROC)(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 *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 *PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length); +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 *PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer); +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 *PFNGLTEXPARAMETERIUIVPROC)(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 *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 *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint location, GLint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(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 *PFNGLUNIFORM3IPROC)(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 *PFNGLUNIFORM3UIPROC)(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 *PFNGLUNIFORM4FPROC)(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 *PFNGLUNIFORM4IPROC)(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 *PFNGLUNIFORM4UIPROC)(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 *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DPROC)(GLuint index, GLdouble x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SPROC)(GLuint index, GLshort x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DPROC)(GLuint index, GLdouble x, GLdouble y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SPROC)(GLuint index, GLshort x, GLshort y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DPROC)(GLuint index, GLdouble x, GLdouble y, GLdouble z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3DVPROC)(GLuint index, const GLdouble * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SPROC)(GLuint index, GLshort x, GLshort y, GLshort z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NBVPROC)(GLuint index, const GLbyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NIVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NSVPROC)(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 *PFNGLVERTEXATTRIB4NUBVPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4NUSVPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4BVPROC)(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 *PFNGLVERTEXATTRIB4DVPROC)(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 *PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4IVPROC)(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 *PFNGLVERTEXATTRIB4SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UBVPROC)(GLuint index, const GLubyte * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4USVPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IPROC)(GLuint index, GLint x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIPROC)(GLuint index, GLuint x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI1UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IPROC)(GLuint index, GLint x, GLint y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIPROC)(GLuint index, GLuint x, GLuint y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI2UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IPROC)(GLuint index, GLint x, GLint y, GLint z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI3UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4BVPROC)(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 *PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4SVPROC)(GLuint index, const GLshort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UBVPROC)(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 *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4USVPROC)(GLuint index, const GLushort * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIPOINTERPROC)(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 *PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout); + +GLAD_API_CALL PFNGLACTIVETEXTUREPROC glad_glActiveTexture; +#define glActiveTexture glad_glActiveTexture +GLAD_API_CALL PFNGLATTACHSHADERPROC glad_glAttachShader; +#define glAttachShader glad_glAttachShader +GLAD_API_CALL PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender; +#define glBeginConditionalRender glad_glBeginConditionalRender +GLAD_API_CALL PFNGLBEGINQUERYPROC glad_glBeginQuery; +#define glBeginQuery glad_glBeginQuery +GLAD_API_CALL PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback; +#define glBeginTransformFeedback glad_glBeginTransformFeedback +GLAD_API_CALL PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation; +#define glBindAttribLocation glad_glBindAttribLocation +GLAD_API_CALL PFNGLBINDBUFFERPROC glad_glBindBuffer; +#define glBindBuffer glad_glBindBuffer +GLAD_API_CALL PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase; +#define glBindBufferBase glad_glBindBufferBase +GLAD_API_CALL PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange; +#define glBindBufferRange glad_glBindBufferRange +GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation; +#define glBindFragDataLocation glad_glBindFragDataLocation +GLAD_API_CALL PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed; +#define glBindFragDataLocationIndexed glad_glBindFragDataLocationIndexed +GLAD_API_CALL PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer; +#define glBindFramebuffer glad_glBindFramebuffer +GLAD_API_CALL PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer; +#define glBindRenderbuffer glad_glBindRenderbuffer +GLAD_API_CALL PFNGLBINDSAMPLERPROC glad_glBindSampler; +#define glBindSampler glad_glBindSampler +GLAD_API_CALL PFNGLBINDTEXTUREPROC glad_glBindTexture; +#define glBindTexture glad_glBindTexture +GLAD_API_CALL PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray; +#define glBindVertexArray glad_glBindVertexArray +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 PFNGLBLENDFUNCPROC glad_glBlendFunc; +#define glBlendFunc glad_glBlendFunc +GLAD_API_CALL PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate; +#define glBlendFuncSeparate glad_glBlendFuncSeparate +GLAD_API_CALL PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer; +#define glBlitFramebuffer glad_glBlitFramebuffer +GLAD_API_CALL PFNGLBUFFERDATAPROC glad_glBufferData; +#define glBufferData glad_glBufferData +GLAD_API_CALL PFNGLBUFFERSUBDATAPROC glad_glBufferSubData; +#define glBufferSubData glad_glBufferSubData +GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus; +#define glCheckFramebufferStatus glad_glCheckFramebufferStatus +GLAD_API_CALL PFNGLCLAMPCOLORPROC glad_glClampColor; +#define glClampColor glad_glClampColor +GLAD_API_CALL PFNGLCLEARPROC glad_glClear; +#define glClear glad_glClear +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 PFNGLCLEARDEPTHPROC glad_glClearDepth; +#define glClearDepth glad_glClearDepth +GLAD_API_CALL PFNGLCLEARSTENCILPROC glad_glClearStencil; +#define glClearStencil glad_glClearStencil +GLAD_API_CALL PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync; +#define glClientWaitSync glad_glClientWaitSync +GLAD_API_CALL PFNGLCOLORMASKPROC glad_glColorMask; +#define glColorMask glad_glColorMask +GLAD_API_CALL PFNGLCOLORMASKIPROC glad_glColorMaski; +#define glColorMaski glad_glColorMaski +GLAD_API_CALL PFNGLCOMPILESHADERPROC glad_glCompileShader; +#define glCompileShader glad_glCompileShader +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 PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData; +#define glCopyBufferSubData glad_glCopyBufferSubData +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 PFNGLCREATEPROGRAMPROC glad_glCreateProgram; +#define glCreateProgram glad_glCreateProgram +GLAD_API_CALL PFNGLCREATESHADERPROC glad_glCreateShader; +#define glCreateShader glad_glCreateShader +GLAD_API_CALL PFNGLCULLFACEPROC glad_glCullFace; +#define glCullFace glad_glCullFace +GLAD_API_CALL PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers; +#define glDeleteBuffers glad_glDeleteBuffers +GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers; +#define glDeleteFramebuffers glad_glDeleteFramebuffers +GLAD_API_CALL PFNGLDELETEPROGRAMPROC glad_glDeleteProgram; +#define glDeleteProgram glad_glDeleteProgram +GLAD_API_CALL PFNGLDELETEQUERIESPROC glad_glDeleteQueries; +#define glDeleteQueries glad_glDeleteQueries +GLAD_API_CALL PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers; +#define glDeleteRenderbuffers glad_glDeleteRenderbuffers +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 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 PFNGLDETACHSHADERPROC glad_glDetachShader; +#define glDetachShader glad_glDetachShader +GLAD_API_CALL PFNGLDISABLEPROC glad_glDisable; +#define glDisable glad_glDisable +GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray; +#define glDisableVertexAttribArray glad_glDisableVertexAttribArray +GLAD_API_CALL PFNGLDISABLEIPROC glad_glDisablei; +#define glDisablei glad_glDisablei +GLAD_API_CALL PFNGLDRAWARRAYSPROC glad_glDrawArrays; +#define glDrawArrays glad_glDrawArrays +GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced; +#define glDrawArraysInstanced glad_glDrawArraysInstanced +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 PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced; +#define glDrawElementsInstanced glad_glDrawElementsInstanced +GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex; +#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex +GLAD_API_CALL PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements; +#define glDrawRangeElements glad_glDrawRangeElements +GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex; +#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex +GLAD_API_CALL PFNGLENABLEPROC glad_glEnable; +#define glEnable glad_glEnable +GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray; +#define glEnableVertexAttribArray glad_glEnableVertexAttribArray +GLAD_API_CALL PFNGLENABLEIPROC glad_glEnablei; +#define glEnablei glad_glEnablei +GLAD_API_CALL PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender; +#define glEndConditionalRender glad_glEndConditionalRender +GLAD_API_CALL PFNGLENDQUERYPROC glad_glEndQuery; +#define glEndQuery glad_glEndQuery +GLAD_API_CALL PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback; +#define glEndTransformFeedback glad_glEndTransformFeedback +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 PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer; +#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture; +#define glFramebufferTexture glad_glFramebufferTexture +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D; +#define glFramebufferTexture1D glad_glFramebufferTexture1D +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D; +#define glFramebufferTexture2D glad_glFramebufferTexture2D +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D; +#define glFramebufferTexture3D glad_glFramebufferTexture3D +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer; +#define glFramebufferTextureLayer glad_glFramebufferTextureLayer +GLAD_API_CALL PFNGLFRONTFACEPROC glad_glFrontFace; +#define glFrontFace glad_glFrontFace +GLAD_API_CALL PFNGLGENBUFFERSPROC glad_glGenBuffers; +#define glGenBuffers glad_glGenBuffers +GLAD_API_CALL PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers; +#define glGenFramebuffers glad_glGenFramebuffers +GLAD_API_CALL PFNGLGENQUERIESPROC glad_glGenQueries; +#define glGenQueries glad_glGenQueries +GLAD_API_CALL PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers; +#define glGenRenderbuffers glad_glGenRenderbuffers +GLAD_API_CALL PFNGLGENSAMPLERSPROC glad_glGenSamplers; +#define glGenSamplers glad_glGenSamplers +GLAD_API_CALL PFNGLGENTEXTURESPROC glad_glGenTextures; +#define glGenTextures glad_glGenTextures +GLAD_API_CALL PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays; +#define glGenVertexArrays glad_glGenVertexArrays +GLAD_API_CALL PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap; +#define glGenerateMipmap glad_glGenerateMipmap +GLAD_API_CALL PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib; +#define glGetActiveAttrib glad_glGetActiveAttrib +GLAD_API_CALL PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform; +#define glGetActiveUniform glad_glGetActiveUniform +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 PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders; +#define glGetAttachedShaders glad_glGetAttachedShaders +GLAD_API_CALL PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation; +#define glGetAttribLocation glad_glGetAttribLocation +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 PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv; +#define glGetBufferPointerv glad_glGetBufferPointerv +GLAD_API_CALL PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData; +#define glGetBufferSubData glad_glGetBufferSubData +GLAD_API_CALL PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage; +#define glGetCompressedTexImage glad_glGetCompressedTexImage +GLAD_API_CALL PFNGLGETDOUBLEVPROC glad_glGetDoublev; +#define glGetDoublev glad_glGetDoublev +GLAD_API_CALL PFNGLGETERRORPROC glad_glGetError; +#define glGetError glad_glGetError +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 PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv; +#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv +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 PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v; +#define glGetIntegeri_v glad_glGetIntegeri_v +GLAD_API_CALL PFNGLGETINTEGERVPROC glad_glGetIntegerv; +#define glGetIntegerv glad_glGetIntegerv +GLAD_API_CALL PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv; +#define glGetMultisamplefv glad_glGetMultisamplefv +GLAD_API_CALL PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog; +#define glGetProgramInfoLog glad_glGetProgramInfoLog +GLAD_API_CALL PFNGLGETPROGRAMIVPROC glad_glGetProgramiv; +#define glGetProgramiv glad_glGetProgramiv +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 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 PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource; +#define glGetShaderSource glad_glGetShaderSource +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 PFNGLGETSYNCIVPROC glad_glGetSynciv; +#define glGetSynciv glad_glGetSynciv +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 PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv; +#define glGetTexParameterIuiv glad_glGetTexParameterIuiv +GLAD_API_CALL PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv; +#define glGetTexParameterfv glad_glGetTexParameterfv +GLAD_API_CALL PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv; +#define glGetTexParameteriv glad_glGetTexParameteriv +GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying; +#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying +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 PFNGLGETUNIFORMFVPROC glad_glGetUniformfv; +#define glGetUniformfv glad_glGetUniformfv +GLAD_API_CALL PFNGLGETUNIFORMIVPROC glad_glGetUniformiv; +#define glGetUniformiv glad_glGetUniformiv +GLAD_API_CALL PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv; +#define glGetUniformuiv glad_glGetUniformuiv +GLAD_API_CALL PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv; +#define glGetVertexAttribIiv glad_glGetVertexAttribIiv +GLAD_API_CALL PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv; +#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv +GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv; +#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv +GLAD_API_CALL PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv; +#define glGetVertexAttribdv glad_glGetVertexAttribdv +GLAD_API_CALL PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv; +#define glGetVertexAttribfv glad_glGetVertexAttribfv +GLAD_API_CALL PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv; +#define glGetVertexAttribiv glad_glGetVertexAttribiv +GLAD_API_CALL PFNGLHINTPROC glad_glHint; +#define glHint glad_glHint +GLAD_API_CALL PFNGLISBUFFERPROC glad_glIsBuffer; +#define glIsBuffer glad_glIsBuffer +GLAD_API_CALL PFNGLISENABLEDPROC glad_glIsEnabled; +#define glIsEnabled glad_glIsEnabled +GLAD_API_CALL PFNGLISENABLEDIPROC glad_glIsEnabledi; +#define glIsEnabledi glad_glIsEnabledi +GLAD_API_CALL PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer; +#define glIsFramebuffer glad_glIsFramebuffer +GLAD_API_CALL PFNGLISPROGRAMPROC glad_glIsProgram; +#define glIsProgram glad_glIsProgram +GLAD_API_CALL PFNGLISQUERYPROC glad_glIsQuery; +#define glIsQuery glad_glIsQuery +GLAD_API_CALL PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer; +#define glIsRenderbuffer glad_glIsRenderbuffer +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 PFNGLISVERTEXARRAYPROC glad_glIsVertexArray; +#define glIsVertexArray glad_glIsVertexArray +GLAD_API_CALL PFNGLLINEWIDTHPROC glad_glLineWidth; +#define glLineWidth glad_glLineWidth +GLAD_API_CALL PFNGLLINKPROGRAMPROC glad_glLinkProgram; +#define glLinkProgram glad_glLinkProgram +GLAD_API_CALL PFNGLLOGICOPPROC glad_glLogicOp; +#define glLogicOp glad_glLogicOp +GLAD_API_CALL PFNGLMAPBUFFERPROC glad_glMapBuffer; +#define glMapBuffer glad_glMapBuffer +GLAD_API_CALL PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange; +#define glMapBufferRange glad_glMapBufferRange +GLAD_API_CALL PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays; +#define glMultiDrawArrays glad_glMultiDrawArrays +GLAD_API_CALL PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements; +#define glMultiDrawElements glad_glMultiDrawElements +GLAD_API_CALL PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex; +#define glMultiDrawElementsBaseVertex glad_glMultiDrawElementsBaseVertex +GLAD_API_CALL PFNGLPIXELSTOREFPROC glad_glPixelStoref; +#define glPixelStoref glad_glPixelStoref +GLAD_API_CALL PFNGLPIXELSTOREIPROC glad_glPixelStorei; +#define glPixelStorei glad_glPixelStorei +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 PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex; +#define glPrimitiveRestartIndex glad_glPrimitiveRestartIndex +GLAD_API_CALL PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex; +#define glProvokingVertex glad_glProvokingVertex +GLAD_API_CALL PFNGLQUERYCOUNTERPROC glad_glQueryCounter; +#define glQueryCounter glad_glQueryCounter +GLAD_API_CALL PFNGLREADBUFFERPROC glad_glReadBuffer; +#define glReadBuffer glad_glReadBuffer +GLAD_API_CALL PFNGLREADPIXELSPROC glad_glReadPixels; +#define glReadPixels glad_glReadPixels +GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage; +#define glRenderbufferStorage glad_glRenderbufferStorage +GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample; +#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample +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 PFNGLSCISSORPROC glad_glScissor; +#define glScissor glad_glScissor +GLAD_API_CALL PFNGLSHADERSOURCEPROC glad_glShaderSource; +#define glShaderSource glad_glShaderSource +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 PFNGLTEXBUFFERPROC glad_glTexBuffer; +#define glTexBuffer glad_glTexBuffer +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 PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv; +#define glTexParameterIuiv glad_glTexParameterIuiv +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 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 PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings; +#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings +GLAD_API_CALL PFNGLUNIFORM1FPROC glad_glUniform1f; +#define glUniform1f glad_glUniform1f +GLAD_API_CALL PFNGLUNIFORM1FVPROC glad_glUniform1fv; +#define glUniform1fv glad_glUniform1fv +GLAD_API_CALL PFNGLUNIFORM1IPROC glad_glUniform1i; +#define glUniform1i glad_glUniform1i +GLAD_API_CALL PFNGLUNIFORM1IVPROC glad_glUniform1iv; +#define glUniform1iv glad_glUniform1iv +GLAD_API_CALL PFNGLUNIFORM1UIPROC glad_glUniform1ui; +#define glUniform1ui glad_glUniform1ui +GLAD_API_CALL PFNGLUNIFORM1UIVPROC glad_glUniform1uiv; +#define glUniform1uiv glad_glUniform1uiv +GLAD_API_CALL PFNGLUNIFORM2FPROC glad_glUniform2f; +#define glUniform2f glad_glUniform2f +GLAD_API_CALL PFNGLUNIFORM2FVPROC glad_glUniform2fv; +#define glUniform2fv glad_glUniform2fv +GLAD_API_CALL PFNGLUNIFORM2IPROC glad_glUniform2i; +#define glUniform2i glad_glUniform2i +GLAD_API_CALL PFNGLUNIFORM2IVPROC glad_glUniform2iv; +#define glUniform2iv glad_glUniform2iv +GLAD_API_CALL PFNGLUNIFORM2UIPROC glad_glUniform2ui; +#define glUniform2ui glad_glUniform2ui +GLAD_API_CALL PFNGLUNIFORM2UIVPROC glad_glUniform2uiv; +#define glUniform2uiv glad_glUniform2uiv +GLAD_API_CALL PFNGLUNIFORM3FPROC glad_glUniform3f; +#define glUniform3f glad_glUniform3f +GLAD_API_CALL PFNGLUNIFORM3FVPROC glad_glUniform3fv; +#define glUniform3fv glad_glUniform3fv +GLAD_API_CALL PFNGLUNIFORM3IPROC glad_glUniform3i; +#define glUniform3i glad_glUniform3i +GLAD_API_CALL PFNGLUNIFORM3IVPROC glad_glUniform3iv; +#define glUniform3iv glad_glUniform3iv +GLAD_API_CALL PFNGLUNIFORM3UIPROC glad_glUniform3ui; +#define glUniform3ui glad_glUniform3ui +GLAD_API_CALL PFNGLUNIFORM3UIVPROC glad_glUniform3uiv; +#define glUniform3uiv glad_glUniform3uiv +GLAD_API_CALL PFNGLUNIFORM4FPROC glad_glUniform4f; +#define glUniform4f glad_glUniform4f +GLAD_API_CALL PFNGLUNIFORM4FVPROC glad_glUniform4fv; +#define glUniform4fv glad_glUniform4fv +GLAD_API_CALL PFNGLUNIFORM4IPROC glad_glUniform4i; +#define glUniform4i glad_glUniform4i +GLAD_API_CALL PFNGLUNIFORM4IVPROC glad_glUniform4iv; +#define glUniform4iv glad_glUniform4iv +GLAD_API_CALL PFNGLUNIFORM4UIPROC glad_glUniform4ui; +#define glUniform4ui glad_glUniform4ui +GLAD_API_CALL PFNGLUNIFORM4UIVPROC glad_glUniform4uiv; +#define glUniform4uiv glad_glUniform4uiv +GLAD_API_CALL PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding; +#define glUniformBlockBinding glad_glUniformBlockBinding +GLAD_API_CALL PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv; +#define glUniformMatrix2fv glad_glUniformMatrix2fv +GLAD_API_CALL PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv; +#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv +GLAD_API_CALL PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv; +#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv +GLAD_API_CALL PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv; +#define glUniformMatrix3fv glad_glUniformMatrix3fv +GLAD_API_CALL PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv; +#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv +GLAD_API_CALL PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv; +#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv +GLAD_API_CALL PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv; +#define glUniformMatrix4fv glad_glUniformMatrix4fv +GLAD_API_CALL PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv; +#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv +GLAD_API_CALL PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv; +#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv +GLAD_API_CALL PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer; +#define glUnmapBuffer glad_glUnmapBuffer +GLAD_API_CALL PFNGLUSEPROGRAMPROC glad_glUseProgram; +#define glUseProgram glad_glUseProgram +GLAD_API_CALL PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram; +#define glValidateProgram glad_glValidateProgram +GLAD_API_CALL PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d; +#define glVertexAttrib1d glad_glVertexAttrib1d +GLAD_API_CALL PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv; +#define glVertexAttrib1dv glad_glVertexAttrib1dv +GLAD_API_CALL PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f; +#define glVertexAttrib1f glad_glVertexAttrib1f +GLAD_API_CALL PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv; +#define glVertexAttrib1fv glad_glVertexAttrib1fv +GLAD_API_CALL PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s; +#define glVertexAttrib1s glad_glVertexAttrib1s +GLAD_API_CALL PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv; +#define glVertexAttrib1sv glad_glVertexAttrib1sv +GLAD_API_CALL PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d; +#define glVertexAttrib2d glad_glVertexAttrib2d +GLAD_API_CALL PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv; +#define glVertexAttrib2dv glad_glVertexAttrib2dv +GLAD_API_CALL PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f; +#define glVertexAttrib2f glad_glVertexAttrib2f +GLAD_API_CALL PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv; +#define glVertexAttrib2fv glad_glVertexAttrib2fv +GLAD_API_CALL PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s; +#define glVertexAttrib2s glad_glVertexAttrib2s +GLAD_API_CALL PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv; +#define glVertexAttrib2sv glad_glVertexAttrib2sv +GLAD_API_CALL PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d; +#define glVertexAttrib3d glad_glVertexAttrib3d +GLAD_API_CALL PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv; +#define glVertexAttrib3dv glad_glVertexAttrib3dv +GLAD_API_CALL PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f; +#define glVertexAttrib3f glad_glVertexAttrib3f +GLAD_API_CALL PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv; +#define glVertexAttrib3fv glad_glVertexAttrib3fv +GLAD_API_CALL PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s; +#define glVertexAttrib3s glad_glVertexAttrib3s +GLAD_API_CALL PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv; +#define glVertexAttrib3sv glad_glVertexAttrib3sv +GLAD_API_CALL PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv; +#define glVertexAttrib4Nbv glad_glVertexAttrib4Nbv +GLAD_API_CALL PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv; +#define glVertexAttrib4Niv glad_glVertexAttrib4Niv +GLAD_API_CALL PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv; +#define glVertexAttrib4Nsv glad_glVertexAttrib4Nsv +GLAD_API_CALL PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub; +#define glVertexAttrib4Nub glad_glVertexAttrib4Nub +GLAD_API_CALL PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv; +#define glVertexAttrib4Nubv glad_glVertexAttrib4Nubv +GLAD_API_CALL PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv; +#define glVertexAttrib4Nuiv glad_glVertexAttrib4Nuiv +GLAD_API_CALL PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv; +#define glVertexAttrib4Nusv glad_glVertexAttrib4Nusv +GLAD_API_CALL PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv; +#define glVertexAttrib4bv glad_glVertexAttrib4bv +GLAD_API_CALL PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d; +#define glVertexAttrib4d glad_glVertexAttrib4d +GLAD_API_CALL PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv; +#define glVertexAttrib4dv glad_glVertexAttrib4dv +GLAD_API_CALL PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f; +#define glVertexAttrib4f glad_glVertexAttrib4f +GLAD_API_CALL PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv; +#define glVertexAttrib4fv glad_glVertexAttrib4fv +GLAD_API_CALL PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv; +#define glVertexAttrib4iv glad_glVertexAttrib4iv +GLAD_API_CALL PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s; +#define glVertexAttrib4s glad_glVertexAttrib4s +GLAD_API_CALL PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv; +#define glVertexAttrib4sv glad_glVertexAttrib4sv +GLAD_API_CALL PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv; +#define glVertexAttrib4ubv glad_glVertexAttrib4ubv +GLAD_API_CALL PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv; +#define glVertexAttrib4uiv glad_glVertexAttrib4uiv +GLAD_API_CALL PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv; +#define glVertexAttrib4usv glad_glVertexAttrib4usv +GLAD_API_CALL PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor; +#define glVertexAttribDivisor glad_glVertexAttribDivisor +GLAD_API_CALL PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i; +#define glVertexAttribI1i glad_glVertexAttribI1i +GLAD_API_CALL PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv; +#define glVertexAttribI1iv glad_glVertexAttribI1iv +GLAD_API_CALL PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui; +#define glVertexAttribI1ui glad_glVertexAttribI1ui +GLAD_API_CALL PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv; +#define glVertexAttribI1uiv glad_glVertexAttribI1uiv +GLAD_API_CALL PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i; +#define glVertexAttribI2i glad_glVertexAttribI2i +GLAD_API_CALL PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv; +#define glVertexAttribI2iv glad_glVertexAttribI2iv +GLAD_API_CALL PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui; +#define glVertexAttribI2ui glad_glVertexAttribI2ui +GLAD_API_CALL PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv; +#define glVertexAttribI2uiv glad_glVertexAttribI2uiv +GLAD_API_CALL PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i; +#define glVertexAttribI3i glad_glVertexAttribI3i +GLAD_API_CALL PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv; +#define glVertexAttribI3iv glad_glVertexAttribI3iv +GLAD_API_CALL PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui; +#define glVertexAttribI3ui glad_glVertexAttribI3ui +GLAD_API_CALL PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv; +#define glVertexAttribI3uiv glad_glVertexAttribI3uiv +GLAD_API_CALL PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv; +#define glVertexAttribI4bv glad_glVertexAttribI4bv +GLAD_API_CALL PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i; +#define glVertexAttribI4i glad_glVertexAttribI4i +GLAD_API_CALL PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv; +#define glVertexAttribI4iv glad_glVertexAttribI4iv +GLAD_API_CALL PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv; +#define glVertexAttribI4sv glad_glVertexAttribI4sv +GLAD_API_CALL PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv; +#define glVertexAttribI4ubv glad_glVertexAttribI4ubv +GLAD_API_CALL PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui; +#define glVertexAttribI4ui glad_glVertexAttribI4ui +GLAD_API_CALL PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv; +#define glVertexAttribI4uiv glad_glVertexAttribI4uiv +GLAD_API_CALL PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv; +#define glVertexAttribI4usv glad_glVertexAttribI4usv +GLAD_API_CALL PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer; +#define glVertexAttribIPointer glad_glVertexAttribIPointer +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 PFNGLVIEWPORTPROC glad_glViewport; +#define glViewport glad_glViewport +GLAD_API_CALL PFNGLWAITSYNCPROC glad_glWaitSync; +#define glWaitSync glad_glWaitSync + + + + + +GLAD_API_CALL int gladLoadGLUserPtr( GLADuserptrloadfunc load, void *userptr); +GLAD_API_CALL int gladLoadGL( GLADloadfunc load); + + +#ifdef GLAD_GL + +GLAD_API_CALL int gladLoaderLoadGL(void); +GLAD_API_CALL void gladLoaderUnloadGL(void); + +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/libs/glad/src/gl.c b/libs/glad/src/gl.c new file mode 100644 index 0000000..840cefc --- /dev/null +++ b/libs/glad/src/gl.c @@ -0,0 +1,1127 @@ +#include +#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; + + + +PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL; +PFNGLATTACHSHADERPROC glad_glAttachShader = NULL; +PFNGLBEGINCONDITIONALRENDERPROC glad_glBeginConditionalRender = NULL; +PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL; +PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL; +PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL; +PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL; +PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL; +PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL; +PFNGLBINDFRAGDATALOCATIONPROC glad_glBindFragDataLocation = NULL; +PFNGLBINDFRAGDATALOCATIONINDEXEDPROC glad_glBindFragDataLocationIndexed = NULL; +PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL; +PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL; +PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL; +PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL; +PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL; +PFNGLBLENDCOLORPROC glad_glBlendColor = NULL; +PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL; +PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL; +PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL; +PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL; +PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL; +PFNGLBUFFERDATAPROC glad_glBufferData = NULL; +PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL; +PFNGLCLAMPCOLORPROC glad_glClampColor = NULL; +PFNGLCLEARPROC glad_glClear = NULL; +PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL; +PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL; +PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL; +PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL; +PFNGLCLEARCOLORPROC glad_glClearColor = NULL; +PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL; +PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL; +PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL; +PFNGLCOLORMASKPROC glad_glColorMask = NULL; +PFNGLCOLORMASKIPROC glad_glColorMaski = NULL; +PFNGLCOMPILESHADERPROC glad_glCompileShader = 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; +PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL; +PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL; +PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL; +PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL; +PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL; +PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL; +PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL; +PFNGLCREATESHADERPROC glad_glCreateShader = NULL; +PFNGLCULLFACEPROC glad_glCullFace = NULL; +PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL; +PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL; +PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL; +PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL; +PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL; +PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL; +PFNGLDELETESHADERPROC glad_glDeleteShader = NULL; +PFNGLDELETESYNCPROC glad_glDeleteSync = NULL; +PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL; +PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL; +PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL; +PFNGLDEPTHMASKPROC glad_glDepthMask = NULL; +PFNGLDEPTHRANGEPROC glad_glDepthRange = NULL; +PFNGLDETACHSHADERPROC glad_glDetachShader = NULL; +PFNGLDISABLEPROC glad_glDisable = NULL; +PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL; +PFNGLDISABLEIPROC glad_glDisablei = NULL; +PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL; +PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL; +PFNGLDRAWBUFFERPROC glad_glDrawBuffer = NULL; +PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL; +PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL; +PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL; +PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL; +PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL; +PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL; +PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL; +PFNGLENABLEPROC glad_glEnable = NULL; +PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL; +PFNGLENABLEIPROC glad_glEnablei = NULL; +PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL; +PFNGLENDQUERYPROC glad_glEndQuery = NULL; +PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL; +PFNGLFENCESYNCPROC glad_glFenceSync = NULL; +PFNGLFINISHPROC glad_glFinish = NULL; +PFNGLFLUSHPROC glad_glFlush = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL; +PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL; +PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL; +PFNGLFRAMEBUFFERTEXTURE1DPROC glad_glFramebufferTexture1D = NULL; +PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL; +PFNGLFRAMEBUFFERTEXTURE3DPROC glad_glFramebufferTexture3D = NULL; +PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL; +PFNGLFRONTFACEPROC glad_glFrontFace = NULL; +PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL; +PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL; +PFNGLGENQUERIESPROC glad_glGenQueries = NULL; +PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL; +PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL; +PFNGLGENTEXTURESPROC glad_glGenTextures = NULL; +PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL; +PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL; +PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL; +PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL; +PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL; +PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL; +PFNGLGETACTIVEUNIFORMNAMEPROC glad_glGetActiveUniformName = NULL; +PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL; +PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL; +PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL; +PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL; +PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL; +PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL; +PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL; +PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL; +PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL; +PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL; +PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL; +PFNGLGETERRORPROC glad_glGetError = NULL; +PFNGLGETFLOATVPROC glad_glGetFloatv = NULL; +PFNGLGETFRAGDATAINDEXPROC glad_glGetFragDataIndex = NULL; +PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL; +PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL; +PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL; +PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL; +PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL; +PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL; +PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL; +PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = 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; +PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL; +PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL; +PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL; +PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL; +PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL; +PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL; +PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL; +PFNGLGETSTRINGPROC glad_glGetString = NULL; +PFNGLGETSTRINGIPROC glad_glGetStringi = NULL; +PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL; +PFNGLGETTEXIMAGEPROC glad_glGetTexImage = NULL; +PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL; +PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL; +PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL; +PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL; +PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL; +PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL; +PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL; +PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL; +PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL; +PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL; +PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL; +PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL; +PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL; +PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL; +PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL; +PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL; +PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL; +PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL; +PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL; +PFNGLHINTPROC glad_glHint = NULL; +PFNGLISBUFFERPROC glad_glIsBuffer = NULL; +PFNGLISENABLEDPROC glad_glIsEnabled = NULL; +PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL; +PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL; +PFNGLISPROGRAMPROC glad_glIsProgram = NULL; +PFNGLISQUERYPROC glad_glIsQuery = NULL; +PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL; +PFNGLISSAMPLERPROC glad_glIsSampler = NULL; +PFNGLISSHADERPROC glad_glIsShader = NULL; +PFNGLISSYNCPROC glad_glIsSync = NULL; +PFNGLISTEXTUREPROC glad_glIsTexture = NULL; +PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL; +PFNGLLINEWIDTHPROC glad_glLineWidth = NULL; +PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL; +PFNGLLOGICOPPROC glad_glLogicOp = NULL; +PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL; +PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL; +PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL; +PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL; +PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL; +PFNGLPIXELSTOREFPROC glad_glPixelStoref = NULL; +PFNGLPIXELSTOREIPROC glad_glPixelStorei = 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; +PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL; +PFNGLPROVOKINGVERTEXPROC glad_glProvokingVertex = NULL; +PFNGLQUERYCOUNTERPROC glad_glQueryCounter = NULL; +PFNGLREADBUFFERPROC glad_glReadBuffer = NULL; +PFNGLREADPIXELSPROC glad_glReadPixels = NULL; +PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL; +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = 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; +PFNGLSCISSORPROC glad_glScissor = NULL; +PFNGLSHADERSOURCEPROC glad_glShaderSource = 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; +PFNGLTEXBUFFERPROC glad_glTexBuffer = 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; +PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL; +PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL; +PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL; +PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL; +PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL; +PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL; +PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL; +PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL; +PFNGLUNIFORM1FPROC glad_glUniform1f = NULL; +PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL; +PFNGLUNIFORM1IPROC glad_glUniform1i = NULL; +PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL; +PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL; +PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL; +PFNGLUNIFORM2FPROC glad_glUniform2f = NULL; +PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL; +PFNGLUNIFORM2IPROC glad_glUniform2i = NULL; +PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL; +PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL; +PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL; +PFNGLUNIFORM3FPROC glad_glUniform3f = NULL; +PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL; +PFNGLUNIFORM3IPROC glad_glUniform3i = NULL; +PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL; +PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL; +PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL; +PFNGLUNIFORM4FPROC glad_glUniform4f = NULL; +PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL; +PFNGLUNIFORM4IPROC glad_glUniform4i = NULL; +PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL; +PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL; +PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL; +PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL; +PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL; +PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL; +PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL; +PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL; +PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL; +PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL; +PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL; +PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL; +PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL; +PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL; +PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL; +PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL; +PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL; +PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL; +PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL; +PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL; +PFNGLVERTEXATTRIB1SPROC glad_glVertexAttrib1s = NULL; +PFNGLVERTEXATTRIB1SVPROC glad_glVertexAttrib1sv = NULL; +PFNGLVERTEXATTRIB2DPROC glad_glVertexAttrib2d = NULL; +PFNGLVERTEXATTRIB2DVPROC glad_glVertexAttrib2dv = NULL; +PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL; +PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL; +PFNGLVERTEXATTRIB2SPROC glad_glVertexAttrib2s = NULL; +PFNGLVERTEXATTRIB2SVPROC glad_glVertexAttrib2sv = NULL; +PFNGLVERTEXATTRIB3DPROC glad_glVertexAttrib3d = NULL; +PFNGLVERTEXATTRIB3DVPROC glad_glVertexAttrib3dv = NULL; +PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL; +PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL; +PFNGLVERTEXATTRIB3SPROC glad_glVertexAttrib3s = NULL; +PFNGLVERTEXATTRIB3SVPROC glad_glVertexAttrib3sv = NULL; +PFNGLVERTEXATTRIB4NBVPROC glad_glVertexAttrib4Nbv = NULL; +PFNGLVERTEXATTRIB4NIVPROC glad_glVertexAttrib4Niv = NULL; +PFNGLVERTEXATTRIB4NSVPROC glad_glVertexAttrib4Nsv = NULL; +PFNGLVERTEXATTRIB4NUBPROC glad_glVertexAttrib4Nub = NULL; +PFNGLVERTEXATTRIB4NUBVPROC glad_glVertexAttrib4Nubv = NULL; +PFNGLVERTEXATTRIB4NUIVPROC glad_glVertexAttrib4Nuiv = NULL; +PFNGLVERTEXATTRIB4NUSVPROC glad_glVertexAttrib4Nusv = NULL; +PFNGLVERTEXATTRIB4BVPROC glad_glVertexAttrib4bv = NULL; +PFNGLVERTEXATTRIB4DPROC glad_glVertexAttrib4d = NULL; +PFNGLVERTEXATTRIB4DVPROC glad_glVertexAttrib4dv = NULL; +PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL; +PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL; +PFNGLVERTEXATTRIB4IVPROC glad_glVertexAttrib4iv = NULL; +PFNGLVERTEXATTRIB4SPROC glad_glVertexAttrib4s = NULL; +PFNGLVERTEXATTRIB4SVPROC glad_glVertexAttrib4sv = NULL; +PFNGLVERTEXATTRIB4UBVPROC glad_glVertexAttrib4ubv = NULL; +PFNGLVERTEXATTRIB4UIVPROC glad_glVertexAttrib4uiv = NULL; +PFNGLVERTEXATTRIB4USVPROC glad_glVertexAttrib4usv = NULL; +PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL; +PFNGLVERTEXATTRIBI1IPROC glad_glVertexAttribI1i = NULL; +PFNGLVERTEXATTRIBI1IVPROC glad_glVertexAttribI1iv = NULL; +PFNGLVERTEXATTRIBI1UIPROC glad_glVertexAttribI1ui = NULL; +PFNGLVERTEXATTRIBI1UIVPROC glad_glVertexAttribI1uiv = NULL; +PFNGLVERTEXATTRIBI2IPROC glad_glVertexAttribI2i = NULL; +PFNGLVERTEXATTRIBI2IVPROC glad_glVertexAttribI2iv = NULL; +PFNGLVERTEXATTRIBI2UIPROC glad_glVertexAttribI2ui = NULL; +PFNGLVERTEXATTRIBI2UIVPROC glad_glVertexAttribI2uiv = NULL; +PFNGLVERTEXATTRIBI3IPROC glad_glVertexAttribI3i = NULL; +PFNGLVERTEXATTRIBI3IVPROC glad_glVertexAttribI3iv = NULL; +PFNGLVERTEXATTRIBI3UIPROC glad_glVertexAttribI3ui = NULL; +PFNGLVERTEXATTRIBI3UIVPROC glad_glVertexAttribI3uiv = NULL; +PFNGLVERTEXATTRIBI4BVPROC glad_glVertexAttribI4bv = NULL; +PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL; +PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL; +PFNGLVERTEXATTRIBI4SVPROC glad_glVertexAttribI4sv = NULL; +PFNGLVERTEXATTRIBI4UBVPROC glad_glVertexAttribI4ubv = NULL; +PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL; +PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL; +PFNGLVERTEXATTRIBI4USVPROC glad_glVertexAttribI4usv = NULL; +PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = 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; +PFNGLVIEWPORTPROC glad_glViewport = NULL; +PFNGLWAITSYNCPROC glad_glWaitSync = NULL; + + +static void glad_gl_load_GL_VERSION_1_0( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_VERSION_1_0) return; + glad_glBlendFunc = (PFNGLBLENDFUNCPROC) load(userptr, "glBlendFunc"); + glad_glClear = (PFNGLCLEARPROC) load(userptr, "glClear"); + glad_glClearColor = (PFNGLCLEARCOLORPROC) load(userptr, "glClearColor"); + glad_glClearDepth = (PFNGLCLEARDEPTHPROC) load(userptr, "glClearDepth"); + glad_glClearStencil = (PFNGLCLEARSTENCILPROC) load(userptr, "glClearStencil"); + glad_glColorMask = (PFNGLCOLORMASKPROC) load(userptr, "glColorMask"); + glad_glCullFace = (PFNGLCULLFACEPROC) load(userptr, "glCullFace"); + 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_glEnable = (PFNGLENABLEPROC) load(userptr, "glEnable"); + glad_glFinish = (PFNGLFINISHPROC) load(userptr, "glFinish"); + glad_glFlush = (PFNGLFLUSHPROC) load(userptr, "glFlush"); + glad_glFrontFace = (PFNGLFRONTFACEPROC) load(userptr, "glFrontFace"); + glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC) load(userptr, "glGetBooleanv"); + 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_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString"); + 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_glIsEnabled = (PFNGLISENABLEDPROC) load(userptr, "glIsEnabled"); + glad_glLineWidth = (PFNGLLINEWIDTHPROC) load(userptr, "glLineWidth"); + glad_glLogicOp = (PFNGLLOGICOPPROC) load(userptr, "glLogicOp"); + glad_glPixelStoref = (PFNGLPIXELSTOREFPROC) load(userptr, "glPixelStoref"); + glad_glPixelStorei = (PFNGLPIXELSTOREIPROC) load(userptr, "glPixelStorei"); + glad_glPointSize = (PFNGLPOINTSIZEPROC) load(userptr, "glPointSize"); + glad_glPolygonMode = (PFNGLPOLYGONMODEPROC) load(userptr, "glPolygonMode"); + glad_glReadBuffer = (PFNGLREADBUFFERPROC) load(userptr, "glReadBuffer"); + glad_glReadPixels = (PFNGLREADPIXELSPROC) load(userptr, "glReadPixels"); + glad_glScissor = (PFNGLSCISSORPROC) load(userptr, "glScissor"); + glad_glStencilFunc = (PFNGLSTENCILFUNCPROC) load(userptr, "glStencilFunc"); + glad_glStencilMask = (PFNGLSTENCILMASKPROC) load(userptr, "glStencilMask"); + glad_glStencilOp = (PFNGLSTENCILOPPROC) load(userptr, "glStencilOp"); + 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_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_glBindTexture = (PFNGLBINDTEXTUREPROC) load(userptr, "glBindTexture"); + 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_glDrawArrays = (PFNGLDRAWARRAYSPROC) load(userptr, "glDrawArrays"); + glad_glDrawElements = (PFNGLDRAWELEMENTSPROC) load(userptr, "glDrawElements"); + glad_glGenTextures = (PFNGLGENTEXTURESPROC) load(userptr, "glGenTextures"); + glad_glIsTexture = (PFNGLISTEXTUREPROC) load(userptr, "glIsTexture"); + glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load(userptr, "glPolygonOffset"); + glad_glTexSubImage1D = (PFNGLTEXSUBIMAGE1DPROC) load(userptr, "glTexSubImage1D"); + glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load(userptr, "glTexSubImage2D"); +} +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_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_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_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"); +} +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_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_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_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"); +} + + + +#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0) +#define GLAD_GL_IS_SOME_NEW_VERSION 1 +#else +#define GLAD_GL_IS_SOME_NEW_VERSION 0 +#endif + +static int glad_gl_get_extensions( int version, const char **out_exts, unsigned int *out_num_exts_i, char ***out_exts_i) { +#if GLAD_GL_IS_SOME_NEW_VERSION + if(GLAD_VERSION_MAJOR(version) < 3) { +#else + (void) version; + (void) out_num_exts_i; + (void) out_exts_i; +#endif + if (glad_glGetString == NULL) { + return 0; + } + *out_exts = (const char *)glad_glGetString(GL_EXTENSIONS); +#if GLAD_GL_IS_SOME_NEW_VERSION + } else { + unsigned int index = 0; + unsigned int num_exts_i = 0; + char **exts_i = NULL; + if (glad_glGetStringi == NULL || glad_glGetIntegerv == NULL) { + return 0; + } + glad_glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i); + if (num_exts_i > 0) { + exts_i = (char **) malloc(num_exts_i * (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) { + memcpy(local_str, gl_str_tmp, len * sizeof(char)); + } + + exts_i[index] = local_str; + } + + *out_num_exts_i = num_exts_i; + *out_exts_i = exts_i; + } +#endif + return 1; +} +static void glad_gl_free_extensions(char **exts_i, unsigned int num_exts_i) { + if (exts_i != NULL) { + unsigned int index; + for(index = 0; index < num_exts_i; index++) { + free((void *) (exts_i[index])); + } + free((void *)exts_i); + exts_i = NULL; + } +} +static int glad_gl_has_extension(int version, const char *exts, unsigned int num_exts_i, char **exts_i, const char *ext) { + if(GLAD_VERSION_MAJOR(version) < 3 || !GLAD_GL_IS_SOME_NEW_VERSION) { + 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; + } + } else { + unsigned int index; + for(index = 0; index < num_exts_i; index++) { + const char *e = exts_i[index]; + if(strcmp(e, ext) == 0) { + return 1; + } + } + } + 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( int version) { + const char *exts = NULL; + unsigned int num_exts_i = 0; + char **exts_i = NULL; + if (!glad_gl_get_extensions(version, &exts, &num_exts_i, &exts_i)) return 0; + + (void) glad_gl_has_extension; + + glad_gl_free_extensions(exts_i, num_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; + + 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; + if(glad_glGetString(GL_VERSION) == 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); + + if (!glad_gl_find_extensions_gl(version)) return 0; + + + + return version; +} + + +int gladLoadGL( GLADloadfunc load) { + return gladLoadGLUserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load); +} + + + + + +#ifdef GLAD_GL + +#ifndef GLAD_LOADER_LIBRARY_C_ +#define GLAD_LOADER_LIBRARY_C_ + +#include +#include + +#if GLAD_PLATFORM_WIN32 +#include +#else +#include +#endif + + +static void* glad_get_dlopen_handle(const char *lib_names[], int length) { + void *handle = NULL; + int i; + + for (i = 0; i < length; ++i) { +#if GLAD_PLATFORM_WIN32 + #if GLAD_PLATFORM_UWP + size_t buffer_size = (strlen(lib_names[i]) + 1) * sizeof(WCHAR); + LPWSTR buffer = (LPWSTR) malloc(buffer_size); + if (buffer != NULL) { + int ret = MultiByteToWideChar(CP_ACP, 0, lib_names[i], -1, buffer, buffer_size); + if (ret != 0) { + handle = (void*) LoadPackagedLibrary(buffer, 0); + } + free((void*) buffer); + } + #else + handle = (void*) LoadLibraryA(lib_names[i]); + #endif +#else + handle = dlopen(lib_names[i], RTLD_LAZY | RTLD_LOCAL); +#endif + if (handle != NULL) { + return handle; + } + } + + return NULL; +} + +static void glad_close_dlopen_handle(void* handle) { + if (handle != NULL) { +#if GLAD_PLATFORM_WIN32 + FreeLibrary((HMODULE) handle); +#else + dlclose(handle); +#endif + } +} + +static GLADapiproc glad_dlsym_handle(void* handle, const char *name) { + if (handle == NULL) { + return NULL; + } + +#if GLAD_PLATFORM_WIN32 + return (GLADapiproc) GetProcAddress((HMODULE) handle, name); +#else + return GLAD_GNUC_EXTENSION (GLADapiproc) dlsym(handle, name); +#endif +} + +#endif /* GLAD_LOADER_LIBRARY_C_ */ + +typedef void* (GLAD_API_PTR *GLADglprocaddrfunc)(const char*); +struct _glad_gl_userptr { + void *handle; + GLADglprocaddrfunc gl_get_proc_address_ptr; +}; + +static GLADapiproc glad_gl_get_proc(void *vuserptr, const char *name) { + struct _glad_gl_userptr userptr = *(struct _glad_gl_userptr*) vuserptr; + GLADapiproc result = NULL; + + if(userptr.gl_get_proc_address_ptr != NULL) { + result = GLAD_GNUC_EXTENSION (GLADapiproc) userptr.gl_get_proc_address_ptr(name); + } + if(result == NULL) { + result = glad_dlsym_handle(userptr.handle, name); + } + + return result; +} + +static void* _gl_handle = NULL; + +static void* glad_gl_dlopen_handle(void) { +#if GLAD_PLATFORM_APPLE + static const char *NAMES[] = { + "../Frameworks/OpenGL.framework/OpenGL", + "/Library/Frameworks/OpenGL.framework/OpenGL", + "/System/Library/Frameworks/OpenGL.framework/OpenGL", + "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL" + }; +#elif GLAD_PLATFORM_WIN32 + static const char *NAMES[] = {"opengl32.dll"}; +#else + static const char *NAMES[] = { + #if defined(__CYGWIN__) + "libGL-1.so", + #endif + "libGL.so.1", + "libGL.so" + }; +#endif + + if (_gl_handle == NULL) { + _gl_handle = glad_get_dlopen_handle(NAMES, sizeof(NAMES) / sizeof(NAMES[0])); + } + + return _gl_handle; +} + +static struct _glad_gl_userptr glad_gl_build_userptr(void *handle) { + struct _glad_gl_userptr userptr; + + userptr.handle = handle; +#if GLAD_PLATFORM_APPLE || defined(__HAIKU__) + userptr.gl_get_proc_address_ptr = NULL; +#elif GLAD_PLATFORM_WIN32 + userptr.gl_get_proc_address_ptr = + (GLADglprocaddrfunc) glad_dlsym_handle(handle, "wglGetProcAddress"); +#else + userptr.gl_get_proc_address_ptr = + (GLADglprocaddrfunc) glad_dlsym_handle(handle, "glXGetProcAddressARB"); +#endif + + return userptr; +} + +int gladLoaderLoadGL(void) { + int version = 0; + void *handle; + int did_load = 0; + struct _glad_gl_userptr userptr; + + did_load = _gl_handle == NULL; + handle = glad_gl_dlopen_handle(); + if (handle) { + userptr = glad_gl_build_userptr(handle); + + version = gladLoadGLUserPtr(glad_gl_get_proc, &userptr); + + if (did_load) { + gladLoaderUnloadGL(); + } + } + + return version; +} + + + +void gladLoaderUnloadGL(void) { + if (_gl_handle != NULL) { + glad_close_dlopen_handle(_gl_handle); + _gl_handle = NULL; + } +} + +#endif /* GLAD_GL */ + +#ifdef __cplusplus +} +#endif diff --git a/libs/glfw/libglfw.3.dylib b/libs/glfw/libglfw.3.dylib new file mode 100755 index 0000000000000000000000000000000000000000..8c03fc60d522fe1add3709ed8146ca0f192f7e73 GIT binary patch literal 233166 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

(9B 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 literal 0 HcmV?d00001 diff --git a/libs/stb_image/stb_image.h b/libs/stb_image/stb_image.h new file mode 100644 index 0000000..7374743 --- /dev/null +++ b/libs/stb_image/stb_image.h @@ -0,0 +1,7873 @@ +/* stb_image - v2.27 - 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.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 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 + +#ifdef _MSC_VER +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 + +// 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); + 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]; + 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); + + 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); + 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); + 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; + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + 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 + 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; + + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + 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 + 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]; + } + 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; +} + +// 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 ) { + // handle 0s at the end of image data from IP Kamera 9060 + while (!stbi__at_eof(j->s)) { + int x = stbi__get8(j->s); + if (x == 255) { + j->marker = stbi__get8(j->s); + break; + } + } + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + } 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"); + } else { + if (!stbi__process_marker(j, m)) return 0; + } + 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"); + 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"); + 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"); + 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; + } + 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) return stbi__err("bad huffman code","Corrupt PNG"); + 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__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"); + if (scan == STBI__SCAN_header) return 1; + } 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"); + // if 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; + 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) { s->img_n = pal_img_n; return 1; } + 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) { + if (info.offset != s->callback_already_read + (s->img_buffer - s->img_buffer_original)) { + return stbi__errpuc("bad offset", "Corrupt BMP"); + } + } + + 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 > 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 > 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"); + stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8)); + + if (req_comp && req_comp != s->img_n) { + 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); + } + + 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 + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + 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/libs/stb_image/stbi_image.cpp b/libs/stb_image/stbi_image.cpp new file mode 100644 index 0000000..8ddfd1f --- /dev/null +++ b/libs/stb_image/stbi_image.cpp @@ -0,0 +1,2 @@ +#define STB_IMAGE_IMPLEMENTATION +#include "stb_image.h" diff --git a/log.hpp b/log.hpp new file mode 100644 index 0000000..ecc8c13 --- /dev/null +++ b/log.hpp @@ -0,0 +1,5 @@ +#pragma once + +#include "pch.hpp" + +#define Log(msg, ...) printf("[%s: %d] " msg, __func__, __LINE__, ## __VA_ARGS__) diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..96c7715 --- /dev/null +++ b/main.cpp @@ -0,0 +1,19 @@ +#include "engine.hpp" +#include "event.hpp" + +int main(int argc, char** argv) { + engine.Init("sandbox", Size{720, 480}); + + Color color{0.1, 0.1, 0.1, 1}; + Renderer::SetClearColor(color); + while (!engine.ShouldExit()) { + Renderer::Clear(); + engine.PollEvent(); + engine.Update(); + engine.Render(); + engine.SwapContext(); + } + + engine.Shutdown(); + return 0; +} diff --git a/pch.hpp b/pch.hpp new file mode 100644 index 0000000..93e1038 --- /dev/null +++ b/pch.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "glad/gl.h" +#include "GLFW/glfw3.h" +#include "stb_image.h" +#include +#include +#include +#include +#include +#include diff --git a/renderer.cpp b/renderer.cpp new file mode 100644 index 0000000..2a4e15e --- /dev/null +++ b/renderer.cpp @@ -0,0 +1,41 @@ +#include "renderer.hpp" + +struct RenderContext { + +}; + +void Renderer::Init() { + if (!gladLoadGL(glfwGetProcAddress)) { + glfwTerminate(); + throw std::runtime_error("glad load failed"); + } + + GL_CALL(glEnable(GL_DEPTH_TEST)); + GL_CALL(glEnable(GL_STENCIL_TEST)); +} + +void Renderer::SetClearColor(const Color& color) { + GL_CALL(glClearColor(color.r, color.g, color.b, color.a)); +} + +void Renderer::DrawLine(const Point& p1, const Point& p2) { +} + +void Renderer::DrawRect(const Rect& rect) { +} + +void Renderer::FillRect(const Rect& rect) { +} + +void Renderer::SetDrawColor(const Color& color) { +} + +void Renderer::Clear() { + GL_CALL(glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); +} + +void Renderer::SetViewport(int x, int y, int w, int h) { + GL_CALL(glViewport(x, y, w, h)); +} + +void Renderer::Shutdown() {} diff --git a/renderer.hpp b/renderer.hpp new file mode 100644 index 0000000..cff7a74 --- /dev/null +++ b/renderer.hpp @@ -0,0 +1,18 @@ +#pragma once +#include "libmath.hpp" +#include "texture.hpp" +#include "pch.hpp" +#include "glhelpfunc.hpp" + +class Renderer final { +public: + static void Init(); + static void Shutdown(); + static void SetClearColor(const Color& color); + static void SetDrawColor(const Color& color); + static void Clear(); + static void DrawLine(const Point& p1, const Point& p2); + static void DrawRect(const Rect& rect); + static void FillRect(const Rect& rect); + static void SetViewport(int x, int y, int w, int h); +}; diff --git a/shader.cpp b/shader.cpp new file mode 100644 index 0000000..ca7a76a --- /dev/null +++ b/shader.cpp @@ -0,0 +1,277 @@ +#include "shader.hpp" + +SourceCode::SourceCode(const std::string& code) + : code_(code) {} + +Shader::ShaderStruct::ShaderStruct(const SourceCode& code, Shader::ShaderStruct::Type type) { + if (code.Empty()) { return; } + switch (type) { + case ShaderStruct::Vertex: + Log("compiling vertex shader ..."); + GL_CALL(shader_ = glCreateShader(GL_VERTEX_SHADER)); + break; + case Fragment: + Log("compiling fragment shader ..."); + GL_CALL(shader_ = glCreateShader(GL_FRAGMENT_SHADER)); + break; + case Geometry: + Log("compiling geometry shader ..."); + GL_CALL(shader_ = glCreateShader(GL_GEOMETRY_SHADER)); + break; + } + if (shader_ == 0) { + Log("create shader failed"); + } else { + const GLchar* const sources[] = {code.GetCode().c_str()}; + GL_CALL(glShaderSource(shader_, 1, sources, nullptr)); + GL_CALL(glCompileShader(shader_)); + GLint err; + GL_CALL(glGetShaderiv(shader_, GL_COMPILE_STATUS, &err)); + if (err == GL_FALSE) { + char buf[1024] = {0}; + GL_CALL(glGetShaderInfoLog(shader_, sizeof(buf), nullptr, buf)); + Log("shader compile failed:\n%s", buf); + } + } +} + +Shader::ShaderStruct::~ShaderStruct() { + GL_CALL(glDeleteShader(shader_)); +} + +Shader::Shader(const SourceCode* vertex, + const SourceCode* fragment, + const SourceCode* geometry) { + if (vertex) { + shaders_[0].reset(new ShaderStruct(*vertex, ShaderStruct::Vertex)); + } + if (fragment) { + shaders_[1].reset(new ShaderStruct(*fragment, ShaderStruct::Fragment)); + } + if (geometry) { + shaders_[2].reset(new ShaderStruct(*geometry, ShaderStruct::Geometry)); + } + + GL_CALL(program_ = glCreateProgram()); + if (program_ == 0) { + Log("create shader program failed"); + } else { + for (const auto& shader : shaders_) { + if (shader) { + GL_CALL(glAttachShader(program_, shader->Get())); + } + } + GL_CALL(glLinkProgram(program_)); + GLint err; + GL_CALL(glGetProgramiv(program_, GL_LINK_STATUS, &err)); + if (err == GL_FALSE) { + char buf[1024] = {0}; + GL_CALL(glGetProgramInfoLog(program_, sizeof(buf), nullptr, buf)); + Log("link shader program failed:\n%s", buf); + } + } +} + +Shader::~Shader() { + for (auto& shader : shaders_) + shader.reset(); + GL_CALL(glDeleteProgram(program_)); +} + +void Shader::SetInt(const std::string& name, int i) { + GLint loc; + GL_CALL(loc = glGetUniformLocation(program_, name.c_str())); + if (loc == -1) { + Log("uniform variable %s is not found", name.c_str()); + } else { + Use(); + GL_CALL(glUniform1i(loc, i)); + } +} + +void Shader::SetInt2(const std::string& name, int i1, int i2) { + GLint loc; + GL_CALL(loc = glGetUniformLocation(program_, name.c_str())); + if (loc == -1) { + Log("uniform variable %s is not found", name.c_str()); + } else { + Use(); + GL_CALL(glUniform2i(loc, i1, i2)); + } +} + +void Shader::SetInt3(const std::string& name, int i1, int i2, int i3) { + GLint loc; + GL_CALL(loc = glGetUniformLocation(program_, name.c_str())); + if (loc == -1) { + Log("uniform variable %s is not found", name.c_str()); + } else { + Use(); + GL_CALL(glUniform3i(loc, i1, i2, i3)); + } +} + +void Shader::SetInt4(const std::string& name, int i1, int i2, int i3, int i4) { + GLint loc; + GL_CALL(loc = glGetUniformLocation(program_, name.c_str())); + if (loc == -1) { + Log("uniform variable %s is not found", name.c_str()); + } else { + Use(); + GL_CALL(glUniform4i(loc, i1, i2, i3, i4)); + } +} + +void Shader::SetFloat(const std::string& name, float f) { + GLint loc; + GL_CALL(loc = glGetUniformLocation(program_, name.c_str())); + if (loc == -1) { + Log("uniform variable %s is not found", name.c_str()); + } else { + Use(); + GL_CALL(glUniform1f(loc, f)); + } +} + +void Shader::SetFloat2(const std::string& name, float f1, float f2) { + GLint loc; + GL_CALL(loc = glGetUniformLocation(program_, name.c_str())); + if (loc == -1) { + Log("uniform variable %s is not found", name.c_str()); + } else { + Use(); + GL_CALL(glUniform2f(loc, f1, f2)); + } +} + +void Shader::SetFloat3(const std::string& name, float f1, float f2, float f3) { + GLint loc; + GL_CALL(loc = glGetUniformLocation(program_, name.c_str())); + if (loc == -1) { + Log("uniform variable %s is not found", name.c_str()); + } else { + Use(); + GL_CALL(glUniform3f(loc, f1, f2, f3)); + } +} + +void Shader::SetFloat4(const std::string& name, float f1, float f2, float f3, float f4) { + GLint loc; + GL_CALL(loc = glGetUniformLocation(program_, name.c_str())); + if (loc == -1) { + Log("uniform variable %s is not found", name.c_str()); + } else { + Use(); + GL_CALL(glUniform4f(loc, f1, f2, f3, f4)); + } +} + +// void Shader::SetMat4(const std::string& name, const glm::mat4& mat, bool transpose) { +// GLint loc; +// GL_CALL(loc = glGetUniformLocation(program_, name.c_str())); +// if (loc == -1) { +// Log("uniform variable %s is not found", name.c_str()); +// } else { +// Use(); +// GL_CALL(glUniformMatrix4fv(loc, 1, transpose ? GL_TRUE : GL_FALSE, glm::value_ptr(mat))); +// } +// } + +// void Shader::SetFloatVec3(const std::string& name, const glm::vec3& data) { +// GLint loc; +// GL_CALL(loc = glGetUniformLocation(program_, name.c_str())); +// if (loc == -1) { +// Log("uniform variable %s is not found", name.c_str()); +// } else { +// Use(); +// GL_CALL(glUniform3fv(loc, 1, glm::value_ptr(data))); +// } +// } + + +SourceCodePtr CreateSourceCodeFromFile(const std::string& filename) { + std::ifstream file(filename); + if (file.fail()) { + Log("SourceCodeRes %s load failed", filename.c_str()); + return nullptr; + } + std::string code((std::istreambuf_iterator(file)), + std::istreambuf_iterator()); + return CreateSourceCode(code); +} + +void parseShaderFile(const std::string& code, + std::string& vertexCode, + std::string& geometryCode, + std::string& fragmentCode) { + std::string::size_type pos[3] = {code.find("#type vertex"), + code.find("#type geometry"), + code.find("#type fragment")}; + /* 1 - vertex shader code + 2 - tessellation shader code + 3 - fragment shader code */ + std::string* codes[3] = {&vertexCode, + &geometryCode, + &fragmentCode}; + + // sort three code by their position + if (pos[0] > pos[1]) { + std::swap(pos[0], pos[1]); + std::swap(codes[0], codes[1]); + } + if (pos[1] > pos[2]) { + std::swap(pos[1], pos[2]); + std::swap(codes[1], codes[2]); + } + if (pos[0] > pos[1]) { + std::swap(pos[0], pos[1]); + std::swap(codes[0], codes[1]); + } + + // split file in codes + if (pos[0] != std::string::npos) { + if (pos[1] != std::string::npos) { + std::copy_n(code.begin() + pos[0], pos[1] - pos[0], std::back_inserter(*codes[0])); + } else { + std::copy(code.begin() + pos[0], code.end(), std::back_inserter(*codes[0])); + } + } + if (pos[1] != std::string::npos) { + if (pos[2] != std::string::npos) { + std::copy_n(code.begin() + pos[1], pos[2] - pos[1], std::back_inserter(*codes[1])); + } else { + std::copy(code.begin() + pos[1], code.end(), std::back_inserter(*codes[1])); + } + } + if (pos[2] != std::string::npos) { + std::copy(code.begin() + pos[2], code.end(), std::back_inserter(*codes[2])); + } + + for (auto& c : codes) { + c->erase(0, c->find_first_of('\n')); + } +} + +SourceCodeGroup CreateSourceCodeFromGroup(const std::string& code) { + std::string vertex, geometry, fragment; + parseShaderFile(code, vertex, geometry, fragment); + SourceCodeGroup group; + if (!vertex.empty()) + group.vertexCode = CreateSourceCode(vertex); + if (!geometry.empty()) + group.geometryCode = CreateSourceCode(geometry); + if (!fragment.empty()) + group.fragmentCode = CreateSourceCode(fragment); + return group; +} + +SourceCodeGroup CreateSourceCodeFromGroupFile(const std::string& filename) { + std::ifstream file(filename); + if (file.fail()) { + Log("SourceCodeRes %s load failed", filename.c_str()); + return {nullptr, nullptr, nullptr}; + } + std::string code((std::istreambuf_iterator(file)), + std::istreambuf_iterator()); + return CreateSourceCodeFromGroup(code); +} diff --git a/shader.hpp b/shader.hpp new file mode 100644 index 0000000..9caff04 --- /dev/null +++ b/shader.hpp @@ -0,0 +1,99 @@ +#pragma once +#include "pch.hpp" +#include "glhelpfunc.hpp" +#include "log.hpp" +#include "tool.hpp" + +class SourceCode { +public: + SourceCode(const std::string& code); + inline bool Empty() const { return code_.empty(); } + inline std::string& GetCode() { return code_; } + inline const std::string& GetCode() const { return code_;} + inline bool HasCode() const { return !code_.empty(); } + +private: + std::string code_; +}; + +inline std::ostream& operator<<(std::ostream& o, const SourceCode& res) { + o << res.GetCode(); + return o; +} + +class Shader final { +public: + Shader(const SourceCode* vertex, + const SourceCode* fragment, + const SourceCode* geometry = nullptr); + Shader(const Shader&) = delete; + ~Shader(); + Shader& operator=(const Shader&) = delete; + + inline bool Valid() const { return program_ != 0; } + GLuint Get() const { return program_; } + + void SetInt(const std::string& name, int i); + void SetInt2(const std::string& name, int i1, int i2); + void SetInt3(const std::string& name, int i1, int i2, int i3); + void SetInt4(const std::string& name, int i1, int i2, int i3, int i4); + void SetFloat(const std::string& name, float f); + void SetFloat2(const std::string& name, float f1, float f2); + void SetFloat3(const std::string& name, float f1, float f2, float f3); + void SetFloat4(const std::string& name, float f1, float f2, float f3, float f4); + // void SetMat4(const std::string& name, const glm::mat4& mat, bool transpose = false); + // void SetFloatVec3(const std::string& name, const glm::vec3&); + + inline void Use() const { GL_CALL(glUseProgram(program_)); } + +private: + class ShaderStruct final { + public: + enum Type { + Vertex, + Fragment, + Geometry, + }; + ShaderStruct(const SourceCode& code, Type type); + ~ShaderStruct(); + ShaderStruct(const Shader&) = delete; + Shader& operator=(const Shader&) = delete; + + inline bool Valid() const { return shader_ != 0; } + + GLuint Get() const { return shader_; } + + private: + GLuint shader_; + }; + + GLuint program_; + Unique shaders_[3]; +}; + +using SourceCodePtr = Ref; +using ShaderPtr = Ref; + +struct SourceCodeGroup { + SourceCodePtr vertexCode = nullptr; + SourceCodePtr geometryCode = nullptr; + SourceCodePtr fragmentCode = nullptr; +}; + +inline SourceCodePtr CreateSourceCode(const std::string& code) { + if (code.empty()) { + Log("source code is empty"); + return nullptr; + } + return SourceCodePtr(new SourceCode(code)); +} + +SourceCodePtr CreateSourceCodeFromFile(const std::string& filename); +SourceCodeGroup CreateSourceCodeFromGroup(const std::string& code); +SourceCodeGroup CreateSourceCodeFromGroupFile(const std::string& filename); + +inline ShaderPtr CreateShader(const SourceCode* vertex, + const SourceCode* fragment, + const SourceCode* geometry = nullptr) { + return ShaderPtr(new Shader(vertex, fragment, geometry)); +} diff --git a/texture.hpp b/texture.hpp new file mode 100644 index 0000000..1cd3c39 --- /dev/null +++ b/texture.hpp @@ -0,0 +1,5 @@ +#pragma once + +class Texture { +// TODO implement your own texture +}; diff --git a/tool.hpp b/tool.hpp new file mode 100644 index 0000000..9fa13ca --- /dev/null +++ b/tool.hpp @@ -0,0 +1,8 @@ +#pragma once +#include "pch.hpp" + +template +using Unique = std::unique_ptr; + +template +using Ref = std::shared_ptr;