diff --git a/CMakeLists.txt b/CMakeLists.txt index 577375eaab..587d263f8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,6 +200,7 @@ if( ${ZDOOM_TARGET_ARCH} MATCHES "x86_64" ) endif() option (HAVE_VULKAN "Enable Vulkan support" ON) +option (HAVE_GLES2 "Enable GLES2 support" ON) # no, we're not using external asmjit for now, we made too many modifications to our's. # if the asmjit author uses our changes then we'll update this. @@ -216,10 +217,14 @@ if( MSVC ) # String pooling # Function-level linking # Disable run-time type information + set( ALL_C_FLAGS "/GF /Gy /permissive- /DHAVE_SOFTPOLY" ) + if ( HAVE_VULKAN ) - set( ALL_C_FLAGS "/GF /Gy /permissive- /DHAVE_VULKAN /DHAVE_SOFTPOLY" ) - else() - set( ALL_C_FLAGS "/GF /Gy /permissive- /DHAVE_SOFTPOLY" ) + set( ALL_C_FLAGS "${ALL_C_FLAGS} /DHAVE_VULKAN" ) + endif() + + if ( HAVE_GLES2 ) + set( ALL_C_FLAGS "${ALL_C_FLAGS} /DHAVE_GLES2" ) endif() # Use SSE 2 as minimum always as the true color drawers needs it for __vectorcall @@ -254,10 +259,14 @@ if( MSVC ) string(REPLACE "/MDd " " " CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} ) else() set( REL_LINKER_FLAGS "" ) + set( ALL_C_FLAGS "-ffp-contract=off -DHAVE_SOFTPOLY" ) + if ( HAVE_VULKAN ) - set( ALL_C_FLAGS "-ffp-contract=off -DHAVE_VULKAN -DHAVE_SOFTPOLY" ) - else() - set( ALL_C_FLAGS "-ffp-contract=off -DHAVE_SOFTPOLY" ) + set( ALL_C_FLAGS "${ALL_C_FLAGS} -DHAVE_VULKAN" ) + endif() + + if ( HAVE_GLES2 ) + set( ALL_C_FLAGS "${ALL_C_FLAGS} -DHAVE_GLES2" ) endif() if ( UNIX ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1268b85738..178a5934e4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -607,6 +607,7 @@ file( GLOB HEADER_FILES common/thirdparty/math/*h common/rendering/*.h common/rendering/gl_load/*.h + common/rendering/gles/*.h common/rendering/hwrenderer/data/*.h common/rendering/polyrenderer/*.h common/rendering/polyrenderer/math/*.h @@ -784,6 +785,26 @@ set (VULKAN_SOURCES common/rendering/vulkan/thirdparty/vk_mem_alloc/vk_mem_alloc.cpp ) +if (HAVE_GLES2) + set (GLES_SOURCES + common/rendering/gles/gles_system.cpp + common/rendering/gles/gles_renderer.cpp + common/rendering/gles/gles_framebuffer.cpp + common/rendering/gles/gles_renderstate.cpp + common/rendering/gles/gles_renderbuffers.cpp + common/rendering/gles/gles_postprocess.cpp + common/rendering/gles/gles_postprocessstate.cpp + common/rendering/gles/gles_buffers.cpp + common/rendering/gles/gles_hwtexture.cpp + common/rendering/gles/gles_shader.cpp + common/rendering/gles/gles_shaderprogram.cpp + common/rendering/gles/gles_samplers.cpp + common/rendering/gles/glad/src/glad.c + ) + + set (FASTMATH_SOURCES ${FASTMATH_SOURCES} ${GLES_SOURCES}) +endif() + if (HAVE_VULKAN) set (FASTMATH_SOURCES ${FASTMATH_SOURCES} ${VULKAN_SOURCES}) endif() @@ -1256,6 +1277,9 @@ include_directories( . common/rendering/hwrenderer/data common/rendering/gl_load common/rendering/gl + common/rendering/gles + common/rendering/gles/glad/include + common/rendering/gles/Mali_OpenGL_ES_Emulator/include common/rendering/vulkan/thirdparty common/rendering/polyrenderer/backend common/rendering/polyrenderer/drawers @@ -1459,6 +1483,7 @@ source_group("Common\\Rendering\\Hardware Renderer\\Data" REGULAR_EXPRESSION "^$ source_group("Common\\Rendering\\Hardware Renderer\\Postprocessing" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/hwrenderer/postprocessing/.+") source_group("Common\\Rendering\\OpenGL Loader" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/gl_load/.+") source_group("Common\\Rendering\\OpenGL Backend" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/gl/.+") +source_group("Common\\Rendering\\GLES Backend" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/gles/.+") source_group("Common\\Rendering\\Vulkan Renderer\\System" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/system/.+") source_group("Common\\Rendering\\Vulkan Renderer\\Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/renderer/.+") source_group("Common\\Rendering\\Vulkan Renderer\\Shaders" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/common/rendering/vulkan/shaders/.+") diff --git a/src/common/platform/posix/cocoa/i_video.mm b/src/common/platform/posix/cocoa/i_video.mm index b9b1be72ed..a306433b86 100644 --- a/src/common/platform/posix/cocoa/i_video.mm +++ b/src/common/platform/posix/cocoa/i_video.mm @@ -52,8 +52,11 @@ #include "v_text.h" #include "version.h" #include "printf.h" - #include "gl_framebuffer.h" +#ifdef HAVE_GLES2 +#include "gles_framebuffer.h" +#endif + #ifdef HAVE_VULKAN #include "vulkan/system/vk_framebuffer.h" #endif @@ -462,7 +465,12 @@ public: if (fb == nullptr) { - fb = new OpenGLRenderer::OpenGLFrameBuffer(0, vid_fullscreen); +#ifdef HAVE_GLES2 + if( (Args->CheckParm ("-gles2_renderer")) || (vid_preferbackend == 3) ) + fb = new OpenGLESRenderer::OpenGLFrameBuffer(0, vid_fullscreen); + else +#endif + fb = new OpenGLRenderer::OpenGLFrameBuffer(0, vid_fullscreen); } fb->SetWindow(ms_window); diff --git a/src/common/platform/posix/sdl/sdlglvideo.cpp b/src/common/platform/posix/sdl/sdlglvideo.cpp index 4f7dc6e88f..57c46e9082 100644 --- a/src/common/platform/posix/sdl/sdlglvideo.cpp +++ b/src/common/platform/posix/sdl/sdlglvideo.cpp @@ -50,7 +50,10 @@ #include "gl_renderer.h" #include "gl_framebuffer.h" - +#ifdef HAVE_GLES2 +#include "gles_framebuffer.h" +#endif + #ifdef HAVE_VULKAN #include "vulkan/system/vk_framebuffer.h" #endif @@ -468,7 +471,12 @@ DFrameBuffer *SDLVideo::CreateFrameBuffer () #endif if (fb == nullptr) { - fb = new OpenGLRenderer::OpenGLFrameBuffer(0, vid_fullscreen); +#ifdef HAVE_GLES2 + if( (Args->CheckParm ("-gles2_renderer")) || (vid_preferbackend == 3) ) + fb = new OpenGLESRenderer::OpenGLFrameBuffer(0, vid_fullscreen); + else +#endif + fb = new OpenGLRenderer::OpenGLFrameBuffer(0, vid_fullscreen); } return fb; diff --git a/src/common/platform/win32/gl_sysfb.cpp b/src/common/platform/win32/gl_sysfb.cpp index e373c3d3b0..17822d2130 100644 --- a/src/common/platform/win32/gl_sysfb.cpp +++ b/src/common/platform/win32/gl_sysfb.cpp @@ -71,7 +71,7 @@ PFNWGLSWAPINTERVALEXTPROC myWglSwapIntervalExtProc; SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : SystemBaseFrameBuffer(hMonitor, fullscreen) { - if (!static_cast(Video)->InitHardware(Window, 0)) + if (!static_cast(Video)->InitHardware(Window, 0)) { I_FatalError("Unable to initialize OpenGL"); return; diff --git a/src/common/platform/win32/i_system.cpp b/src/common/platform/win32/i_system.cpp index 72930a560c..103b26f317 100644 --- a/src/common/platform/win32/i_system.cpp +++ b/src/common/platform/win32/i_system.cpp @@ -510,7 +510,6 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa char szString[256]; // Check the current video settings. - //SendDlgItemMessage( hDlg, vid_renderer ? IDC_WELCOME_OPENGL : IDC_WELCOME_SOFTWARE, BM_SETCHECK, BST_CHECKED, 0 ); SendDlgItemMessage( hDlg, IDC_WELCOME_FULLSCREEN, BM_SETCHECK, vid_fullscreen ? BST_CHECKED : BST_UNCHECKED, 0 ); switch (vid_preferbackend) { @@ -520,6 +519,11 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa case 2: SendDlgItemMessage( hDlg, IDC_WELCOME_VULKAN3, BM_SETCHECK, BST_CHECKED, 0 ); break; +#ifdef HAVE_GLES2 + case 3: + SendDlgItemMessage( hDlg, IDC_WELCOME_VULKAN4, BM_SETCHECK, BST_CHECKED, 0 ); + break; +#endif default: SendDlgItemMessage( hDlg, IDC_WELCOME_VULKAN1, BM_SETCHECK, BST_CHECKED, 0 ); break; @@ -574,6 +578,11 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa SetQueryIWad(hDlg); // [SP] Upstreamed from Zandronum vid_fullscreen = SendDlgItemMessage( hDlg, IDC_WELCOME_FULLSCREEN, BM_GETCHECK, 0, 0 ) == BST_CHECKED; +#ifdef HAVE_GLES2 + if (SendDlgItemMessage(hDlg, IDC_WELCOME_VULKAN4, BM_GETCHECK, 0, 0) == BST_CHECKED) + vid_preferbackend = 3; + else +#endif if (SendDlgItemMessage(hDlg, IDC_WELCOME_VULKAN3, BM_GETCHECK, 0, 0) == BST_CHECKED) vid_preferbackend = 2; else if (SendDlgItemMessage(hDlg, IDC_WELCOME_VULKAN2, BM_GETCHECK, 0, 0) == BST_CHECKED) diff --git a/src/common/platform/win32/resource.h b/src/common/platform/win32/resource.h index f07a37083e..d00ee9bd9d 100644 --- a/src/common/platform/win32/resource.h +++ b/src/common/platform/win32/resource.h @@ -97,6 +97,7 @@ #define IDC_RADIO3 1086 #define IDC_WELCOME_VULKAN3 1086 #define IDCE_ROOM 1087 +#define IDC_WELCOME_VULKAN4 1187 #define IDCS_ROOM 1088 #define IDCE_ROOMHF 1089 #define IDCS_ROOMHF 1090 diff --git a/src/common/platform/win32/win32glvideo.cpp b/src/common/platform/win32/win32glvideo.cpp index e41d29b390..abc9768cc6 100644 --- a/src/common/platform/win32/win32glvideo.cpp +++ b/src/common/platform/win32/win32glvideo.cpp @@ -53,6 +53,9 @@ #include "win32glvideo.h" #include "gl_framebuffer.h" +#ifdef HAVE_GLES2 +#include "gles_framebuffer.h" +#endif extern "C" { HGLRC zd_wglCreateContext(HDC Arg1); @@ -62,6 +65,7 @@ PROC zd_wglGetProcAddress(LPCSTR name); } EXTERN_CVAR(Int, vid_adapter) +EXTERN_CVAR(Int, vid_preferbackend) EXTERN_CVAR(Bool, vid_hdr) CUSTOM_CVAR(Bool, gl_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) @@ -105,7 +109,13 @@ DFrameBuffer *Win32GLVideo::CreateFrameBuffer() { SystemGLFrameBuffer *fb; - fb = new OpenGLRenderer::OpenGLFrameBuffer(m_hMonitor, vid_fullscreen); +#ifdef HAVE_GLES2 + if ((Args->CheckParm("-gles2_renderer")) || (vid_preferbackend == 3) ) + fb = new OpenGLESRenderer::OpenGLFrameBuffer(m_hMonitor, vid_fullscreen); + else +#endif + fb = new OpenGLRenderer::OpenGLFrameBuffer(m_hMonitor, vid_fullscreen); + return fb; } diff --git a/src/common/rendering/gl/gl_buffers.cpp b/src/common/rendering/gl/gl_buffers.cpp index 9b49d431ad..47970b4016 100644 --- a/src/common/rendering/gl/gl_buffers.cpp +++ b/src/common/rendering/gl/gl_buffers.cpp @@ -170,6 +170,29 @@ void GLBuffer::Resize(size_t newsize) } } +void GLBuffer::GPUDropSync() +{ + if (mGLSync != NULL) + { + glDeleteSync(mGLSync); + } + + mGLSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); +} + +void GLBuffer::GPUWaitSync() +{ + GLenum status = glClientWaitSync(mGLSync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000 * 1000 * 50); // Wait for a max of 50ms... + + if (status != GL_ALREADY_SIGNALED && status != GL_CONDITION_SATISFIED) + { + //Printf("Error on glClientWaitSync: %d\n", status); + } + + glDeleteSync(mGLSync); + + mGLSync = NULL; +} //=========================================================================== // diff --git a/src/common/rendering/gl/gl_buffers.h b/src/common/rendering/gl/gl_buffers.h index 950556ff9f..0141ece5f4 100644 --- a/src/common/rendering/gl/gl_buffers.h +++ b/src/common/rendering/gl/gl_buffers.h @@ -1,6 +1,7 @@ #pragma once #include "buffers.h" +#include "gl_load.h" #ifdef _MSC_VER // silence bogus warning C4250: 'GLVertexBuffer': inherits 'GLBuffer::GLBuffer::SetData' via dominance @@ -19,6 +20,7 @@ protected: int mAllocationSize = 0; bool mPersistent = false; bool nomap = true; + GLsync mGLSync = 0; GLBuffer(int usetype); ~GLBuffer(); @@ -29,6 +31,9 @@ protected: void Resize(size_t newsize) override; void *Lock(unsigned int size) override; void Unlock() override; + + void GPUDropSync(); + void GPUWaitSync(); public: void Bind(); }; diff --git a/src/common/rendering/gl/gl_framebuffer.cpp b/src/common/rendering/gl/gl_framebuffer.cpp index b116e95774..668965a111 100644 --- a/src/common/rendering/gl/gl_framebuffer.cpp +++ b/src/common/rendering/gl/gl_framebuffer.cpp @@ -65,6 +65,7 @@ EXTERN_CVAR (Bool, vid_vsync) EXTERN_CVAR(Bool, r_drawvoxels) EXTERN_CVAR(Int, gl_tonemap) EXTERN_CVAR(Bool, cl_capfps) +EXTERN_CVAR(Int, gl_pipeline_depth); void gl_LoadExtensions(); void gl_PrintStartupLog(); @@ -133,6 +134,9 @@ void OpenGLFrameBuffer::InitializeState() gl_LoadExtensions(); + mPipelineNbr = clamp(*gl_pipeline_depth, 1, HW_MAX_PIPELINE_BUFFERS); + mPipelineType = gl_pipeline_depth > 0; + // Move some state to the framebuffer object for easier access. hwcaps = gl.flags; glslversion = gl.glslversion; @@ -164,10 +168,10 @@ void OpenGLFrameBuffer::InitializeState() SetViewportRects(nullptr); - mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight()); + mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight(), screen->mPipelineNbr); mSkyData = new FSkyVertexBuffer; - mViewpoints = new HWViewpointBuffer; - mLights = new FLightBuffer(); + mViewpoints = new HWViewpointBuffer(screen->mPipelineNbr); + mLights = new FLightBuffer(screen->mPipelineNbr); GLRenderer = new FGLRenderer(this); GLRenderer->Initialize(GetWidth(), GetHeight()); static_cast(mLights->GetBuffer())->BindBase(); @@ -256,10 +260,25 @@ void OpenGLFrameBuffer::Swap() bool swapbefore = gl_finishbeforeswap && camtexcount == 0; Finish.Reset(); Finish.Clock(); - if (swapbefore) glFinish(); - FPSLimit(); - SwapBuffers(); - if (!swapbefore) glFinish(); + if (gl_pipeline_depth < 1) + { + if (swapbefore) glFinish(); + FPSLimit(); + SwapBuffers(); + if (!swapbefore) glFinish(); + } + else + { + mVertexData->DropSync(); + + FPSLimit(); + SwapBuffers(); + + mVertexData->NextPipelineBuffer(); + mVertexData->WaitSync(); + + RenderState()->SetVertexBuffer(screen->mVertexData); // Needed for Raze because it does not reset it + } Finish.Unclock(); camtexcount = 0; FHardwareTexture::UnbindAll(); diff --git a/src/common/rendering/gl/gl_renderstate.cpp b/src/common/rendering/gl/gl_renderstate.cpp index 64e8cc4d15..b8272e58dd 100644 --- a/src/common/rendering/gl/gl_renderstate.cpp +++ b/src/common/rendering/gl/gl_renderstate.cpp @@ -204,7 +204,7 @@ bool FGLRenderState::ApplyShader() size_t start, size; index = screen->mLights->GetBinding(index, &start, &size); - if (start != mLastMappedLightIndex) + if (start != mLastMappedLightIndex || screen->mPipelineNbr > 1) // If multiple buffers always bind { mLastMappedLightIndex = start; static_cast(screen->mLights->GetBuffer())->BindRange(nullptr, start, size); diff --git a/src/common/rendering/gl/gl_shader.cpp b/src/common/rendering/gl/gl_shader.cpp index 5694b7ef03..2ef56a2889 100644 --- a/src/common/rendering/gl/gl_shader.cpp +++ b/src/common/rendering/gl/gl_shader.cpp @@ -382,7 +382,7 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * vp_comb = "#version 430 core\n#define SHADER_STORAGE_LIGHTS\n"; } - if (gl.flags & RFL_SHADER_STORAGE_BUFFER) + if ((gl.flags & RFL_SHADER_STORAGE_BUFFER) && screen->allowSSBO()) { vp_comb << "#define SUPPORTS_SHADOWMAPS\n"; } diff --git a/src/common/rendering/gles/EGL/egl.h b/src/common/rendering/gles/EGL/egl.h new file mode 100644 index 0000000000..5a27291213 --- /dev/null +++ b/src/common/rendering/gles/EGL/egl.h @@ -0,0 +1,303 @@ +#ifndef __egl_h_ +#define __egl_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2013-2014 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. +*/ +/* +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** http://www.opengl.org/registry/ +** +** Khronos $Revision: 29318 $ on $Date: 2015-01-02 03:16:10 -0800 (Fri, 02 Jan 2015) $ +*/ + +#include + +/* Generated on date 20150102 */ + +/* Generated C header for: + * API: egl + * Versions considered: .* + * Versions emitted: .* + * Default extensions included: None + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef EGL_VERSION_1_0 +#define EGL_VERSION_1_0 1 +typedef unsigned int EGLBoolean; +typedef void *EGLDisplay; +#include +#include +typedef void *EGLConfig; +typedef void *EGLSurface; +typedef void *EGLContext; +typedef void (*__eglMustCastToProperFunctionPointerType)(void); +#define EGL_ALPHA_SIZE 0x3021 +#define EGL_BAD_ACCESS 0x3002 +#define EGL_BAD_ALLOC 0x3003 +#define EGL_BAD_ATTRIBUTE 0x3004 +#define EGL_BAD_CONFIG 0x3005 +#define EGL_BAD_CONTEXT 0x3006 +#define EGL_BAD_CURRENT_SURFACE 0x3007 +#define EGL_BAD_DISPLAY 0x3008 +#define EGL_BAD_MATCH 0x3009 +#define EGL_BAD_NATIVE_PIXMAP 0x300A +#define EGL_BAD_NATIVE_WINDOW 0x300B +#define EGL_BAD_PARAMETER 0x300C +#define EGL_BAD_SURFACE 0x300D +#define EGL_BLUE_SIZE 0x3022 +#define EGL_BUFFER_SIZE 0x3020 +#define EGL_CONFIG_CAVEAT 0x3027 +#define EGL_CONFIG_ID 0x3028 +#define EGL_CORE_NATIVE_ENGINE 0x305B +#define EGL_DEPTH_SIZE 0x3025 +#define EGL_DONT_CARE ((EGLint)-1) +#define EGL_DRAW 0x3059 +#define EGL_EXTENSIONS 0x3055 +#define EGL_FALSE 0 +#define EGL_GREEN_SIZE 0x3023 +#define EGL_HEIGHT 0x3056 +#define EGL_LARGEST_PBUFFER 0x3058 +#define EGL_LEVEL 0x3029 +#define EGL_MAX_PBUFFER_HEIGHT 0x302A +#define EGL_MAX_PBUFFER_PIXELS 0x302B +#define EGL_MAX_PBUFFER_WIDTH 0x302C +#define EGL_NATIVE_RENDERABLE 0x302D +#define EGL_NATIVE_VISUAL_ID 0x302E +#define EGL_NATIVE_VISUAL_TYPE 0x302F +#define EGL_NONE 0x3038 +#define EGL_NON_CONFORMANT_CONFIG 0x3051 +#define EGL_NOT_INITIALIZED 0x3001 +#define EGL_NO_CONTEXT ((EGLContext)0) +#define EGL_NO_DISPLAY ((EGLDisplay)0) +#define EGL_NO_SURFACE ((EGLSurface)0) +#define EGL_PBUFFER_BIT 0x0001 +#define EGL_PIXMAP_BIT 0x0002 +#define EGL_READ 0x305A +#define EGL_RED_SIZE 0x3024 +#define EGL_SAMPLES 0x3031 +#define EGL_SAMPLE_BUFFERS 0x3032 +#define EGL_SLOW_CONFIG 0x3050 +#define EGL_STENCIL_SIZE 0x3026 +#define EGL_SUCCESS 0x3000 +#define EGL_SURFACE_TYPE 0x3033 +#define EGL_TRANSPARENT_BLUE_VALUE 0x3035 +#define EGL_TRANSPARENT_GREEN_VALUE 0x3036 +#define EGL_TRANSPARENT_RED_VALUE 0x3037 +#define EGL_TRANSPARENT_RGB 0x3052 +#define EGL_TRANSPARENT_TYPE 0x3034 +#define EGL_TRUE 1 +#define EGL_VENDOR 0x3053 +#define EGL_VERSION 0x3054 +#define EGL_WIDTH 0x3057 +#define EGL_WINDOW_BIT 0x0004 +EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); +EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target); +EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface); +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); +EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void); +EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw); +EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id); +EGLAPI EGLint EGLAPIENTRY eglGetError (void); +EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname); +EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor); +EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value); +EGLAPI const char *EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name); +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface); +EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine); +#endif /* EGL_VERSION_1_0 */ + +#ifndef EGL_VERSION_1_1 +#define EGL_VERSION_1_1 1 +#define EGL_BACK_BUFFER 0x3084 +#define EGL_BIND_TO_TEXTURE_RGB 0x3039 +#define EGL_BIND_TO_TEXTURE_RGBA 0x303A +#define EGL_CONTEXT_LOST 0x300E +#define EGL_MIN_SWAP_INTERVAL 0x303B +#define EGL_MAX_SWAP_INTERVAL 0x303C +#define EGL_MIPMAP_TEXTURE 0x3082 +#define EGL_MIPMAP_LEVEL 0x3083 +#define EGL_NO_TEXTURE 0x305C +#define EGL_TEXTURE_2D 0x305F +#define EGL_TEXTURE_FORMAT 0x3080 +#define EGL_TEXTURE_RGB 0x305D +#define EGL_TEXTURE_RGBA 0x305E +#define EGL_TEXTURE_TARGET 0x3081 +EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer); +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer); +EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval (EGLDisplay dpy, EGLint interval); +#endif /* EGL_VERSION_1_1 */ + +#ifndef EGL_VERSION_1_2 +#define EGL_VERSION_1_2 1 +typedef unsigned int EGLenum; +typedef void *EGLClientBuffer; +#define EGL_ALPHA_FORMAT 0x3088 +#define EGL_ALPHA_FORMAT_NONPRE 0x308B +#define EGL_ALPHA_FORMAT_PRE 0x308C +#define EGL_ALPHA_MASK_SIZE 0x303E +#define EGL_BUFFER_PRESERVED 0x3094 +#define EGL_BUFFER_DESTROYED 0x3095 +#define EGL_CLIENT_APIS 0x308D +#define EGL_COLORSPACE 0x3087 +#define EGL_COLORSPACE_sRGB 0x3089 +#define EGL_COLORSPACE_LINEAR 0x308A +#define EGL_COLOR_BUFFER_TYPE 0x303F +#define EGL_CONTEXT_CLIENT_TYPE 0x3097 +#define EGL_DISPLAY_SCALING 10000 +#define EGL_HORIZONTAL_RESOLUTION 0x3090 +#define EGL_LUMINANCE_BUFFER 0x308F +#define EGL_LUMINANCE_SIZE 0x303D +#define EGL_OPENGL_ES_BIT 0x0001 +#define EGL_OPENVG_BIT 0x0002 +#define EGL_OPENGL_ES_API 0x30A0 +#define EGL_OPENVG_API 0x30A1 +#define EGL_OPENVG_IMAGE 0x3096 +#define EGL_PIXEL_ASPECT_RATIO 0x3092 +#define EGL_RENDERABLE_TYPE 0x3040 +#define EGL_RENDER_BUFFER 0x3086 +#define EGL_RGB_BUFFER 0x308E +#define EGL_SINGLE_BUFFER 0x3085 +#define EGL_SWAP_BEHAVIOR 0x3093 +#define EGL_UNKNOWN ((EGLint)-1) +#define EGL_VERTICAL_RESOLUTION 0x3091 +EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api); +EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread (void); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void); +#endif /* EGL_VERSION_1_2 */ + +#ifndef EGL_VERSION_1_3 +#define EGL_VERSION_1_3 1 +#define EGL_CONFORMANT 0x3042 +#define EGL_CONTEXT_CLIENT_VERSION 0x3098 +#define EGL_MATCH_NATIVE_PIXMAP 0x3041 +#define EGL_OPENGL_ES2_BIT 0x0004 +#define EGL_VG_ALPHA_FORMAT 0x3088 +#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B +#define EGL_VG_ALPHA_FORMAT_PRE 0x308C +#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040 +#define EGL_VG_COLORSPACE 0x3087 +#define EGL_VG_COLORSPACE_sRGB 0x3089 +#define EGL_VG_COLORSPACE_LINEAR 0x308A +#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020 +#endif /* EGL_VERSION_1_3 */ + +#ifndef EGL_VERSION_1_4 +#define EGL_VERSION_1_4 1 +#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) +#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 +#define EGL_MULTISAMPLE_RESOLVE 0x3099 +#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A +#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B +#define EGL_OPENGL_API 0x30A2 +#define EGL_OPENGL_BIT 0x0008 +#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 +EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void); +#endif /* EGL_VERSION_1_4 */ + +#ifndef EGL_VERSION_1_5 +#define EGL_VERSION_1_5 1 +typedef void *EGLSync; +typedef intptr_t EGLAttrib; +typedef khronos_utime_nanoseconds_t EGLTime; +typedef void *EGLImage; +#define EGL_CONTEXT_MAJOR_VERSION 0x3098 +#define EGL_CONTEXT_MINOR_VERSION 0x30FB +#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD +#define EGL_NO_RESET_NOTIFICATION 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001 +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0 +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2 +#define EGL_OPENGL_ES3_BIT 0x00000040 +#define EGL_CL_EVENT_HANDLE 0x309C +#define EGL_SYNC_CL_EVENT 0x30FE +#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0 +#define EGL_SYNC_TYPE 0x30F7 +#define EGL_SYNC_STATUS 0x30F1 +#define EGL_SYNC_CONDITION 0x30F8 +#define EGL_SIGNALED 0x30F2 +#define EGL_UNSIGNALED 0x30F3 +#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001 +#define EGL_FOREVER 0xFFFFFFFFFFFFFFFFull +#define EGL_TIMEOUT_EXPIRED 0x30F5 +#define EGL_CONDITION_SATISFIED 0x30F6 +#define EGL_NO_SYNC ((EGLSync)0) +#define EGL_SYNC_FENCE 0x30F9 +#define EGL_GL_COLORSPACE 0x309D +#define EGL_GL_COLORSPACE_SRGB 0x3089 +#define EGL_GL_COLORSPACE_LINEAR 0x308A +#define EGL_GL_RENDERBUFFER 0x30B9 +#define EGL_GL_TEXTURE_2D 0x30B1 +#define EGL_GL_TEXTURE_LEVEL 0x30BC +#define EGL_GL_TEXTURE_3D 0x30B2 +#define EGL_GL_TEXTURE_ZOFFSET 0x30BD +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8 +#define EGL_IMAGE_PRESERVED 0x30D2 +#define EGL_NO_IMAGE ((EGLImage)0) +EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync); +EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value); +EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image); +EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags); +#endif /* EGL_VERSION_1_5 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/common/rendering/gles/EGL/eglext.h b/src/common/rendering/gles/EGL/eglext.h new file mode 100644 index 0000000000..c8c93773b1 --- /dev/null +++ b/src/common/rendering/gles/EGL/eglext.h @@ -0,0 +1,826 @@ +#ifndef __eglext_h_ +#define __eglext_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2013-2014 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. +*/ +/* +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** http://www.opengl.org/registry/ +** +** Khronos $Revision: 29318 $ on $Date: 2015-01-02 03:16:10 -0800 (Fri, 02 Jan 2015) $ +*/ + +#include + +#define EGL_EGLEXT_VERSION 20150102 + +/* Generated C header for: + * API: egl + * Versions considered: .* + * Versions emitted: _nomatch_^ + * Default extensions included: egl + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef EGL_KHR_cl_event +#define EGL_KHR_cl_event 1 +#define EGL_CL_EVENT_HANDLE_KHR 0x309C +#define EGL_SYNC_CL_EVENT_KHR 0x30FE +#define EGL_SYNC_CL_EVENT_COMPLETE_KHR 0x30FF +#endif /* EGL_KHR_cl_event */ + +#ifndef EGL_KHR_cl_event2 +#define EGL_KHR_cl_event2 1 +typedef void *EGLSyncKHR; +typedef intptr_t EGLAttribKHR; +typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); +#endif +#endif /* EGL_KHR_cl_event2 */ + +#ifndef EGL_KHR_client_get_all_proc_addresses +#define EGL_KHR_client_get_all_proc_addresses 1 +#endif /* EGL_KHR_client_get_all_proc_addresses */ + +#ifndef EGL_KHR_config_attribs +#define EGL_KHR_config_attribs 1 +#define EGL_CONFORMANT_KHR 0x3042 +#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020 +#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040 +#endif /* EGL_KHR_config_attribs */ + +#ifndef EGL_KHR_create_context +#define EGL_KHR_create_context 1 +#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 +#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB +#define EGL_CONTEXT_FLAGS_KHR 0x30FC +#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD +#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF +#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004 +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 +#define EGL_OPENGL_ES3_BIT_KHR 0x00000040 +#endif /* EGL_KHR_create_context */ + +#ifndef EGL_KHR_fence_sync +#define EGL_KHR_fence_sync 1 +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0 +#define EGL_SYNC_CONDITION_KHR 0x30F8 +#define EGL_SYNC_FENCE_KHR 0x30F9 +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_fence_sync */ + +#ifndef EGL_KHR_get_all_proc_addresses +#define EGL_KHR_get_all_proc_addresses 1 +#endif /* EGL_KHR_get_all_proc_addresses */ + +#ifndef EGL_KHR_gl_colorspace +#define EGL_KHR_gl_colorspace 1 +#define EGL_GL_COLORSPACE_KHR 0x309D +#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089 +#define EGL_GL_COLORSPACE_LINEAR_KHR 0x308A +#endif /* EGL_KHR_gl_colorspace */ + +#ifndef EGL_KHR_gl_renderbuffer_image +#define EGL_KHR_gl_renderbuffer_image 1 +#define EGL_GL_RENDERBUFFER_KHR 0x30B9 +#endif /* EGL_KHR_gl_renderbuffer_image */ + +#ifndef EGL_KHR_gl_texture_2D_image +#define EGL_KHR_gl_texture_2D_image 1 +#define EGL_GL_TEXTURE_2D_KHR 0x30B1 +#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC +#endif /* EGL_KHR_gl_texture_2D_image */ + +#ifndef EGL_KHR_gl_texture_3D_image +#define EGL_KHR_gl_texture_3D_image 1 +#define EGL_GL_TEXTURE_3D_KHR 0x30B2 +#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD +#endif /* EGL_KHR_gl_texture_3D_image */ + +#ifndef EGL_KHR_gl_texture_cubemap_image +#define EGL_KHR_gl_texture_cubemap_image 1 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8 +#endif /* EGL_KHR_gl_texture_cubemap_image */ + +#ifndef EGL_KHR_image +#define EGL_KHR_image 1 +typedef void *EGLImageKHR; +#define EGL_NATIVE_PIXMAP_KHR 0x30B0 +#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0) +typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image); +#endif +#endif /* EGL_KHR_image */ + +#ifndef EGL_KHR_image_base +#define EGL_KHR_image_base 1 +#define EGL_IMAGE_PRESERVED_KHR 0x30D2 +#endif /* EGL_KHR_image_base */ + +#ifndef EGL_KHR_image_pixmap +#define EGL_KHR_image_pixmap 1 +#endif /* EGL_KHR_image_pixmap */ + +#ifndef EGL_KHR_lock_surface +#define EGL_KHR_lock_surface 1 +#define EGL_READ_SURFACE_BIT_KHR 0x0001 +#define EGL_WRITE_SURFACE_BIT_KHR 0x0002 +#define EGL_LOCK_SURFACE_BIT_KHR 0x0080 +#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100 +#define EGL_MATCH_FORMAT_KHR 0x3043 +#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0 +#define EGL_FORMAT_RGB_565_KHR 0x30C1 +#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2 +#define EGL_FORMAT_RGBA_8888_KHR 0x30C3 +#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4 +#define EGL_LOCK_USAGE_HINT_KHR 0x30C5 +#define EGL_BITMAP_POINTER_KHR 0x30C6 +#define EGL_BITMAP_PITCH_KHR 0x30C7 +#define EGL_BITMAP_ORIGIN_KHR 0x30C8 +#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9 +#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA +#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB +#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC +#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD +#define EGL_LOWER_LEFT_KHR 0x30CE +#define EGL_UPPER_LEFT_KHR 0x30CF +typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface); +#endif +#endif /* EGL_KHR_lock_surface */ + +#ifndef EGL_KHR_lock_surface2 +#define EGL_KHR_lock_surface2 1 +#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110 +#endif /* EGL_KHR_lock_surface2 */ + +#ifndef EGL_KHR_lock_surface3 +#define EGL_KHR_lock_surface3 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value); +#endif +#endif /* EGL_KHR_lock_surface3 */ + +#ifndef EGL_KHR_partial_update +#define EGL_KHR_partial_update 1 +#define EGL_BUFFER_AGE_KHR 0x313D +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSETDAMAGEREGIONKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSetDamageRegionKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#endif +#endif /* EGL_KHR_partial_update */ + +#ifndef EGL_KHR_platform_android +#define EGL_KHR_platform_android 1 +#define EGL_PLATFORM_ANDROID_KHR 0x3141 +#endif /* EGL_KHR_platform_android */ + +#ifndef EGL_KHR_platform_gbm +#define EGL_KHR_platform_gbm 1 +#define EGL_PLATFORM_GBM_KHR 0x31D7 +#endif /* EGL_KHR_platform_gbm */ + +#ifndef EGL_KHR_platform_wayland +#define EGL_KHR_platform_wayland 1 +#define EGL_PLATFORM_WAYLAND_KHR 0x31D8 +#endif /* EGL_KHR_platform_wayland */ + +#ifndef EGL_KHR_platform_x11 +#define EGL_KHR_platform_x11 1 +#define EGL_PLATFORM_X11_KHR 0x31D5 +#define EGL_PLATFORM_X11_SCREEN_KHR 0x31D6 +#endif /* EGL_KHR_platform_x11 */ + +#ifndef EGL_KHR_reusable_sync +#define EGL_KHR_reusable_sync 1 +typedef khronos_utime_nanoseconds_t EGLTimeKHR; +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_SYNC_STATUS_KHR 0x30F1 +#define EGL_SIGNALED_KHR 0x30F2 +#define EGL_UNSIGNALED_KHR 0x30F3 +#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5 +#define EGL_CONDITION_SATISFIED_KHR 0x30F6 +#define EGL_SYNC_TYPE_KHR 0x30F7 +#define EGL_SYNC_REUSABLE_KHR 0x30FA +#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001 +#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull +#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0) +typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync); +typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync); +EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); +EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode); +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value); +#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_reusable_sync */ + +#ifndef EGL_KHR_stream +#define EGL_KHR_stream 1 +typedef void *EGLStreamKHR; +typedef khronos_uint64_t EGLuint64KHR; +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0) +#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210 +#define EGL_PRODUCER_FRAME_KHR 0x3212 +#define EGL_CONSUMER_FRAME_KHR 0x3213 +#define EGL_STREAM_STATE_KHR 0x3214 +#define EGL_STREAM_STATE_CREATED_KHR 0x3215 +#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216 +#define EGL_STREAM_STATE_EMPTY_KHR 0x3217 +#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218 +#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219 +#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A +#define EGL_BAD_STREAM_KHR 0x321B +#define EGL_BAD_STATE_KHR 0x321C +typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value); +#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_stream */ + +#ifndef EGL_KHR_stream_consumer_gltexture +#define EGL_KHR_stream_consumer_gltexture 1 +#ifdef EGL_KHR_stream +#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_consumer_gltexture */ + +#ifndef EGL_KHR_stream_cross_process_fd +#define EGL_KHR_stream_cross_process_fd 1 +typedef int EGLNativeFileDescriptorKHR; +#ifdef EGL_KHR_stream +#define EGL_NO_FILE_DESCRIPTOR_KHR ((EGLNativeFileDescriptorKHR)(-1)) +typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_cross_process_fd */ + +#ifndef EGL_KHR_stream_fifo +#define EGL_KHR_stream_fifo 1 +#ifdef EGL_KHR_stream +#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC +#define EGL_STREAM_TIME_NOW_KHR 0x31FD +#define EGL_STREAM_TIME_CONSUMER_KHR 0x31FE +#define EGL_STREAM_TIME_PRODUCER_KHR 0x31FF +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_fifo */ + +#ifndef EGL_KHR_stream_producer_aldatalocator +#define EGL_KHR_stream_producer_aldatalocator 1 +#ifdef EGL_KHR_stream +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_producer_aldatalocator */ + +#ifndef EGL_KHR_stream_producer_eglsurface +#define EGL_KHR_stream_producer_eglsurface 1 +#ifdef EGL_KHR_stream +#define EGL_STREAM_BIT_KHR 0x0800 +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_producer_eglsurface */ + +#ifndef EGL_KHR_surfaceless_context +#define EGL_KHR_surfaceless_context 1 +#endif /* EGL_KHR_surfaceless_context */ + +#ifndef EGL_KHR_swap_buffers_with_damage +#define EGL_KHR_swap_buffers_with_damage 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEKHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#endif +#endif /* EGL_KHR_swap_buffers_with_damage */ + +#ifndef EGL_KHR_vg_parent_image +#define EGL_KHR_vg_parent_image 1 +#define EGL_VG_PARENT_IMAGE_KHR 0x30BA +#endif /* EGL_KHR_vg_parent_image */ + +#ifndef EGL_KHR_wait_sync +#define EGL_KHR_wait_sync 1 +typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); +#endif +#endif /* EGL_KHR_wait_sync */ + +#ifndef EGL_ANDROID_blob_cache +#define EGL_ANDROID_blob_cache 1 +typedef khronos_ssize_t EGLsizeiANDROID; +typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize); +typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize); +typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); +#endif +#endif /* EGL_ANDROID_blob_cache */ + +#ifndef EGL_ANDROID_framebuffer_target +#define EGL_ANDROID_framebuffer_target 1 +#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147 +#endif /* EGL_ANDROID_framebuffer_target */ + +#ifndef EGL_ANDROID_image_native_buffer +#define EGL_ANDROID_image_native_buffer 1 +#define EGL_NATIVE_BUFFER_ANDROID 0x3140 +#endif /* EGL_ANDROID_image_native_buffer */ + +#ifndef EGL_ANDROID_native_fence_sync +#define EGL_ANDROID_native_fence_sync 1 +#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144 +#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145 +#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146 +#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1 +typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync); +#endif +#endif /* EGL_ANDROID_native_fence_sync */ + +#ifndef EGL_ANDROID_recordable +#define EGL_ANDROID_recordable 1 +#define EGL_RECORDABLE_ANDROID 0x3142 +#endif /* EGL_ANDROID_recordable */ + +#ifndef EGL_ANGLE_d3d_share_handle_client_buffer +#define EGL_ANGLE_d3d_share_handle_client_buffer 1 +#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200 +#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */ + +#ifndef EGL_ANGLE_query_surface_pointer +#define EGL_ANGLE_query_surface_pointer 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); +#endif +#endif /* EGL_ANGLE_query_surface_pointer */ + +#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle +#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1 +#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */ + +#ifndef EGL_ANGLE_window_fixed_size +#define EGL_ANGLE_window_fixed_size 1 +#define EGL_FIXED_SIZE_ANGLE 0x3201 +#endif /* EGL_ANGLE_window_fixed_size */ + +#ifndef EGL_ARM_pixmap_multisample_discard +#define EGL_ARM_pixmap_multisample_discard 1 +#define EGL_DISCARD_SAMPLES_ARM 0x3286 +#endif /* EGL_ARM_pixmap_multisample_discard */ + +#ifndef EGL_EXT_buffer_age +#define EGL_EXT_buffer_age 1 +#define EGL_BUFFER_AGE_EXT 0x313D +#endif /* EGL_EXT_buffer_age */ + +#ifndef EGL_EXT_client_extensions +#define EGL_EXT_client_extensions 1 +#endif /* EGL_EXT_client_extensions */ + +#ifndef EGL_EXT_create_context_robustness +#define EGL_EXT_create_context_robustness 1 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138 +#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF +#endif /* EGL_EXT_create_context_robustness */ + +#ifndef EGL_EXT_device_base +#define EGL_EXT_device_base 1 +typedef void *EGLDeviceEXT; +#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT)(0)) +#define EGL_BAD_DEVICE_EXT 0x322B +#define EGL_DEVICE_EXT 0x322C +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value); +typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value); +EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value); +#endif +#endif /* EGL_EXT_device_base */ + +#ifndef EGL_EXT_device_drm +#define EGL_EXT_device_drm 1 +#define EGL_DRM_DEVICE_FILE_EXT 0x3233 +#endif /* EGL_EXT_device_drm */ + +#ifndef EGL_EXT_device_openwf +#define EGL_EXT_device_openwf 1 +#define EGL_OPENWF_DEVICE_ID_EXT 0x3237 +#endif /* EGL_EXT_device_openwf */ + +#ifndef EGL_EXT_image_dma_buf_import +#define EGL_EXT_image_dma_buf_import 1 +#define EGL_LINUX_DMA_BUF_EXT 0x3270 +#define EGL_LINUX_DRM_FOURCC_EXT 0x3271 +#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272 +#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273 +#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274 +#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275 +#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276 +#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277 +#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278 +#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279 +#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A +#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B +#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C +#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D +#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E +#define EGL_ITU_REC601_EXT 0x327F +#define EGL_ITU_REC709_EXT 0x3280 +#define EGL_ITU_REC2020_EXT 0x3281 +#define EGL_YUV_FULL_RANGE_EXT 0x3282 +#define EGL_YUV_NARROW_RANGE_EXT 0x3283 +#define EGL_YUV_CHROMA_SITING_0_EXT 0x3284 +#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285 +#endif /* EGL_EXT_image_dma_buf_import */ + +#ifndef EGL_EXT_multiview_window +#define EGL_EXT_multiview_window 1 +#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134 +#endif /* EGL_EXT_multiview_window */ + +#ifndef EGL_EXT_output_base +#define EGL_EXT_output_base 1 +typedef void *EGLOutputLayerEXT; +typedef void *EGLOutputPortEXT; +#define EGL_NO_OUTPUT_LAYER_EXT ((EGLOutputLayerEXT)0) +#define EGL_NO_OUTPUT_PORT_EXT ((EGLOutputPortEXT)0) +#define EGL_BAD_OUTPUT_LAYER_EXT 0x322D +#define EGL_BAD_OUTPUT_PORT_EXT 0x322E +#define EGL_SWAP_INTERVAL_EXT 0x322F +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTLAYERSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETOUTPUTPORTSEXTPROC) (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value); +typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTLAYERSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTATTRIBEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value); +typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputLayersEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputLayerEXT *layers, EGLint max_layers, EGLint *num_layers); +EGLAPI EGLBoolean EGLAPIENTRY eglGetOutputPortsEXT (EGLDisplay dpy, const EGLAttrib *attrib_list, EGLOutputPortEXT *ports, EGLint max_ports, EGLint *num_ports); +EGLAPI EGLBoolean EGLAPIENTRY eglOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputLayerAttribEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint attribute, EGLAttrib *value); +EGLAPI const char *EGLAPIENTRY eglQueryOutputLayerStringEXT (EGLDisplay dpy, EGLOutputLayerEXT layer, EGLint name); +EGLAPI EGLBoolean EGLAPIENTRY eglOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryOutputPortAttribEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint attribute, EGLAttrib *value); +EGLAPI const char *EGLAPIENTRY eglQueryOutputPortStringEXT (EGLDisplay dpy, EGLOutputPortEXT port, EGLint name); +#endif +#endif /* EGL_EXT_output_base */ + +#ifndef EGL_EXT_output_drm +#define EGL_EXT_output_drm 1 +#define EGL_DRM_CRTC_EXT 0x3234 +#define EGL_DRM_PLANE_EXT 0x3235 +#define EGL_DRM_CONNECTOR_EXT 0x3236 +#endif /* EGL_EXT_output_drm */ + +#ifndef EGL_EXT_output_openwf +#define EGL_EXT_output_openwf 1 +#define EGL_OPENWF_PIPELINE_ID_EXT 0x3238 +#define EGL_OPENWF_PORT_ID_EXT 0x3239 +#endif /* EGL_EXT_output_openwf */ + +#ifndef EGL_EXT_platform_base +#define EGL_EXT_platform_base 1 +typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list); +#endif +#endif /* EGL_EXT_platform_base */ + +#ifndef EGL_EXT_platform_device +#define EGL_EXT_platform_device 1 +#define EGL_PLATFORM_DEVICE_EXT 0x313F +#endif /* EGL_EXT_platform_device */ + +#ifndef EGL_EXT_platform_wayland +#define EGL_EXT_platform_wayland 1 +#define EGL_PLATFORM_WAYLAND_EXT 0x31D8 +#endif /* EGL_EXT_platform_wayland */ + +#ifndef EGL_EXT_platform_x11 +#define EGL_EXT_platform_x11 1 +#define EGL_PLATFORM_X11_EXT 0x31D5 +#define EGL_PLATFORM_X11_SCREEN_EXT 0x31D6 +#endif /* EGL_EXT_platform_x11 */ + +#ifndef EGL_EXT_protected_surface +#define EGL_EXT_protected_surface 1 +#define EGL_PROTECTED_CONTENT_EXT 0x32C0 +#endif /* EGL_EXT_protected_surface */ + +#ifndef EGL_EXT_stream_consumer_egloutput +#define EGL_EXT_stream_consumer_egloutput 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMEROUTPUTEXTPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerOutputEXT (EGLDisplay dpy, EGLStreamKHR stream, EGLOutputLayerEXT layer); +#endif +#endif /* EGL_EXT_stream_consumer_egloutput */ + +#ifndef EGL_EXT_swap_buffers_with_damage +#define EGL_EXT_swap_buffers_with_damage 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#endif +#endif /* EGL_EXT_swap_buffers_with_damage */ + +#ifndef EGL_HI_clientpixmap +#define EGL_HI_clientpixmap 1 +struct EGLClientPixmapHI { + void *pData; + EGLint iWidth; + EGLint iHeight; + EGLint iStride; +}; +#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74 +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap); +#endif +#endif /* EGL_HI_clientpixmap */ + +#ifndef EGL_HI_colorformats +#define EGL_HI_colorformats 1 +#define EGL_COLOR_FORMAT_HI 0x8F70 +#define EGL_COLOR_RGB_HI 0x8F71 +#define EGL_COLOR_RGBA_HI 0x8F72 +#define EGL_COLOR_ARGB_HI 0x8F73 +#endif /* EGL_HI_colorformats */ + +#ifndef EGL_IMG_context_priority +#define EGL_IMG_context_priority 1 +#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100 +#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 +#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 +#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103 +#endif /* EGL_IMG_context_priority */ + +#ifndef EGL_MESA_drm_image +#define EGL_MESA_drm_image 1 +#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0 +#define EGL_DRM_BUFFER_USE_MESA 0x31D1 +#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2 +#define EGL_DRM_BUFFER_MESA 0x31D3 +#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4 +#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001 +#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002 +typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); +#endif +#endif /* EGL_MESA_drm_image */ + +#ifndef EGL_MESA_platform_gbm +#define EGL_MESA_platform_gbm 1 +#define EGL_PLATFORM_GBM_MESA 0x31D7 +#endif /* EGL_MESA_platform_gbm */ + +#ifndef EGL_NOK_swap_region +#define EGL_NOK_swap_region 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); +#endif +#endif /* EGL_NOK_swap_region */ + +#ifndef EGL_NOK_swap_region2 +#define EGL_NOK_swap_region2 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGION2NOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); +#endif +#endif /* EGL_NOK_swap_region2 */ + +#ifndef EGL_NOK_texture_from_pixmap +#define EGL_NOK_texture_from_pixmap 1 +#define EGL_Y_INVERTED_NOK 0x307F +#endif /* EGL_NOK_texture_from_pixmap */ + +#ifndef EGL_NV_3dvision_surface +#define EGL_NV_3dvision_surface 1 +#define EGL_AUTO_STEREO_NV 0x3136 +#endif /* EGL_NV_3dvision_surface */ + +#ifndef EGL_NV_coverage_sample +#define EGL_NV_coverage_sample 1 +#define EGL_COVERAGE_BUFFERS_NV 0x30E0 +#define EGL_COVERAGE_SAMPLES_NV 0x30E1 +#endif /* EGL_NV_coverage_sample */ + +#ifndef EGL_NV_coverage_sample_resolve +#define EGL_NV_coverage_sample_resolve 1 +#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131 +#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132 +#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133 +#endif /* EGL_NV_coverage_sample_resolve */ + +#ifndef EGL_NV_cuda_event +#define EGL_NV_cuda_event 1 +#define EGL_CUDA_EVENT_HANDLE_NV 0x323B +#define EGL_SYNC_CUDA_EVENT_NV 0x323C +#define EGL_SYNC_CUDA_EVENT_COMPLETE_NV 0x323D +#endif /* EGL_NV_cuda_event */ + +#ifndef EGL_NV_depth_nonlinear +#define EGL_NV_depth_nonlinear 1 +#define EGL_DEPTH_ENCODING_NV 0x30E2 +#define EGL_DEPTH_ENCODING_NONE_NV 0 +#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3 +#endif /* EGL_NV_depth_nonlinear */ + +#ifndef EGL_NV_device_cuda +#define EGL_NV_device_cuda 1 +#define EGL_CUDA_DEVICE_NV 0x323A +#endif /* EGL_NV_device_cuda */ + +#ifndef EGL_NV_native_query +#define EGL_NV_native_query 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap); +#endif +#endif /* EGL_NV_native_query */ + +#ifndef EGL_NV_post_convert_rounding +#define EGL_NV_post_convert_rounding 1 +#endif /* EGL_NV_post_convert_rounding */ + +#ifndef EGL_NV_post_sub_buffer +#define EGL_NV_post_sub_buffer 1 +#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE +typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); +#endif +#endif /* EGL_NV_post_sub_buffer */ + +#ifndef EGL_NV_stream_sync +#define EGL_NV_stream_sync 1 +#define EGL_SYNC_NEW_FRAME_NV 0x321F +typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list); +#endif +#endif /* EGL_NV_stream_sync */ + +#ifndef EGL_NV_sync +#define EGL_NV_sync 1 +typedef void *EGLSyncNV; +typedef khronos_utime_nanoseconds_t EGLTimeNV; +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6 +#define EGL_SYNC_STATUS_NV 0x30E7 +#define EGL_SIGNALED_NV 0x30E8 +#define EGL_UNSIGNALED_NV 0x30E9 +#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001 +#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull +#define EGL_ALREADY_SIGNALED_NV 0x30EA +#define EGL_TIMEOUT_EXPIRED_NV 0x30EB +#define EGL_CONDITION_SATISFIED_NV 0x30EC +#define EGL_SYNC_TYPE_NV 0x30ED +#define EGL_SYNC_CONDITION_NV 0x30EE +#define EGL_SYNC_FENCE_NV 0x30EF +#define EGL_NO_SYNC_NV ((EGLSyncNV)0) +typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync); +typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync); +EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync); +EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); +EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode); +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value); +#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_NV_sync */ + +#ifndef EGL_NV_system_time +#define EGL_NV_system_time 1 +typedef khronos_utime_nanoseconds_t EGLuint64NV; +#ifdef KHRONOS_SUPPORT_INT64 +typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void); +typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void); +EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void); +#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_NV_system_time */ + +#ifndef EGL_TIZEN_image_native_buffer +#define EGL_TIZEN_image_native_buffer 1 +#define EGL_NATIVE_BUFFER_TIZEN 0x32A0 +#endif /* EGL_TIZEN_image_native_buffer */ + +#ifndef EGL_TIZEN_image_native_surface +#define EGL_TIZEN_image_native_surface 1 +#define EGL_NATIVE_SURFACE_TIZEN 0x32A1 +#endif /* EGL_TIZEN_image_native_surface */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/common/rendering/gles/EGL/eglplatform.h b/src/common/rendering/gles/EGL/eglplatform.h new file mode 100644 index 0000000000..d79f322e2d --- /dev/null +++ b/src/common/rendering/gles/EGL/eglplatform.h @@ -0,0 +1,125 @@ +#ifndef __eglplatform_h_ +#define __eglplatform_h_ + +/* +** Copyright (c) 2007-2013 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. +*/ + +/* Platform-specific types and definitions for egl.h + * $Revision: 23432 $ on $Date: 2013-10-09 00:57:24 -0700 (Wed, 09 Oct 2013) $ + * + * Adopters may modify khrplatform.h and this file to suit their platform. + * You are encouraged to submit all modifications to the Khronos group so that + * they can be included in future versions of this file. Please submit changes + * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) + * by filing a bug against product "EGL" component "Registry". + */ + +#include + +/* Macros used in EGL function prototype declarations. + * + * EGL functions should be prototyped as: + * + * EGLAPI return-type EGLAPIENTRY eglFunction(arguments); + * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments); + * + * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h + */ + +#ifndef EGLAPI +#define EGLAPI KHRONOS_APICALL +#endif + +#ifndef EGLAPIENTRY +#define EGLAPIENTRY KHRONOS_APIENTRY +#endif +#define EGLAPIENTRYP EGLAPIENTRY* + +/* The types NativeDisplayType, NativeWindowType, and NativePixmapType + * are aliases of window-system-dependent types, such as X Display * or + * Windows Device Context. They must be defined in platform-specific + * code below. The EGL-prefixed versions of Native*Type are the same + * types, renamed in EGL 1.3 so all types in the API start with "EGL". + * + * Khronos STRONGLY RECOMMENDS that you use the default definitions + * provided below, since these changes affect both binary and source + * portability of applications using EGL running on different EGL + * implementations. + */ + +#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif +#include + +typedef HDC EGLNativeDisplayType; +typedef HBITMAP EGLNativePixmapType; +typedef HWND EGLNativeWindowType; + +#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ + +typedef int EGLNativeDisplayType; +typedef void *EGLNativeWindowType; +typedef void *EGLNativePixmapType; + +#elif defined(__ANDROID__) || defined(ANDROID) + +#include + +struct egl_native_pixmap_t; + +typedef struct ANativeWindow* EGLNativeWindowType; +typedef struct egl_native_pixmap_t* EGLNativePixmapType; +typedef void* EGLNativeDisplayType; + +#elif defined(__unix__) || defined(__APPLE__) + +/* X11 (tentative) */ +#include +#include + +typedef Display *EGLNativeDisplayType; +typedef Pixmap EGLNativePixmapType; +typedef Window EGLNativeWindowType; + +#else +#error "Platform not recognized" +#endif + +/* EGL 1.2 types, renamed for consistency in EGL 1.3 */ +typedef EGLNativeDisplayType NativeDisplayType; +typedef EGLNativePixmapType NativePixmapType; +typedef EGLNativeWindowType NativeWindowType; + + +/* Define EGLint. This must be a signed integral type large enough to contain + * all legal attribute names and values passed into and out of EGL, whether + * their type is boolean, bitmask, enumerant (symbolic constant), integer, + * handle, or other. While in general a 32-bit integer will suffice, if + * handles are 64 bit types, then EGLint should be defined as a signed 64-bit + * integer type. + */ +typedef khronos_int32_t EGLint; + +#endif /* __eglplatform_h */ diff --git a/src/common/rendering/gles/glad/include/EGL/eglplatform.h b/src/common/rendering/gles/glad/include/EGL/eglplatform.h new file mode 100644 index 0000000000..d79f322e2d --- /dev/null +++ b/src/common/rendering/gles/glad/include/EGL/eglplatform.h @@ -0,0 +1,125 @@ +#ifndef __eglplatform_h_ +#define __eglplatform_h_ + +/* +** Copyright (c) 2007-2013 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. +*/ + +/* Platform-specific types and definitions for egl.h + * $Revision: 23432 $ on $Date: 2013-10-09 00:57:24 -0700 (Wed, 09 Oct 2013) $ + * + * Adopters may modify khrplatform.h and this file to suit their platform. + * You are encouraged to submit all modifications to the Khronos group so that + * they can be included in future versions of this file. Please submit changes + * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) + * by filing a bug against product "EGL" component "Registry". + */ + +#include + +/* Macros used in EGL function prototype declarations. + * + * EGL functions should be prototyped as: + * + * EGLAPI return-type EGLAPIENTRY eglFunction(arguments); + * typedef return-type (EXPAPIENTRYP PFNEGLFUNCTIONPROC) (arguments); + * + * KHRONOS_APICALL and KHRONOS_APIENTRY are defined in KHR/khrplatform.h + */ + +#ifndef EGLAPI +#define EGLAPI KHRONOS_APICALL +#endif + +#ifndef EGLAPIENTRY +#define EGLAPIENTRY KHRONOS_APIENTRY +#endif +#define EGLAPIENTRYP EGLAPIENTRY* + +/* The types NativeDisplayType, NativeWindowType, and NativePixmapType + * are aliases of window-system-dependent types, such as X Display * or + * Windows Device Context. They must be defined in platform-specific + * code below. The EGL-prefixed versions of Native*Type are the same + * types, renamed in EGL 1.3 so all types in the API start with "EGL". + * + * Khronos STRONGLY RECOMMENDS that you use the default definitions + * provided below, since these changes affect both binary and source + * portability of applications using EGL running on different EGL + * implementations. + */ + +#if defined(_WIN32) || defined(__VC32__) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) /* Win32 and WinCE */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif +#include + +typedef HDC EGLNativeDisplayType; +typedef HBITMAP EGLNativePixmapType; +typedef HWND EGLNativeWindowType; + +#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */ + +typedef int EGLNativeDisplayType; +typedef void *EGLNativeWindowType; +typedef void *EGLNativePixmapType; + +#elif defined(__ANDROID__) || defined(ANDROID) + +#include + +struct egl_native_pixmap_t; + +typedef struct ANativeWindow* EGLNativeWindowType; +typedef struct egl_native_pixmap_t* EGLNativePixmapType; +typedef void* EGLNativeDisplayType; + +#elif defined(__unix__) || defined(__APPLE__) + +/* X11 (tentative) */ +#include +#include + +typedef Display *EGLNativeDisplayType; +typedef Pixmap EGLNativePixmapType; +typedef Window EGLNativeWindowType; + +#else +#error "Platform not recognized" +#endif + +/* EGL 1.2 types, renamed for consistency in EGL 1.3 */ +typedef EGLNativeDisplayType NativeDisplayType; +typedef EGLNativePixmapType NativePixmapType; +typedef EGLNativeWindowType NativeWindowType; + + +/* Define EGLint. This must be a signed integral type large enough to contain + * all legal attribute names and values passed into and out of EGL, whether + * their type is boolean, bitmask, enumerant (symbolic constant), integer, + * handle, or other. While in general a 32-bit integer will suffice, if + * handles are 64 bit types, then EGLint should be defined as a signed 64-bit + * integer type. + */ +typedef khronos_int32_t EGLint; + +#endif /* __eglplatform_h */ diff --git a/src/common/rendering/gles/glad/include/KHR/khrplatform.h b/src/common/rendering/gles/glad/include/KHR/khrplatform.h new file mode 100644 index 0000000000..dd22d92701 --- /dev/null +++ b/src/common/rendering/gles/glad/include/KHR/khrplatform.h @@ -0,0 +1,290 @@ +#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 + +#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 _WIN64 +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +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/src/common/rendering/gles/glad/include/glad/glad.h b/src/common/rendering/gles/glad/include/glad/glad.h new file mode 100644 index 0000000000..5a7c1505e9 --- /dev/null +++ b/src/common/rendering/gles/glad/include/glad/glad.h @@ -0,0 +1,874 @@ +/* + + OpenGL ES loader generated by glad 0.1.34 on Fri Mar 19 17:04:24 2021. + + Language/Generator: C/C++ + Specification: gl + APIs: gles2=2.0 + Profile: compatibility + Extensions: + + Loader: True + Local files: False + Omit khrplatform: False + Reproducible: False + + Commandline: + --profile="compatibility" --api="gles2=2.0" --generator="c" --spec="gl" --extensions="" + Online: + https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gles2%3D2.0 +*/ + + +#ifndef __glad_h_ +#define __glad_h_ + +#ifdef __gl2_h_ +#error OpenGL ES 2 header already included, remove this include, glad already provides it +#endif +#define __gl2_h_ + +#ifdef __gl3_h_ +#error OpenGL ES 3 header already included, remove this include, glad already provides it +#endif +#define __gl3_h_ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define APIENTRY __stdcall +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif + +#ifndef GLAPIENTRY +#define GLAPIENTRY APIENTRY +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +struct gladGLversionStruct { + int major; + int minor; +}; + +typedef void* (* GLADloadproc)(const char *name); + +#ifndef GLAPI +# if defined(GLAD_GLAPI_EXPORT) +# if defined(_WIN32) || defined(__CYGWIN__) +# if defined(GLAD_GLAPI_EXPORT_BUILD) +# if defined(__GNUC__) +# define GLAPI __attribute__ ((dllexport)) extern +# else +# define GLAPI __declspec(dllexport) extern +# endif +# else +# if defined(__GNUC__) +# define GLAPI __attribute__ ((dllimport)) extern +# else +# define GLAPI __declspec(dllimport) extern +# endif +# endif +# elif defined(__GNUC__) && defined(GLAD_GLAPI_EXPORT_BUILD) +# define GLAPI __attribute__ ((visibility ("default"))) extern +# else +# define GLAPI extern +# endif +# else +# define GLAPI extern +# endif +#endif + +GLAPI struct gladGLversionStruct GLVersion; +GLAPI int gladLoadGLES2Loader(GLADloadproc); + +#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; +typedef khronos_intptr_t GLintptr; +typedef khronos_intptr_t GLintptrARB; +typedef khronos_ssize_t GLsizeiptr; +typedef khronos_ssize_t GLsizeiptrARB; +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 (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam); +typedef unsigned short GLhalfNV; +typedef GLintptr GLvdpauSurfaceNV; +typedef void (APIENTRY *GLVULKANPROCNV)(void); +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_FALSE 0 +#define GL_TRUE 1 +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_FUNC_ADD 0x8006 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_BLEND 0x0BE2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_CW 0x0900 +#define GL_CCW 0x0901 +#define GL_LINE_WIDTH 0x0B21 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#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_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_SHADER_TYPE 0x8B4F +#define GL_DELETE_STATUS 0x8B80 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_INVERT 0x150A +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TEXTURE 0x1702 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#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_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_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_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_COMPILE_STATUS 0x8B81 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGB565 0x8D62 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_NONE 0 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#ifndef GL_ES_VERSION_2_0 +#define GL_ES_VERSION_2_0 1 +GLAPI int GLAD_GL_ES_VERSION_2_0; +typedef void (APIENTRYP PFNGLACTIVETEXTUREPROC)(GLenum texture); +GLAPI PFNGLACTIVETEXTUREPROC glad_glActiveTexture; +#define glActiveTexture glad_glActiveTexture +typedef void (APIENTRYP PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader); +GLAPI PFNGLATTACHSHADERPROC glad_glAttachShader; +#define glAttachShader glad_glAttachShader +typedef void (APIENTRYP PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar *name); +GLAPI PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation; +#define glBindAttribLocation glad_glBindAttribLocation +typedef void (APIENTRYP PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer); +GLAPI PFNGLBINDBUFFERPROC glad_glBindBuffer; +#define glBindBuffer glad_glBindBuffer +typedef void (APIENTRYP PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer); +GLAPI PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer; +#define glBindFramebuffer glad_glBindFramebuffer +typedef void (APIENTRYP PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer); +GLAPI PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer; +#define glBindRenderbuffer glad_glBindRenderbuffer +typedef void (APIENTRYP PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture); +GLAPI PFNGLBINDTEXTUREPROC glad_glBindTexture; +#define glBindTexture glad_glBindTexture +typedef void (APIENTRYP PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI PFNGLBLENDCOLORPROC glad_glBlendColor; +#define glBlendColor glad_glBlendColor +typedef void (APIENTRYP PFNGLBLENDEQUATIONPROC)(GLenum mode); +GLAPI PFNGLBLENDEQUATIONPROC glad_glBlendEquation; +#define glBlendEquation glad_glBlendEquation +typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha); +GLAPI PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate; +#define glBlendEquationSeparate glad_glBlendEquationSeparate +typedef void (APIENTRYP PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor); +GLAPI PFNGLBLENDFUNCPROC glad_glBlendFunc; +#define glBlendFunc glad_glBlendFunc +typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +GLAPI PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate; +#define glBlendFuncSeparate glad_glBlendFuncSeparate +typedef void (APIENTRYP PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void *data, GLenum usage); +GLAPI PFNGLBUFFERDATAPROC glad_glBufferData; +#define glBufferData glad_glBufferData +typedef void (APIENTRYP PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void *data); +GLAPI PFNGLBUFFERSUBDATAPROC glad_glBufferSubData; +#define glBufferSubData glad_glBufferSubData +typedef GLenum (APIENTRYP PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target); +GLAPI PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus; +#define glCheckFramebufferStatus glad_glCheckFramebufferStatus +typedef void (APIENTRYP PFNGLCLEARPROC)(GLbitfield mask); +GLAPI PFNGLCLEARPROC glad_glClear; +#define glClear glad_glClear +typedef void (APIENTRYP PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GLAPI PFNGLCLEARCOLORPROC glad_glClearColor; +#define glClearColor glad_glClearColor +typedef void (APIENTRYP PFNGLCLEARDEPTHFPROC)(GLfloat d); +GLAPI PFNGLCLEARDEPTHFPROC glad_glClearDepthf; +#define glClearDepthf glad_glClearDepthf +typedef void (APIENTRYP PFNGLCLEARSTENCILPROC)(GLint s); +GLAPI PFNGLCLEARSTENCILPROC glad_glClearStencil; +#define glClearStencil glad_glClearStencil +typedef void (APIENTRYP PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GLAPI PFNGLCOLORMASKPROC glad_glColorMask; +#define glColorMask glad_glColorMask +typedef void (APIENTRYP PFNGLCOMPILESHADERPROC)(GLuint shader); +GLAPI PFNGLCOMPILESHADERPROC glad_glCompileShader; +#define glCompileShader glad_glCompileShader +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); +GLAPI PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D; +#define glCompressedTexImage2D glad_glCompressedTexImage2D +typedef void (APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); +GLAPI PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D; +#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D +typedef void (APIENTRYP PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GLAPI PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D; +#define glCopyTexImage2D glad_glCopyTexImage2D +typedef void (APIENTRYP PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D; +#define glCopyTexSubImage2D glad_glCopyTexSubImage2D +typedef GLuint (APIENTRYP PFNGLCREATEPROGRAMPROC)(void); +GLAPI PFNGLCREATEPROGRAMPROC glad_glCreateProgram; +#define glCreateProgram glad_glCreateProgram +typedef GLuint (APIENTRYP PFNGLCREATESHADERPROC)(GLenum type); +GLAPI PFNGLCREATESHADERPROC glad_glCreateShader; +#define glCreateShader glad_glCreateShader +typedef void (APIENTRYP PFNGLCULLFACEPROC)(GLenum mode); +GLAPI PFNGLCULLFACEPROC glad_glCullFace; +#define glCullFace glad_glCullFace +typedef void (APIENTRYP PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint *buffers); +GLAPI PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers; +#define glDeleteBuffers glad_glDeleteBuffers +typedef void (APIENTRYP PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint *framebuffers); +GLAPI PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers; +#define glDeleteFramebuffers glad_glDeleteFramebuffers +typedef void (APIENTRYP PFNGLDELETEPROGRAMPROC)(GLuint program); +GLAPI PFNGLDELETEPROGRAMPROC glad_glDeleteProgram; +#define glDeleteProgram glad_glDeleteProgram +typedef void (APIENTRYP PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint *renderbuffers); +GLAPI PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers; +#define glDeleteRenderbuffers glad_glDeleteRenderbuffers +typedef void (APIENTRYP PFNGLDELETESHADERPROC)(GLuint shader); +GLAPI PFNGLDELETESHADERPROC glad_glDeleteShader; +#define glDeleteShader glad_glDeleteShader +typedef void (APIENTRYP PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint *textures); +GLAPI PFNGLDELETETEXTURESPROC glad_glDeleteTextures; +#define glDeleteTextures glad_glDeleteTextures +typedef void (APIENTRYP PFNGLDEPTHFUNCPROC)(GLenum func); +GLAPI PFNGLDEPTHFUNCPROC glad_glDepthFunc; +#define glDepthFunc glad_glDepthFunc +typedef void (APIENTRYP PFNGLDEPTHMASKPROC)(GLboolean flag); +GLAPI PFNGLDEPTHMASKPROC glad_glDepthMask; +#define glDepthMask glad_glDepthMask +typedef void (APIENTRYP PFNGLDEPTHRANGEFPROC)(GLfloat n, GLfloat f); +GLAPI PFNGLDEPTHRANGEFPROC glad_glDepthRangef; +#define glDepthRangef glad_glDepthRangef +typedef void (APIENTRYP PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader); +GLAPI PFNGLDETACHSHADERPROC glad_glDetachShader; +#define glDetachShader glad_glDetachShader +typedef void (APIENTRYP PFNGLDISABLEPROC)(GLenum cap); +GLAPI PFNGLDISABLEPROC glad_glDisable; +#define glDisable glad_glDisable +typedef void (APIENTRYP PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index); +GLAPI PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray; +#define glDisableVertexAttribArray glad_glDisableVertexAttribArray +typedef void (APIENTRYP PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count); +GLAPI PFNGLDRAWARRAYSPROC glad_glDrawArrays; +#define glDrawArrays glad_glDrawArrays +typedef void (APIENTRYP PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void *indices); +GLAPI PFNGLDRAWELEMENTSPROC glad_glDrawElements; +#define glDrawElements glad_glDrawElements +typedef void (APIENTRYP PFNGLENABLEPROC)(GLenum cap); +GLAPI PFNGLENABLEPROC glad_glEnable; +#define glEnable glad_glEnable +typedef void (APIENTRYP PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index); +GLAPI PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray; +#define glEnableVertexAttribArray glad_glEnableVertexAttribArray +typedef void (APIENTRYP PFNGLFINISHPROC)(void); +GLAPI PFNGLFINISHPROC glad_glFinish; +#define glFinish glad_glFinish +typedef void (APIENTRYP PFNGLFLUSHPROC)(void); +GLAPI PFNGLFLUSHPROC glad_glFlush; +#define glFlush glad_glFlush +typedef void (APIENTRYP PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GLAPI PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer; +#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer +typedef void (APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GLAPI PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D; +#define glFramebufferTexture2D glad_glFramebufferTexture2D +typedef void (APIENTRYP PFNGLFRONTFACEPROC)(GLenum mode); +GLAPI PFNGLFRONTFACEPROC glad_glFrontFace; +#define glFrontFace glad_glFrontFace +typedef void (APIENTRYP PFNGLGENBUFFERSPROC)(GLsizei n, GLuint *buffers); +GLAPI PFNGLGENBUFFERSPROC glad_glGenBuffers; +#define glGenBuffers glad_glGenBuffers +typedef void (APIENTRYP PFNGLGENERATEMIPMAPPROC)(GLenum target); +GLAPI PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap; +#define glGenerateMipmap glad_glGenerateMipmap +typedef void (APIENTRYP PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint *framebuffers); +GLAPI PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers; +#define glGenFramebuffers glad_glGenFramebuffers +typedef void (APIENTRYP PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint *renderbuffers); +GLAPI PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers; +#define glGenRenderbuffers glad_glGenRenderbuffers +typedef void (APIENTRYP PFNGLGENTEXTURESPROC)(GLsizei n, GLuint *textures); +GLAPI PFNGLGENTEXTURESPROC glad_glGenTextures; +#define glGenTextures glad_glGenTextures +typedef void (APIENTRYP PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GLAPI PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib; +#define glGetActiveAttrib glad_glGetActiveAttrib +typedef void (APIENTRYP PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); +GLAPI PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform; +#define glGetActiveUniform glad_glGetActiveUniform +typedef void (APIENTRYP PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); +GLAPI PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders; +#define glGetAttachedShaders glad_glGetAttachedShaders +typedef GLint (APIENTRYP PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar *name); +GLAPI PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation; +#define glGetAttribLocation glad_glGetAttribLocation +typedef void (APIENTRYP PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean *data); +GLAPI PFNGLGETBOOLEANVPROC glad_glGetBooleanv; +#define glGetBooleanv glad_glGetBooleanv +typedef void (APIENTRYP PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params); +GLAPI PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv; +#define glGetBufferParameteriv glad_glGetBufferParameteriv +typedef GLenum (APIENTRYP PFNGLGETERRORPROC)(void); +GLAPI PFNGLGETERRORPROC glad_glGetError; +#define glGetError glad_glGetError +typedef void (APIENTRYP PFNGLGETFLOATVPROC)(GLenum pname, GLfloat *data); +GLAPI PFNGLGETFLOATVPROC glad_glGetFloatv; +#define glGetFloatv glad_glGetFloatv +typedef void (APIENTRYP PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint *params); +GLAPI PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv; +#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv +typedef void (APIENTRYP PFNGLGETINTEGERVPROC)(GLenum pname, GLint *data); +GLAPI PFNGLGETINTEGERVPROC glad_glGetIntegerv; +#define glGetIntegerv glad_glGetIntegerv +typedef void (APIENTRYP PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint *params); +GLAPI PFNGLGETPROGRAMIVPROC glad_glGetProgramiv; +#define glGetProgramiv glad_glGetProgramiv +typedef void (APIENTRYP PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GLAPI PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog; +#define glGetProgramInfoLog glad_glGetProgramInfoLog +typedef void (APIENTRYP PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params); +GLAPI PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv; +#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv +typedef void (APIENTRYP PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint *params); +GLAPI PFNGLGETSHADERIVPROC glad_glGetShaderiv; +#define glGetShaderiv glad_glGetShaderiv +typedef void (APIENTRYP PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); +GLAPI PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog; +#define glGetShaderInfoLog glad_glGetShaderInfoLog +typedef void (APIENTRYP PFNGLGETSHADERPRECISIONFORMATPROC)(GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); +GLAPI PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat; +#define glGetShaderPrecisionFormat glad_glGetShaderPrecisionFormat +typedef void (APIENTRYP PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); +GLAPI PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource; +#define glGetShaderSource glad_glGetShaderSource +typedef const GLubyte * (APIENTRYP PFNGLGETSTRINGPROC)(GLenum name); +GLAPI PFNGLGETSTRINGPROC glad_glGetString; +#define glGetString glad_glGetString +typedef void (APIENTRYP PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat *params); +GLAPI PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv; +#define glGetTexParameterfv glad_glGetTexParameterfv +typedef void (APIENTRYP PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint *params); +GLAPI PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv; +#define glGetTexParameteriv glad_glGetTexParameteriv +typedef void (APIENTRYP PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat *params); +GLAPI PFNGLGETUNIFORMFVPROC glad_glGetUniformfv; +#define glGetUniformfv glad_glGetUniformfv +typedef void (APIENTRYP PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint *params); +GLAPI PFNGLGETUNIFORMIVPROC glad_glGetUniformiv; +#define glGetUniformiv glad_glGetUniformiv +typedef GLint (APIENTRYP PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar *name); +GLAPI PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation; +#define glGetUniformLocation glad_glGetUniformLocation +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat *params); +GLAPI PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv; +#define glGetVertexAttribfv glad_glGetVertexAttribfv +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint *params); +GLAPI PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv; +#define glGetVertexAttribiv glad_glGetVertexAttribiv +typedef void (APIENTRYP PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void **pointer); +GLAPI PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv; +#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv +typedef void (APIENTRYP PFNGLHINTPROC)(GLenum target, GLenum mode); +GLAPI PFNGLHINTPROC glad_glHint; +#define glHint glad_glHint +typedef GLboolean (APIENTRYP PFNGLISBUFFERPROC)(GLuint buffer); +GLAPI PFNGLISBUFFERPROC glad_glIsBuffer; +#define glIsBuffer glad_glIsBuffer +typedef GLboolean (APIENTRYP PFNGLISENABLEDPROC)(GLenum cap); +GLAPI PFNGLISENABLEDPROC glad_glIsEnabled; +#define glIsEnabled glad_glIsEnabled +typedef GLboolean (APIENTRYP PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer); +GLAPI PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer; +#define glIsFramebuffer glad_glIsFramebuffer +typedef GLboolean (APIENTRYP PFNGLISPROGRAMPROC)(GLuint program); +GLAPI PFNGLISPROGRAMPROC glad_glIsProgram; +#define glIsProgram glad_glIsProgram +typedef GLboolean (APIENTRYP PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer); +GLAPI PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer; +#define glIsRenderbuffer glad_glIsRenderbuffer +typedef GLboolean (APIENTRYP PFNGLISSHADERPROC)(GLuint shader); +GLAPI PFNGLISSHADERPROC glad_glIsShader; +#define glIsShader glad_glIsShader +typedef GLboolean (APIENTRYP PFNGLISTEXTUREPROC)(GLuint texture); +GLAPI PFNGLISTEXTUREPROC glad_glIsTexture; +#define glIsTexture glad_glIsTexture +typedef void (APIENTRYP PFNGLLINEWIDTHPROC)(GLfloat width); +GLAPI PFNGLLINEWIDTHPROC glad_glLineWidth; +#define glLineWidth glad_glLineWidth +typedef void (APIENTRYP PFNGLLINKPROGRAMPROC)(GLuint program); +GLAPI PFNGLLINKPROGRAMPROC glad_glLinkProgram; +#define glLinkProgram glad_glLinkProgram +typedef void (APIENTRYP PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param); +GLAPI PFNGLPIXELSTOREIPROC glad_glPixelStorei; +#define glPixelStorei glad_glPixelStorei +typedef void (APIENTRYP PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units); +GLAPI PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset; +#define glPolygonOffset glad_glPolygonOffset +typedef void (APIENTRYP PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); +GLAPI PFNGLREADPIXELSPROC glad_glReadPixels; +#define glReadPixels glad_glReadPixels +typedef void (APIENTRYP PFNGLRELEASESHADERCOMPILERPROC)(void); +GLAPI PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler; +#define glReleaseShaderCompiler glad_glReleaseShaderCompiler +typedef void (APIENTRYP PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GLAPI PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage; +#define glRenderbufferStorage glad_glRenderbufferStorage +typedef void (APIENTRYP PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert); +GLAPI PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage; +#define glSampleCoverage glad_glSampleCoverage +typedef void (APIENTRYP PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI PFNGLSCISSORPROC glad_glScissor; +#define glScissor glad_glScissor +typedef void (APIENTRYP PFNGLSHADERBINARYPROC)(GLsizei count, const GLuint *shaders, GLenum binaryFormat, const void *binary, GLsizei length); +GLAPI PFNGLSHADERBINARYPROC glad_glShaderBinary; +#define glShaderBinary glad_glShaderBinary +typedef void (APIENTRYP PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); +GLAPI PFNGLSHADERSOURCEPROC glad_glShaderSource; +#define glShaderSource glad_glShaderSource +typedef void (APIENTRYP PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask); +GLAPI PFNGLSTENCILFUNCPROC glad_glStencilFunc; +#define glStencilFunc glad_glStencilFunc +typedef void (APIENTRYP PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask); +GLAPI PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate; +#define glStencilFuncSeparate glad_glStencilFuncSeparate +typedef void (APIENTRYP PFNGLSTENCILMASKPROC)(GLuint mask); +GLAPI PFNGLSTENCILMASKPROC glad_glStencilMask; +#define glStencilMask glad_glStencilMask +typedef void (APIENTRYP PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask); +GLAPI PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate; +#define glStencilMaskSeparate glad_glStencilMaskSeparate +typedef void (APIENTRYP PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass); +GLAPI PFNGLSTENCILOPPROC glad_glStencilOp; +#define glStencilOp glad_glStencilOp +typedef void (APIENTRYP PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +GLAPI PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate; +#define glStencilOpSeparate glad_glStencilOpSeparate +typedef void (APIENTRYP PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); +GLAPI PFNGLTEXIMAGE2DPROC glad_glTexImage2D; +#define glTexImage2D glad_glTexImage2D +typedef void (APIENTRYP PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param); +GLAPI PFNGLTEXPARAMETERFPROC glad_glTexParameterf; +#define glTexParameterf glad_glTexParameterf +typedef void (APIENTRYP PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat *params); +GLAPI PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv; +#define glTexParameterfv glad_glTexParameterfv +typedef void (APIENTRYP PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param); +GLAPI PFNGLTEXPARAMETERIPROC glad_glTexParameteri; +#define glTexParameteri glad_glTexParameteri +typedef void (APIENTRYP PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint *params); +GLAPI PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv; +#define glTexParameteriv glad_glTexParameteriv +typedef void (APIENTRYP PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); +GLAPI PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D; +#define glTexSubImage2D glad_glTexSubImage2D +typedef void (APIENTRYP PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0); +GLAPI PFNGLUNIFORM1FPROC glad_glUniform1f; +#define glUniform1f glad_glUniform1f +typedef void (APIENTRYP PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat *value); +GLAPI PFNGLUNIFORM1FVPROC glad_glUniform1fv; +#define glUniform1fv glad_glUniform1fv +typedef void (APIENTRYP PFNGLUNIFORM1IPROC)(GLint location, GLint v0); +GLAPI PFNGLUNIFORM1IPROC glad_glUniform1i; +#define glUniform1i glad_glUniform1i +typedef void (APIENTRYP PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint *value); +GLAPI PFNGLUNIFORM1IVPROC glad_glUniform1iv; +#define glUniform1iv glad_glUniform1iv +typedef void (APIENTRYP PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1); +GLAPI PFNGLUNIFORM2FPROC glad_glUniform2f; +#define glUniform2f glad_glUniform2f +typedef void (APIENTRYP PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat *value); +GLAPI PFNGLUNIFORM2FVPROC glad_glUniform2fv; +#define glUniform2fv glad_glUniform2fv +typedef void (APIENTRYP PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1); +GLAPI PFNGLUNIFORM2IPROC glad_glUniform2i; +#define glUniform2i glad_glUniform2i +typedef void (APIENTRYP PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint *value); +GLAPI PFNGLUNIFORM2IVPROC glad_glUniform2iv; +#define glUniform2iv glad_glUniform2iv +typedef void (APIENTRYP PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +GLAPI PFNGLUNIFORM3FPROC glad_glUniform3f; +#define glUniform3f glad_glUniform3f +typedef void (APIENTRYP PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat *value); +GLAPI PFNGLUNIFORM3FVPROC glad_glUniform3fv; +#define glUniform3fv glad_glUniform3fv +typedef void (APIENTRYP PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2); +GLAPI PFNGLUNIFORM3IPROC glad_glUniform3i; +#define glUniform3i glad_glUniform3i +typedef void (APIENTRYP PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint *value); +GLAPI PFNGLUNIFORM3IVPROC glad_glUniform3iv; +#define glUniform3iv glad_glUniform3iv +typedef void (APIENTRYP PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +GLAPI PFNGLUNIFORM4FPROC glad_glUniform4f; +#define glUniform4f glad_glUniform4f +typedef void (APIENTRYP PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat *value); +GLAPI PFNGLUNIFORM4FVPROC glad_glUniform4fv; +#define glUniform4fv glad_glUniform4fv +typedef void (APIENTRYP PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +GLAPI PFNGLUNIFORM4IPROC glad_glUniform4i; +#define glUniform4i glad_glUniform4i +typedef void (APIENTRYP PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint *value); +GLAPI PFNGLUNIFORM4IVPROC glad_glUniform4iv; +#define glUniform4iv glad_glUniform4iv +typedef void (APIENTRYP PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv; +#define glUniformMatrix2fv glad_glUniformMatrix2fv +typedef void (APIENTRYP PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv; +#define glUniformMatrix3fv glad_glUniformMatrix3fv +typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); +GLAPI PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv; +#define glUniformMatrix4fv glad_glUniformMatrix4fv +typedef void (APIENTRYP PFNGLUSEPROGRAMPROC)(GLuint program); +GLAPI PFNGLUSEPROGRAMPROC glad_glUseProgram; +#define glUseProgram glad_glUseProgram +typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC)(GLuint program); +GLAPI PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram; +#define glValidateProgram glad_glValidateProgram +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x); +GLAPI PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f; +#define glVertexAttrib1f glad_glVertexAttrib1f +typedef void (APIENTRYP PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat *v); +GLAPI PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv; +#define glVertexAttrib1fv glad_glVertexAttrib1fv +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y); +GLAPI PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f; +#define glVertexAttrib2f glad_glVertexAttrib2f +typedef void (APIENTRYP PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat *v); +GLAPI PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv; +#define glVertexAttrib2fv glad_glVertexAttrib2fv +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z); +GLAPI PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f; +#define glVertexAttrib3f glad_glVertexAttrib3f +typedef void (APIENTRYP PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat *v); +GLAPI PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv; +#define glVertexAttrib3fv glad_glVertexAttrib3fv +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GLAPI PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f; +#define glVertexAttrib4f glad_glVertexAttrib4f +typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat *v); +GLAPI PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv; +#define glVertexAttrib4fv glad_glVertexAttrib4fv +typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); +GLAPI PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer; +#define glVertexAttribPointer glad_glVertexAttribPointer +typedef void (APIENTRYP PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +GLAPI PFNGLVIEWPORTPROC glad_glViewport; +#define glViewport glad_glViewport +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/common/rendering/gles/glad/include/glad/glad_egl.h b/src/common/rendering/gles/glad/include/glad/glad_egl.h new file mode 100644 index 0000000000..fbc5b8630b --- /dev/null +++ b/src/common/rendering/gles/glad/include/glad/glad_egl.h @@ -0,0 +1,267 @@ +/* + + EGL loader generated by glad 0.1.34 on Sat Feb 20 22:54:45 2021. + + Language/Generator: C/C++ + Specification: egl + APIs: egl=1.4 + Profile: - + Extensions: + + Loader: True + Local files: False + Omit khrplatform: False + Reproducible: False + + Commandline: + --api="egl=1.4" --generator="c" --spec="egl" --extensions="" + Online: + https://glad.dav1d.de/#language=c&specification=egl&loader=on&api=egl%3D1.4 +*/ + + +#ifndef __glad_egl_h_ + +#ifdef __egl_h_ +#error EGL header already included, remove this include, glad already provides it +#endif + +#define __glad_egl_h_ +#define __egl_h_ + +#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__) +#define APIENTRY __stdcall +#endif + +#ifndef APIENTRY +#define APIENTRY +#endif +#ifndef APIENTRYP +#define APIENTRYP APIENTRY * +#endif +#ifndef GLAPI +#define GLAPI extern +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* (* GLADloadproc)(const char *name); + +GLAPI int gladLoadEGL(void); +GLAPI int gladLoadEGLLoader(GLADloadproc); + +#include +#include + +#define EGL_CAST(X,V) (X)(V) + +struct AHardwareBuffer; +struct wl_buffer; +struct wl_display; +struct wl_resource; +typedef unsigned int EGLBoolean; +typedef unsigned int EGLenum; +typedef intptr_t EGLAttribKHR; +typedef intptr_t EGLAttrib; +typedef void *EGLClientBuffer; +typedef void *EGLConfig; +typedef void *EGLContext; +typedef void *EGLDeviceEXT; +typedef void *EGLDisplay; +typedef void *EGLImage; +typedef void *EGLImageKHR; +typedef void *EGLLabelKHR; +typedef void *EGLObjectKHR; +typedef void *EGLOutputLayerEXT; +typedef void *EGLOutputPortEXT; +typedef void *EGLStreamKHR; +typedef void *EGLSurface; +typedef void *EGLSync; +typedef void *EGLSyncKHR; +typedef void *EGLSyncNV; +typedef void (*__eglMustCastToProperFunctionPointerType)(void); +typedef khronos_utime_nanoseconds_t EGLTimeKHR; +typedef khronos_utime_nanoseconds_t EGLTime; +typedef khronos_utime_nanoseconds_t EGLTimeNV; +typedef khronos_utime_nanoseconds_t EGLuint64NV; +typedef khronos_uint64_t EGLuint64KHR; +typedef khronos_stime_nanoseconds_t EGLnsecsANDROID; +typedef int EGLNativeFileDescriptorKHR; +typedef khronos_ssize_t EGLsizeiANDROID; +typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize); +typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize); +struct EGLClientPixmapHI { + void *pData; + EGLint iWidth; + EGLint iHeight; + EGLint iStride; +}; +typedef void (APIENTRY *EGLDEBUGPROCKHR)(EGLenum error,const char *command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char* message); +#define PFNEGLBINDWAYLANDDISPLAYWL PFNEGLBINDWAYLANDDISPLAYWLPROC +#define PFNEGLUNBINDWAYLANDDISPLAYWL PFNEGLUNBINDWAYLANDDISPLAYWLPROC +#define PFNEGLQUERYWAYLANDBUFFERWL PFNEGLQUERYWAYLANDBUFFERWLPROC +#define PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWL PFNEGLCREATEWAYLANDBUFFERFROMIMAGEWLPROC +#define EGL_ALPHA_SIZE 0x3021 +#define EGL_BAD_ACCESS 0x3002 +#define EGL_BAD_ALLOC 0x3003 +#define EGL_BAD_ATTRIBUTE 0x3004 +#define EGL_BAD_CONFIG 0x3005 +#define EGL_BAD_CONTEXT 0x3006 +#define EGL_BAD_CURRENT_SURFACE 0x3007 +#define EGL_BAD_DISPLAY 0x3008 +#define EGL_BAD_MATCH 0x3009 +#define EGL_BAD_NATIVE_PIXMAP 0x300A +#define EGL_BAD_NATIVE_WINDOW 0x300B +#define EGL_BAD_PARAMETER 0x300C +#define EGL_BAD_SURFACE 0x300D +#define EGL_BLUE_SIZE 0x3022 +#define EGL_BUFFER_SIZE 0x3020 +#define EGL_CONFIG_CAVEAT 0x3027 +#define EGL_CONFIG_ID 0x3028 +#define EGL_CORE_NATIVE_ENGINE 0x305B +#define EGL_DEPTH_SIZE 0x3025 +#define EGL_DONT_CARE EGL_CAST(EGLint,-1) +#define EGL_DRAW 0x3059 +#define EGL_EXTENSIONS 0x3055 +#define EGL_FALSE 0 +#define EGL_GREEN_SIZE 0x3023 +#define EGL_HEIGHT 0x3056 +#define EGL_LARGEST_PBUFFER 0x3058 +#define EGL_LEVEL 0x3029 +#define EGL_MAX_PBUFFER_HEIGHT 0x302A +#define EGL_MAX_PBUFFER_PIXELS 0x302B +#define EGL_MAX_PBUFFER_WIDTH 0x302C +#define EGL_NATIVE_RENDERABLE 0x302D +#define EGL_NATIVE_VISUAL_ID 0x302E +#define EGL_NATIVE_VISUAL_TYPE 0x302F +#define EGL_NONE 0x3038 +#define EGL_NON_CONFORMANT_CONFIG 0x3051 +#define EGL_NOT_INITIALIZED 0x3001 +#define EGL_NO_CONTEXT EGL_CAST(EGLContext,0) +#define EGL_NO_DISPLAY EGL_CAST(EGLDisplay,0) +#define EGL_NO_SURFACE EGL_CAST(EGLSurface,0) +#define EGL_PBUFFER_BIT 0x0001 +#define EGL_PIXMAP_BIT 0x0002 +#define EGL_READ 0x305A +#define EGL_RED_SIZE 0x3024 +#define EGL_SAMPLES 0x3031 +#define EGL_SAMPLE_BUFFERS 0x3032 +#define EGL_SLOW_CONFIG 0x3050 +#define EGL_STENCIL_SIZE 0x3026 +#define EGL_SUCCESS 0x3000 +#define EGL_SURFACE_TYPE 0x3033 +#define EGL_TRANSPARENT_BLUE_VALUE 0x3035 +#define EGL_TRANSPARENT_GREEN_VALUE 0x3036 +#define EGL_TRANSPARENT_RED_VALUE 0x3037 +#define EGL_TRANSPARENT_RGB 0x3052 +#define EGL_TRANSPARENT_TYPE 0x3034 +#define EGL_TRUE 1 +#define EGL_VENDOR 0x3053 +#define EGL_VERSION 0x3054 +#define EGL_WIDTH 0x3057 +#define EGL_WINDOW_BIT 0x0004 +#define EGL_BACK_BUFFER 0x3084 +#define EGL_BIND_TO_TEXTURE_RGB 0x3039 +#define EGL_BIND_TO_TEXTURE_RGBA 0x303A +#define EGL_CONTEXT_LOST 0x300E +#define EGL_MIN_SWAP_INTERVAL 0x303B +#define EGL_MAX_SWAP_INTERVAL 0x303C +#define EGL_MIPMAP_TEXTURE 0x3082 +#define EGL_MIPMAP_LEVEL 0x3083 +#define EGL_NO_TEXTURE 0x305C +#define EGL_TEXTURE_2D 0x305F +#define EGL_TEXTURE_FORMAT 0x3080 +#define EGL_TEXTURE_RGB 0x305D +#define EGL_TEXTURE_RGBA 0x305E +#define EGL_TEXTURE_TARGET 0x3081 +#define EGL_ALPHA_FORMAT 0x3088 +#define EGL_ALPHA_FORMAT_NONPRE 0x308B +#define EGL_ALPHA_FORMAT_PRE 0x308C +#define EGL_ALPHA_MASK_SIZE 0x303E +#define EGL_BUFFER_PRESERVED 0x3094 +#define EGL_BUFFER_DESTROYED 0x3095 +#define EGL_CLIENT_APIS 0x308D +#define EGL_COLORSPACE 0x3087 +#define EGL_COLORSPACE_sRGB 0x3089 +#define EGL_COLORSPACE_LINEAR 0x308A +#define EGL_COLOR_BUFFER_TYPE 0x303F +#define EGL_CONTEXT_CLIENT_TYPE 0x3097 +#define EGL_DISPLAY_SCALING 10000 +#define EGL_HORIZONTAL_RESOLUTION 0x3090 +#define EGL_LUMINANCE_BUFFER 0x308F +#define EGL_LUMINANCE_SIZE 0x303D +#define EGL_OPENGL_ES_BIT 0x0001 +#define EGL_OPENVG_BIT 0x0002 +#define EGL_OPENGL_ES_API 0x30A0 +#define EGL_OPENVG_API 0x30A1 +#define EGL_OPENVG_IMAGE 0x3096 +#define EGL_PIXEL_ASPECT_RATIO 0x3092 +#define EGL_RENDERABLE_TYPE 0x3040 +#define EGL_RENDER_BUFFER 0x3086 +#define EGL_RGB_BUFFER 0x308E +#define EGL_SINGLE_BUFFER 0x3085 +#define EGL_SWAP_BEHAVIOR 0x3093 +#define EGL_UNKNOWN EGL_CAST(EGLint,-1) +#define EGL_VERTICAL_RESOLUTION 0x3091 +#define EGL_CONFORMANT 0x3042 +#define EGL_CONTEXT_CLIENT_VERSION 0x3098 +#define EGL_MATCH_NATIVE_PIXMAP 0x3041 +#define EGL_OPENGL_ES2_BIT 0x0004 +#define EGL_VG_ALPHA_FORMAT 0x3088 +#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B +#define EGL_VG_ALPHA_FORMAT_PRE 0x308C +#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040 +#define EGL_VG_COLORSPACE 0x3087 +#define EGL_VG_COLORSPACE_sRGB 0x3089 +#define EGL_VG_COLORSPACE_LINEAR 0x308A +#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020 +#define EGL_DEFAULT_DISPLAY EGL_CAST(EGLNativeDisplayType,0) +#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 +#define EGL_MULTISAMPLE_RESOLVE 0x3099 +#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A +#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B +#define EGL_OPENGL_API 0x30A2 +#define EGL_OPENGL_BIT 0x0008 +#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 +EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); +EGLBoolean eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target); +EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); +EGLSurface eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); +EGLSurface eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list); +EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list); +EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx); +EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface); +EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); +EGLBoolean eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); +EGLDisplay eglGetCurrentDisplay(void); +EGLSurface eglGetCurrentSurface(EGLint readdraw); +EGLDisplay eglGetDisplay(EGLNativeDisplayType display_id); +EGLint eglGetError(void); +__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname); +EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor); +EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); +EGLBoolean eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value); +const char *eglQueryString(EGLDisplay dpy, EGLint name); +EGLBoolean eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); +EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface); +EGLBoolean eglTerminate(EGLDisplay dpy); +EGLBoolean eglWaitGL(void); +EGLBoolean eglWaitNative(EGLint engine); +EGLBoolean eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer); +EGLBoolean eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer); +EGLBoolean eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); +EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval); +EGLBoolean eglBindAPI(EGLenum api); +EGLenum eglQueryAPI(void); +EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list); +EGLBoolean eglReleaseThread(void); +EGLBoolean eglWaitClient(void); +EGLContext eglGetCurrentContext(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/common/rendering/gles/glad/src/glad.c b/src/common/rendering/gles/glad/src/glad.c new file mode 100644 index 0000000000..9da9f0ed1d --- /dev/null +++ b/src/common/rendering/gles/glad/src/glad.c @@ -0,0 +1,475 @@ +/* + + OpenGL ES loader generated by glad 0.1.34 on Fri Mar 19 17:04:24 2021. + + Language/Generator: C/C++ + Specification: gl + APIs: gles2=2.0 + Profile: compatibility + Extensions: + + Loader: True + Local files: False + Omit khrplatform: False + Reproducible: False + + Commandline: + --profile="compatibility" --api="gles2=2.0" --generator="c" --spec="gl" --extensions="" + Online: + https://glad.dav1d.de/#profile=compatibility&language=c&specification=gl&loader=on&api=gles2%3D2.0 +*/ + +#include +#include +#include +#include + +struct gladGLversionStruct GLVersion = { 0, 0 }; + +#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0) +#define _GLAD_IS_SOME_NEW_VERSION 1 +#endif + +static int max_loaded_major; +static int max_loaded_minor; + +static const char *exts = NULL; +static int num_exts_i = 0; +static char **exts_i = NULL; + +static int get_exts(void) { +#ifdef _GLAD_IS_SOME_NEW_VERSION + if(max_loaded_major < 3) { +#endif + exts = (const char *)glGetString(GL_EXTENSIONS); +#ifdef _GLAD_IS_SOME_NEW_VERSION + } else { + unsigned int index; + + num_exts_i = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i); + if (num_exts_i > 0) { + exts_i = (char **)malloc((size_t)num_exts_i * (sizeof *exts_i)); + } + + if (exts_i == NULL) { + return 0; + } + + for(index = 0; index < (unsigned)num_exts_i; index++) { + const char *gl_str_tmp = (const char*)glGetStringi(GL_EXTENSIONS, index); + size_t len = strlen(gl_str_tmp); + + char *local_str = (char*)malloc((len+1) * sizeof(char)); + if(local_str != NULL) { + memcpy(local_str, gl_str_tmp, (len+1) * sizeof(char)); + } + exts_i[index] = local_str; + } + } +#endif + return 1; +} + +static void free_exts(void) { + if (exts_i != NULL) { + int index; + for(index = 0; index < num_exts_i; index++) { + free((char *)exts_i[index]); + } + free((void *)exts_i); + exts_i = NULL; + } +} + +static int has_ext(const char *ext) { +#ifdef _GLAD_IS_SOME_NEW_VERSION + if(max_loaded_major < 3) { +#endif + 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; + } +#ifdef _GLAD_IS_SOME_NEW_VERSION + } else { + int index; + if(exts_i == NULL) return 0; + for(index = 0; index < num_exts_i; index++) { + const char *e = exts_i[index]; + + if(exts_i[index] != NULL && strcmp(e, ext) == 0) { + return 1; + } + } + } +#endif + + return 0; +} +int GLAD_GL_ES_VERSION_2_0 = 0; +PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL; +PFNGLATTACHSHADERPROC glad_glAttachShader = NULL; +PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL; +PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL; +PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL; +PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL; +PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL; +PFNGLBLENDCOLORPROC glad_glBlendColor = NULL; +PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL; +PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL; +PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL; +PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL; +PFNGLBUFFERDATAPROC glad_glBufferData = NULL; +PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL; +PFNGLCLEARPROC glad_glClear = NULL; +PFNGLCLEARCOLORPROC glad_glClearColor = NULL; +PFNGLCLEARDEPTHFPROC glad_glClearDepthf = NULL; +PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL; +PFNGLCOLORMASKPROC glad_glColorMask = NULL; +PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL; +PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL; +PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL; +PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = 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; +PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL; +PFNGLDELETESHADERPROC glad_glDeleteShader = NULL; +PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL; +PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL; +PFNGLDEPTHMASKPROC glad_glDepthMask = NULL; +PFNGLDEPTHRANGEFPROC glad_glDepthRangef = NULL; +PFNGLDETACHSHADERPROC glad_glDetachShader = NULL; +PFNGLDISABLEPROC glad_glDisable = NULL; +PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL; +PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL; +PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL; +PFNGLENABLEPROC glad_glEnable = NULL; +PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL; +PFNGLFINISHPROC glad_glFinish = NULL; +PFNGLFLUSHPROC glad_glFlush = NULL; +PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL; +PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL; +PFNGLFRONTFACEPROC glad_glFrontFace = NULL; +PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL; +PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL; +PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL; +PFNGLGENTEXTURESPROC glad_glGenTextures = NULL; +PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL; +PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL; +PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL; +PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL; +PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL; +PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL; +PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL; +PFNGLGETERRORPROC glad_glGetError = NULL; +PFNGLGETFLOATVPROC glad_glGetFloatv = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL; +PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL; +PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL; +PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL; +PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL; +PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat = NULL; +PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL; +PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL; +PFNGLGETSTRINGPROC glad_glGetString = NULL; +PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL; +PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL; +PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL; +PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL; +PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL; +PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL; +PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL; +PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL; +PFNGLHINTPROC glad_glHint = NULL; +PFNGLISBUFFERPROC glad_glIsBuffer = NULL; +PFNGLISENABLEDPROC glad_glIsEnabled = NULL; +PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL; +PFNGLISPROGRAMPROC glad_glIsProgram = NULL; +PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL; +PFNGLISSHADERPROC glad_glIsShader = NULL; +PFNGLISTEXTUREPROC glad_glIsTexture = NULL; +PFNGLLINEWIDTHPROC glad_glLineWidth = NULL; +PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL; +PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL; +PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL; +PFNGLREADPIXELSPROC glad_glReadPixels = NULL; +PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler = NULL; +PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL; +PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL; +PFNGLSCISSORPROC glad_glScissor = NULL; +PFNGLSHADERBINARYPROC glad_glShaderBinary = 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; +PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL; +PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL; +PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL; +PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL; +PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL; +PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL; +PFNGLUNIFORM1FPROC glad_glUniform1f = NULL; +PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL; +PFNGLUNIFORM1IPROC glad_glUniform1i = NULL; +PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL; +PFNGLUNIFORM2FPROC glad_glUniform2f = NULL; +PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL; +PFNGLUNIFORM2IPROC glad_glUniform2i = NULL; +PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL; +PFNGLUNIFORM3FPROC glad_glUniform3f = NULL; +PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL; +PFNGLUNIFORM3IPROC glad_glUniform3i = NULL; +PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL; +PFNGLUNIFORM4FPROC glad_glUniform4f = NULL; +PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL; +PFNGLUNIFORM4IPROC glad_glUniform4i = NULL; +PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL; +PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL; +PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL; +PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL; +PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL; +PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL; +PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL; +PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL; +PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL; +PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL; +PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL; +PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL; +PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL; +PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL; +PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL; +PFNGLVIEWPORTPROC glad_glViewport = NULL; +static void load_GL_ES_VERSION_2_0(GLADloadproc load) { + if(!GLAD_GL_ES_VERSION_2_0) return; + glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC)load("glActiveTexture"); + glad_glAttachShader = (PFNGLATTACHSHADERPROC)load("glAttachShader"); + glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)load("glBindAttribLocation"); + glad_glBindBuffer = (PFNGLBINDBUFFERPROC)load("glBindBuffer"); + glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC)load("glBindFramebuffer"); + glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC)load("glBindRenderbuffer"); + glad_glBindTexture = (PFNGLBINDTEXTUREPROC)load("glBindTexture"); + glad_glBlendColor = (PFNGLBLENDCOLORPROC)load("glBlendColor"); + glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC)load("glBlendEquation"); + glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC)load("glBlendEquationSeparate"); + glad_glBlendFunc = (PFNGLBLENDFUNCPROC)load("glBlendFunc"); + glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC)load("glBlendFuncSeparate"); + glad_glBufferData = (PFNGLBUFFERDATAPROC)load("glBufferData"); + glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC)load("glBufferSubData"); + glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)load("glCheckFramebufferStatus"); + glad_glClear = (PFNGLCLEARPROC)load("glClear"); + glad_glClearColor = (PFNGLCLEARCOLORPROC)load("glClearColor"); + glad_glClearDepthf = (PFNGLCLEARDEPTHFPROC)load("glClearDepthf"); + glad_glClearStencil = (PFNGLCLEARSTENCILPROC)load("glClearStencil"); + glad_glColorMask = (PFNGLCOLORMASKPROC)load("glColorMask"); + glad_glCompileShader = (PFNGLCOMPILESHADERPROC)load("glCompileShader"); + glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)load("glCompressedTexImage2D"); + glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)load("glCompressedTexSubImage2D"); + glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC)load("glCopyTexImage2D"); + glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC)load("glCopyTexSubImage2D"); + glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC)load("glCreateProgram"); + glad_glCreateShader = (PFNGLCREATESHADERPROC)load("glCreateShader"); + glad_glCullFace = (PFNGLCULLFACEPROC)load("glCullFace"); + glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC)load("glDeleteBuffers"); + glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC)load("glDeleteFramebuffers"); + glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC)load("glDeleteProgram"); + glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)load("glDeleteRenderbuffers"); + glad_glDeleteShader = (PFNGLDELETESHADERPROC)load("glDeleteShader"); + glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC)load("glDeleteTextures"); + glad_glDepthFunc = (PFNGLDEPTHFUNCPROC)load("glDepthFunc"); + glad_glDepthMask = (PFNGLDEPTHMASKPROC)load("glDepthMask"); + glad_glDepthRangef = (PFNGLDEPTHRANGEFPROC)load("glDepthRangef"); + glad_glDetachShader = (PFNGLDETACHSHADERPROC)load("glDetachShader"); + glad_glDisable = (PFNGLDISABLEPROC)load("glDisable"); + glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC)load("glDisableVertexAttribArray"); + glad_glDrawArrays = (PFNGLDRAWARRAYSPROC)load("glDrawArrays"); + glad_glDrawElements = (PFNGLDRAWELEMENTSPROC)load("glDrawElements"); + glad_glEnable = (PFNGLENABLEPROC)load("glEnable"); + glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC)load("glEnableVertexAttribArray"); + glad_glFinish = (PFNGLFINISHPROC)load("glFinish"); + glad_glFlush = (PFNGLFLUSHPROC)load("glFlush"); + glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)load("glFramebufferRenderbuffer"); + glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC)load("glFramebufferTexture2D"); + glad_glFrontFace = (PFNGLFRONTFACEPROC)load("glFrontFace"); + glad_glGenBuffers = (PFNGLGENBUFFERSPROC)load("glGenBuffers"); + glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC)load("glGenerateMipmap"); + glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC)load("glGenFramebuffers"); + glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC)load("glGenRenderbuffers"); + glad_glGenTextures = (PFNGLGENTEXTURESPROC)load("glGenTextures"); + glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC)load("glGetActiveAttrib"); + glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC)load("glGetActiveUniform"); + glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC)load("glGetAttachedShaders"); + glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC)load("glGetAttribLocation"); + glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC)load("glGetBooleanv"); + glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC)load("glGetBufferParameteriv"); + glad_glGetError = (PFNGLGETERRORPROC)load("glGetError"); + glad_glGetFloatv = (PFNGLGETFLOATVPROC)load("glGetFloatv"); + glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)load("glGetFramebufferAttachmentParameteriv"); + glad_glGetIntegerv = (PFNGLGETINTEGERVPROC)load("glGetIntegerv"); + glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC)load("glGetProgramiv"); + glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)load("glGetProgramInfoLog"); + glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC)load("glGetRenderbufferParameteriv"); + glad_glGetShaderiv = (PFNGLGETSHADERIVPROC)load("glGetShaderiv"); + glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)load("glGetShaderInfoLog"); + glad_glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC)load("glGetShaderPrecisionFormat"); + glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC)load("glGetShaderSource"); + glad_glGetString = (PFNGLGETSTRINGPROC)load("glGetString"); + glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC)load("glGetTexParameterfv"); + glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC)load("glGetTexParameteriv"); + glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC)load("glGetUniformfv"); + glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC)load("glGetUniformiv"); + glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)load("glGetUniformLocation"); + glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC)load("glGetVertexAttribfv"); + glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC)load("glGetVertexAttribiv"); + glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC)load("glGetVertexAttribPointerv"); + glad_glHint = (PFNGLHINTPROC)load("glHint"); + glad_glIsBuffer = (PFNGLISBUFFERPROC)load("glIsBuffer"); + glad_glIsEnabled = (PFNGLISENABLEDPROC)load("glIsEnabled"); + glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC)load("glIsFramebuffer"); + glad_glIsProgram = (PFNGLISPROGRAMPROC)load("glIsProgram"); + glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC)load("glIsRenderbuffer"); + glad_glIsShader = (PFNGLISSHADERPROC)load("glIsShader"); + glad_glIsTexture = (PFNGLISTEXTUREPROC)load("glIsTexture"); + glad_glLineWidth = (PFNGLLINEWIDTHPROC)load("glLineWidth"); + glad_glLinkProgram = (PFNGLLINKPROGRAMPROC)load("glLinkProgram"); + glad_glPixelStorei = (PFNGLPIXELSTOREIPROC)load("glPixelStorei"); + glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC)load("glPolygonOffset"); + glad_glReadPixels = (PFNGLREADPIXELSPROC)load("glReadPixels"); + glad_glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC)load("glReleaseShaderCompiler"); + glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC)load("glRenderbufferStorage"); + glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC)load("glSampleCoverage"); + glad_glScissor = (PFNGLSCISSORPROC)load("glScissor"); + glad_glShaderBinary = (PFNGLSHADERBINARYPROC)load("glShaderBinary"); + glad_glShaderSource = (PFNGLSHADERSOURCEPROC)load("glShaderSource"); + glad_glStencilFunc = (PFNGLSTENCILFUNCPROC)load("glStencilFunc"); + glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC)load("glStencilFuncSeparate"); + glad_glStencilMask = (PFNGLSTENCILMASKPROC)load("glStencilMask"); + glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC)load("glStencilMaskSeparate"); + glad_glStencilOp = (PFNGLSTENCILOPPROC)load("glStencilOp"); + glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC)load("glStencilOpSeparate"); + glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC)load("glTexImage2D"); + glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC)load("glTexParameterf"); + glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC)load("glTexParameterfv"); + glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC)load("glTexParameteri"); + glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC)load("glTexParameteriv"); + glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC)load("glTexSubImage2D"); + glad_glUniform1f = (PFNGLUNIFORM1FPROC)load("glUniform1f"); + glad_glUniform1fv = (PFNGLUNIFORM1FVPROC)load("glUniform1fv"); + glad_glUniform1i = (PFNGLUNIFORM1IPROC)load("glUniform1i"); + glad_glUniform1iv = (PFNGLUNIFORM1IVPROC)load("glUniform1iv"); + glad_glUniform2f = (PFNGLUNIFORM2FPROC)load("glUniform2f"); + glad_glUniform2fv = (PFNGLUNIFORM2FVPROC)load("glUniform2fv"); + glad_glUniform2i = (PFNGLUNIFORM2IPROC)load("glUniform2i"); + glad_glUniform2iv = (PFNGLUNIFORM2IVPROC)load("glUniform2iv"); + glad_glUniform3f = (PFNGLUNIFORM3FPROC)load("glUniform3f"); + glad_glUniform3fv = (PFNGLUNIFORM3FVPROC)load("glUniform3fv"); + glad_glUniform3i = (PFNGLUNIFORM3IPROC)load("glUniform3i"); + glad_glUniform3iv = (PFNGLUNIFORM3IVPROC)load("glUniform3iv"); + glad_glUniform4f = (PFNGLUNIFORM4FPROC)load("glUniform4f"); + glad_glUniform4fv = (PFNGLUNIFORM4FVPROC)load("glUniform4fv"); + glad_glUniform4i = (PFNGLUNIFORM4IPROC)load("glUniform4i"); + glad_glUniform4iv = (PFNGLUNIFORM4IVPROC)load("glUniform4iv"); + glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC)load("glUniformMatrix2fv"); + glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC)load("glUniformMatrix3fv"); + glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC)load("glUniformMatrix4fv"); + glad_glUseProgram = (PFNGLUSEPROGRAMPROC)load("glUseProgram"); + glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC)load("glValidateProgram"); + glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC)load("glVertexAttrib1f"); + glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC)load("glVertexAttrib1fv"); + glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC)load("glVertexAttrib2f"); + glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC)load("glVertexAttrib2fv"); + glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC)load("glVertexAttrib3f"); + glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC)load("glVertexAttrib3fv"); + glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC)load("glVertexAttrib4f"); + glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC)load("glVertexAttrib4fv"); + glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC)load("glVertexAttribPointer"); + glad_glViewport = (PFNGLVIEWPORTPROC)load("glViewport"); +} +static int find_extensionsGLES2(void) { + if (!get_exts()) return 0; + (void)&has_ext; + free_exts(); + return 1; +} + +static void find_coreGLES2(void) { + + /* Thank you @elmindreda + * https://github.com/elmindreda/greg/blob/master/templates/greg.c.in#L176 + * https://github.com/glfw/glfw/blob/master/src/context.c#L36 + */ + int i, major, minor; + + const char* version; + const char* prefixes[] = { + "OpenGL ES-CM ", + "OpenGL ES-CL ", + "OpenGL ES ", + NULL + }; + + version = (const char*) glGetString(GL_VERSION); + if (!version) return; + + for (i = 0; prefixes[i]; i++) { + const size_t length = strlen(prefixes[i]); + if (strncmp(version, prefixes[i], length) == 0) { + version += length; + break; + } + } + +/* PR #18 */ +#ifdef _MSC_VER + sscanf_s(version, "%d.%d", &major, &minor); +#else + sscanf(version, "%d.%d", &major, &minor); +#endif + + GLVersion.major = major; GLVersion.minor = minor; + max_loaded_major = major; max_loaded_minor = minor; + GLAD_GL_ES_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2; + if (GLVersion.major > 2 || (GLVersion.major >= 2 && GLVersion.minor >= 0)) { + max_loaded_major = 2; + max_loaded_minor = 0; + } +} + +int gladLoadGLES2Loader(GLADloadproc load) { + GLVersion.major = 0; GLVersion.minor = 0; + glGetString = (PFNGLGETSTRINGPROC)load("glGetString"); + if(glGetString == NULL) return 0; + if(glGetString(GL_VERSION) == NULL) return 0; + find_coreGLES2(); + load_GL_ES_VERSION_2_0(load); + + if (!find_extensionsGLES2()) return 0; + return GLVersion.major != 0 || GLVersion.minor != 0; +} + diff --git a/src/common/rendering/gles/glad/src/glad_egl.c b/src/common/rendering/gles/glad/src/glad_egl.c new file mode 100644 index 0000000000..3c939401c2 --- /dev/null +++ b/src/common/rendering/gles/glad/src/glad_egl.c @@ -0,0 +1,45 @@ +/* + + EGL loader generated by glad 0.1.34 on Sat Feb 20 22:54:45 2021. + + Language/Generator: C/C++ + Specification: egl + APIs: egl=1.4 + Profile: - + Extensions: + + Loader: True + Local files: False + Omit khrplatform: False + Reproducible: False + + Commandline: + --api="egl=1.4" --generator="c" --spec="egl" --extensions="" + Online: + https://glad.dav1d.de/#language=c&specification=egl&loader=on&api=egl%3D1.4 +*/ + +#include +#include +#include +#include + +int gladLoadEGL(void) { + return gladLoadEGLLoader((GLADloadproc)eglGetProcAddress); +} + +static int find_extensionsEGL(void) { + return 1; +} + +static void find_coreEGL(void) { +} + +int gladLoadEGLLoader(GLADloadproc load) { + (void) load; + find_coreEGL(); + + if (!find_extensionsEGL()) return 0; + return 1; +} + diff --git a/src/common/rendering/gles/gles_buffers.cpp b/src/common/rendering/gles/gles_buffers.cpp new file mode 100644 index 0000000000..61296f3627 --- /dev/null +++ b/src/common/rendering/gles/gles_buffers.cpp @@ -0,0 +1,307 @@ +/* +** gl_buffers.cpp +** Low level vertex buffer class +** +**--------------------------------------------------------------------------- +** Copyright 2018-2020 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +**/ + +#include +#include "gles_system.h" +#include "gles_buffers.h" +#include "gles_renderstate.h" +#include "v_video.h" +#include "flatvertices.h" + +namespace OpenGLESRenderer +{ + +//========================================================================== +// +// basic buffer implementation +// +//========================================================================== + +static inline void InvalidateBufferState() +{ + gl_RenderState.ResetVertexBuffer(); // force rebinding of buffers on next Apply call. +} + +GLBuffer::GLBuffer(int usetype) + : mUseType(usetype) +{ + if ((usetype == GL_ARRAY_BUFFER) || (usetype == GL_ELEMENT_ARRAY_BUFFER)) + { + glGenBuffers(1, &mBufferId); + isData = false; + } + else + { + isData = true; + } +} + +GLBuffer::~GLBuffer() +{ + if (mBufferId != 0) + { + if (gles.useMappedBuffers) + { + glBindBuffer(mUseType, mBufferId); + glUnmapBuffer(mUseType); + } + glBindBuffer(mUseType, 0); + glDeleteBuffers(1, &mBufferId); + } + + if (memory) + delete[] memory; +} + +void GLBuffer::Bind() +{ + if (!isData) + { + glBindBuffer(mUseType, mBufferId); + } +} + + +void GLBuffer::SetData(size_t size, const void* data, bool staticdata) +{ + if (isData || !gles.useMappedBuffers) + { + if (memory) + delete[] memory; + + memory = (char*)(new uint64_t[size / 8 + 16]); + + if (data) + memcpy(memory, data, size); + } + + if (!isData) + { + Bind(); + glBufferData(mUseType, size, data, staticdata ? GL_STATIC_DRAW : GL_STREAM_DRAW); + } + + if (!isData && gles.useMappedBuffers) + { + map = 0; + } + else + { + map = memory; + } + + buffersize = size; + InvalidateBufferState(); +} + +void GLBuffer::SetSubData(size_t offset, size_t size, const void *data) +{ + Bind(); + + memcpy(memory + offset, data, size); + + if (!isData) + { + glBufferSubData(mUseType, offset, size, data); + } +} + +void GLBuffer::Upload(size_t start, size_t size) +{ + if (!gles.useMappedBuffers) + { + Bind(); + + if(size) + glBufferSubData(mUseType, start, size, memory + start); + } +} + +void GLBuffer::Map() +{ + if (!isData && gles.useMappedBuffers) + { + Bind(); + map = (FFlatVertex*)glMapBufferRange(mUseType, 0, buffersize, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); + } + else + { + map = memory; + } + InvalidateBufferState(); +} + +void GLBuffer::Unmap() +{ + if (!isData && gles.useMappedBuffers) + { + Bind(); + glUnmapBuffer(mUseType); + InvalidateBufferState(); + } +} + +void *GLBuffer::Lock(unsigned int size) +{ + // This initializes this buffer as a static object with no data. + SetData(size, nullptr, true); + if (!isData && gles.useMappedBuffers) + { + return glMapBufferRange(mUseType, 0, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT); + } + else + { + return map; + } +} + +void GLBuffer::Unlock() +{ + if (!isData) + { + if (gles.useMappedBuffers) + { + Bind(); + glUnmapBuffer(mUseType); + InvalidateBufferState(); + } + else + { + Bind(); + glBufferData(mUseType, buffersize, map, GL_STATIC_DRAW); + InvalidateBufferState(); + } + } +} + +void GLBuffer::Resize(size_t newsize) +{ + assert(!nomap); // only mappable buffers can be resized. + if (newsize > buffersize && !nomap) + { + /* + // reallocate the buffer with twice the size + unsigned int oldbuffer = mBufferId; + + // first unmap the old buffer + Bind(); + glUnmapBuffer(mUseType); + + glGenBuffers(1, &mBufferId); + SetData(newsize, nullptr, false); + glBindBuffer(GL_COPY_READ_BUFFER, oldbuffer); + + // copy contents and delete the old buffer. + glCopyBufferSubData(GL_COPY_READ_BUFFER, mUseType, 0, 0, buffersize); + glBindBuffer(GL_COPY_READ_BUFFER, 0); + glDeleteBuffers(1, &oldbuffer); + buffersize = newsize; + InvalidateBufferState(); + */ + } +} + + +//=========================================================================== +// +// Vertex buffer implementation +// +//=========================================================================== + +void GLVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) +{ + static int VFmtToGLFmt[] = { GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_UNSIGNED_BYTE, GL_FLOAT }; // TODO Fix last entry GL_INT_2_10_10_10_REV, normals for models will be broken + static uint8_t VFmtToSize[] = {4, 3, 2, 1, 4, 4}; + + mStride = stride; + mNumBindingPoints = numBindingPoints; + + for(int i = 0; i < numAttributes; i++) + { + if (attrs[i].location >= 0 && attrs[i].location < VATTR_MAX) + { + auto & attrinf = mAttributeInfo[attrs[i].location]; + attrinf.format = VFmtToGLFmt[attrs[i].format]; + attrinf.size = VFmtToSize[attrs[i].format]; + attrinf.offset = attrs[i].offset; + attrinf.bindingpoint = attrs[i].binding; + } + } +} + +void GLVertexBuffer::Bind(int *offsets) +{ + int i = 0; + + // This is what gets called from RenderState.Apply. It shouldn't be called anywhere else if the render state is in use + GLBuffer::Bind(); + for(auto &attrinf : mAttributeInfo) + { + if (attrinf.size == 0) + { + glDisableVertexAttribArray(i); + } + else + { + glEnableVertexAttribArray(i); + size_t ofs = offsets == nullptr ? attrinf.offset : attrinf.offset + mStride * offsets[attrinf.bindingpoint]; + glVertexAttribPointer(i, attrinf.size, attrinf.format, attrinf.format != GL_FLOAT, (GLsizei)mStride, (void*)(intptr_t)ofs); + } + i++; + } +} + +void GLDataBuffer::BindRange(FRenderState *state, size_t start, size_t length) +{ + if (mBindingPoint == 3)// VIEWPOINT_BINDINGPOINT + { + static_cast(state)->ApplyViewport(memory + start); + } + else + { + //glBindBufferRange(mUseType, mBindingPoint, mBufferId, start, length); + } +} + +void GLDataBuffer::BindBase() +{ + //glBindBufferBase(mUseType, mBindingPoint, mBufferId); +} + + +GLVertexBuffer::GLVertexBuffer() : GLBuffer(GL_ARRAY_BUFFER) {} +GLIndexBuffer::GLIndexBuffer() : GLBuffer(GL_ELEMENT_ARRAY_BUFFER) {} +GLDataBuffer::GLDataBuffer(int bindingpoint, bool is_ssbo) : GLBuffer(0), mBindingPoint(bindingpoint) {} + +} \ No newline at end of file diff --git a/src/common/rendering/gles/gles_buffers.h b/src/common/rendering/gles/gles_buffers.h new file mode 100644 index 0000000000..de51ff31bf --- /dev/null +++ b/src/common/rendering/gles/gles_buffers.h @@ -0,0 +1,78 @@ +#pragma once + +#include "buffers.h" + +#ifdef _MSC_VER +// silence bogus warning C4250: 'GLVertexBuffer': inherits 'GLBuffer::GLBuffer::SetData' via dominance +// According to internet infos, the warning is erroneously emitted in this case. +#pragma warning(disable:4250) +#endif + +namespace OpenGLESRenderer +{ + +class GLBuffer : virtual public IBuffer +{ +protected: + const int mUseType; + unsigned int mBufferId = 0; + int mAllocationSize = 0; + bool mPersistent = false; + bool nomap = true; + + bool isData = false; + char *memory = nullptr; + + GLBuffer(int usetype); + ~GLBuffer(); + void SetData(size_t size, const void *data, bool staticdata) override; + void SetSubData(size_t offset, size_t size, const void *data) override; + void Map() override; + void Unmap() override; + void Resize(size_t newsize) override; + void *Lock(unsigned int size) override; + void Unlock() override; +public: + void Bind(); + void Upload(size_t start, size_t end); +}; + + +class GLVertexBuffer : public IVertexBuffer, public GLBuffer +{ + // If this could use the modern (since GL 4.3) binding system, things would be simpler... :( + struct GLVertexBufferAttribute + { + int bindingpoint; + int format; + int size; + int offset; + }; + + int mNumBindingPoints; + GLVertexBufferAttribute mAttributeInfo[VATTR_MAX] = {}; // Thanks to OpenGL's state system this needs to contain info about every attribute that may ever be in use throughout the entire renderer. + size_t mStride = 0; + +public: + GLVertexBuffer(); + void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) override; + void Bind(int *offsets); +}; + +class GLIndexBuffer : public IIndexBuffer, public GLBuffer +{ +public: + + GLIndexBuffer(); +}; + +class GLDataBuffer : public IDataBuffer, public GLBuffer +{ + int mBindingPoint; +public: + GLDataBuffer(int bindingpoint, bool is_ssbo); + void BindRange(FRenderState* state, size_t start, size_t length); + void BindBase(); +}; + +} \ No newline at end of file diff --git a/src/common/rendering/gles/gles_framebuffer.cpp b/src/common/rendering/gles/gles_framebuffer.cpp new file mode 100644 index 0000000000..496c25d255 --- /dev/null +++ b/src/common/rendering/gles/gles_framebuffer.cpp @@ -0,0 +1,494 @@ +/* +** gl_framebuffer.cpp +** Implementation of the non-hardware specific parts of the +** OpenGL frame buffer +** +**--------------------------------------------------------------------------- +** Copyright 2010-2020 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "gles_system.h" +#include "v_video.h" +#include "m_png.h" +#include "templates.h" +#include "i_time.h" + +#include "gles_framebuffer.h" +#include "gles_renderer.h" +#include "gles_samplers.h" +#include "gles_renderbuffers.h" +#include "hw_clock.h" +#include "hw_vrmodes.h" +#include "hw_skydome.h" +#include "hw_viewpointbuffer.h" +#include "hw_lightbuffer.h" +#include "gles_shaderprogram.h" +#include "r_videoscale.h" +#include "gles_buffers.h" +#include "gles_postprocessstate.h" +#include "v_draw.h" +#include "printf.h" +#include "gles_hwtexture.h" + +#include "flatvertices.h" +#include "hw_cvars.h" + +EXTERN_CVAR (Bool, vid_vsync) +EXTERN_CVAR(Bool, r_drawvoxels) +EXTERN_CVAR(Int, gl_tonemap) +EXTERN_CVAR(Bool, cl_capfps) +EXTERN_CVAR(Int, gl_pipeline_depth); + +EXTERN_CVAR(Bool, gl_sort_textures); + +void Draw2D(F2DDrawer *drawer, FRenderState &state); + +extern bool vid_hdr_active; + +namespace OpenGLESRenderer +{ + FGLRenderer *GLRenderer; + +//========================================================================== +// +// +// +//========================================================================== + +OpenGLFrameBuffer::OpenGLFrameBuffer(void *hMonitor, bool fullscreen) : + Super(hMonitor, fullscreen) +{ + // SetVSync needs to be at the very top to workaround a bug in Nvidia's OpenGL driver. + // If wglSwapIntervalEXT is called after glBindFramebuffer in a frame the setting is not changed! + Super::SetVSync(vid_vsync); + FHardwareTexture::InitGlobalState(); + + // Make sure all global variables tracking OpenGL context state are reset.. + gl_RenderState.Reset(); + + GLRenderer = nullptr; +} + +OpenGLFrameBuffer::~OpenGLFrameBuffer() +{ + PPResource::ResetAll(); + + if (mVertexData != nullptr) delete mVertexData; + if (mSkyData != nullptr) delete mSkyData; + if (mViewpoints != nullptr) delete mViewpoints; + if (mLights != nullptr) delete mLights; + mShadowMap.Reset(); + + if (GLRenderer) + { + delete GLRenderer; + GLRenderer = nullptr; + } +} + +//========================================================================== +// +// Initializes the GL renderer +// +//========================================================================== + +void OpenGLFrameBuffer::InitializeState() +{ + static bool first=true; + + mPipelineNbr = gl_pipeline_depth == 0? 4 : clamp(*gl_pipeline_depth, 1, HW_MAX_PIPELINE_BUFFERS); + mPipelineType = 1; + + InitGLES(); + + // Move some state to the framebuffer object for easier access. + hwcaps = gles.flags; + vendorstring = gles.vendorstring; + + glDepthFunc(GL_LESS); + + glEnable(GL_DITHER); + glDisable(GL_CULL_FACE); + glDisable(GL_POLYGON_OFFSET_FILL); + + glEnable(GL_BLEND); + + glDisable(GL_DEPTH_TEST); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + glClearDepthf(1.0f); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + SetViewportRects(nullptr); + + mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight(), mPipelineNbr); + mSkyData = new FSkyVertexBuffer; + mViewpoints = new HWViewpointBuffer(mPipelineNbr); + mLights = new FLightBuffer(mPipelineNbr); + GLRenderer = new FGLRenderer(this); + GLRenderer->Initialize(GetWidth(), GetHeight()); + static_cast(mLights->GetBuffer())->BindBase(); +} + +//========================================================================== +// +// Updates the screen +// +//========================================================================== + +void OpenGLFrameBuffer::Update() +{ + twoD.Reset(); + Flush3D.Reset(); + + Flush3D.Clock(); + GLRenderer->Flush(); + Flush3D.Unclock(); + + Swap(); + Super::Update(); +} + +void OpenGLFrameBuffer::CopyScreenToBuffer(int width, int height, uint8_t* scr) +{ + IntRect bounds; + bounds.left = 0; + bounds.top = 0; + bounds.width = width; + bounds.height = height; + GLRenderer->CopyToBackbuffer(&bounds, false); + + // strictly speaking not needed as the glReadPixels should block until the scene is rendered, but this is to safeguard against shitty drivers + glFinish(); + glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, scr); +} + +//=========================================================================== +// +// Camera texture rendering +// +//=========================================================================== + +void OpenGLFrameBuffer::RenderTextureView(FCanvasTexture* tex, std::function renderFunc) +{ + GLRenderer->StartOffscreen(); + GLRenderer->BindToFrameBuffer(tex); + + IntRect bounds; + bounds.left = bounds.top = 0; + bounds.width = FHardwareTexture::GetTexDimension(tex->GetWidth()); + bounds.height = FHardwareTexture::GetTexDimension(tex->GetHeight()); + + renderFunc(bounds); + GLRenderer->EndOffscreen(); + + tex->SetUpdated(true); + static_cast(screen)->camtexcount++; +} + +//=========================================================================== +// +// +// +//=========================================================================== + +const char* OpenGLFrameBuffer::DeviceName() const +{ + return gles.modelstring; +} + +//========================================================================== +// +// Swap the buffers +// +//========================================================================== + + +void OpenGLFrameBuffer::Swap() +{ + + Finish.Reset(); + Finish.Clock(); + + + FPSLimit(); + SwapBuffers(); + + mVertexData->NextPipelineBuffer(); + + RenderState()->SetVertexBuffer(screen->mVertexData); // Needed for Raze because it does not reset it + + Finish.Unclock(); + camtexcount = 0; + FHardwareTexture::UnbindAll(); + gl_RenderState.ClearLastMaterial(); +} + +//========================================================================== +// +// Enable/disable vertical sync +// +//========================================================================== + +void OpenGLFrameBuffer::SetVSync(bool vsync) +{ + Super::SetVSync(vsync); +} + +//=========================================================================== +// +// +//=========================================================================== + +void OpenGLFrameBuffer::SetTextureFilterMode() +{ + if (GLRenderer != nullptr && GLRenderer->mSamplerManager != nullptr) GLRenderer->mSamplerManager->SetTextureFilterMode(); +} + +IHardwareTexture *OpenGLFrameBuffer::CreateHardwareTexture(int numchannels) +{ + return new FHardwareTexture(numchannels); +} + +void OpenGLFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation) +{ + if (mat->Source()->GetUseType() == ETextureType::SWCanvas) return; + + int flags = mat->GetScaleFlags(); + int numLayers = mat->NumLayers(); + MaterialLayerInfo* layer; + auto base = static_cast(mat->GetLayer(0, translation, &layer)); + + if (base->BindOrCreate(layer->layerTexture, 0, CLAMP_NONE, translation, layer->scaleFlags)) + { + for (int i = 1; i < numLayers; i++) + { + auto systex = static_cast(mat->GetLayer(i, 0, &layer)); + systex->BindOrCreate(layer->layerTexture, i, CLAMP_NONE, 0, layer->scaleFlags); + } + } + // unbind everything. + FHardwareTexture::UnbindAll(); + gl_RenderState.ClearLastMaterial(); +} + +IVertexBuffer *OpenGLFrameBuffer::CreateVertexBuffer() +{ + return new GLVertexBuffer; +} + +IIndexBuffer *OpenGLFrameBuffer::CreateIndexBuffer() +{ + return new GLIndexBuffer; +} + +IDataBuffer *OpenGLFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) +{ + return new GLDataBuffer(bindingpoint, ssbo); +} + + +void OpenGLFrameBuffer::SetViewportRects(IntRect *bounds) +{ + Super::SetViewportRects(bounds); + if (!bounds) + { + auto vrmode = VRMode::GetVRMode(true); + vrmode->AdjustViewport(this); + } +} + + +FRenderState* OpenGLFrameBuffer::RenderState() +{ + return &gl_RenderState; +} + + +void OpenGLFrameBuffer::FirstEye() +{ + //GLRenderer->mBuffers->CurrentEye() = 0; // always begin at zero, in case eye count changed +} + +void OpenGLFrameBuffer::NextEye(int eyecount) +{ + //GLRenderer->mBuffers->NextEye(eyecount); +} + +void OpenGLFrameBuffer::SetSceneRenderTarget(bool useSSAO) +{ +#ifndef NO_RENDER_BUFFER + GLRenderer->mBuffers->BindSceneFB(useSSAO); +#endif +} + + + +void OpenGLFrameBuffer::WaitForCommands(bool finish) +{ + glFinish(); +} + + +//=========================================================================== +// +// +// +//=========================================================================== + +void OpenGLFrameBuffer::BeginFrame() +{ + SetViewportRects(nullptr); + if (GLRenderer != nullptr) + GLRenderer->BeginFrame(); +} + +//=========================================================================== +// +// Takes a screenshot +// +//=========================================================================== + +TArray OpenGLFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) +{ + const auto &viewport = mOutputLetterbox; + + // Grab what is in the back buffer. + // We cannot rely on SCREENWIDTH/HEIGHT here because the output may have been scaled. + TArray pixels; + pixels.Resize(viewport.width * viewport.height * 3); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glReadPixels(viewport.left, viewport.top, viewport.width, viewport.height, GL_RGB, GL_UNSIGNED_BYTE, &pixels[0]); + glPixelStorei(GL_PACK_ALIGNMENT, 4); + + // Copy to screenshot buffer: + int w = SCREENWIDTH; + int h = SCREENHEIGHT; + + TArray ScreenshotBuffer(w * h * 3, true); + + float rcpWidth = 1.0f / w; + float rcpHeight = 1.0f / h; + for (int y = 0; y < h; y++) + { + for (int x = 0; x < w; x++) + { + float u = (x + 0.5f) * rcpWidth; + float v = (y + 0.5f) * rcpHeight; + int sx = u * viewport.width; + int sy = v * viewport.height; + int sindex = (sx + sy * viewport.width) * 3; + int dindex = (x + (h - y - 1) * w) * 3; + ScreenshotBuffer[dindex] = pixels[sindex]; + ScreenshotBuffer[dindex + 1] = pixels[sindex + 1]; + ScreenshotBuffer[dindex + 2] = pixels[sindex + 2]; + } + } + + pitch = w * 3; + color_type = SS_RGB; + + // Screenshot should not use gamma correction if it was already applied to rendered image + gamma = 1; + if (vid_hdr_active && vid_fullscreen) + gamma *= 2.2f; + return ScreenshotBuffer; +} + +//=========================================================================== +// +// 2D drawing +// +//=========================================================================== + +void OpenGLFrameBuffer::Draw2D() +{ + if (GLRenderer != nullptr) + { + GLRenderer->mBuffers->BindCurrentFB(); + ::Draw2D(twod, gl_RenderState); + } +} + +void OpenGLFrameBuffer::PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) +{ + //if (!swscene) GLRenderer->mBuffers->BlitSceneToTexture(); // Copy the resulting scene to the current post process texture + GLRenderer->PostProcessScene(fixedcm, flash, afterBloomDrawEndScene2D); +} + +//========================================================================== +// +// OpenGLFrameBuffer :: WipeStartScreen +// +// Called before the current screen has started rendering. This needs to +// save what was drawn the previous frame so that it can be animated into +// what gets drawn this frame. +// +//========================================================================== + +FTexture *OpenGLFrameBuffer::WipeStartScreen() +{ + const auto &viewport = screen->mScreenViewport; + + auto tex = new FWrapperTexture(viewport.width, viewport.height, 1); + tex->GetSystemTexture()->CreateTexture(nullptr, viewport.width, viewport.height, 0, false, "WipeStartScreen"); + glFinish(); + static_cast(tex->GetSystemTexture())->Bind(0, false); + + GLRenderer->mBuffers->BindCurrentFB(); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height); + return tex; +} + +//========================================================================== +// +// OpenGLFrameBuffer :: WipeEndScreen +// +// The screen we want to animate to has just been drawn. +// +//========================================================================== + +FTexture *OpenGLFrameBuffer::WipeEndScreen() +{ + GLRenderer->Flush(); + const auto &viewport = screen->mScreenViewport; + auto tex = new FWrapperTexture(viewport.width, viewport.height, 1); + tex->GetSystemTexture()->CreateTexture(NULL, viewport.width, viewport.height, 0, false, "WipeEndScreen"); + glFinish(); + static_cast(tex->GetSystemTexture())->Bind(0, false); + GLRenderer->mBuffers->BindCurrentFB(); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, viewport.left, viewport.top, viewport.width, viewport.height); + return tex; +} + +} diff --git a/src/common/rendering/gles/gles_framebuffer.h b/src/common/rendering/gles/gles_framebuffer.h new file mode 100644 index 0000000000..25626c6592 --- /dev/null +++ b/src/common/rendering/gles/gles_framebuffer.h @@ -0,0 +1,73 @@ +#ifndef __GLES_FRAMEBUFFER +#define __GLES_FRAMEBUFFER + +#include "gl_sysfb.h" +#include "m_png.h" + +#include + +namespace OpenGLESRenderer +{ + +class FHardwareTexture; +class FGLDebug; + +class OpenGLFrameBuffer : public SystemGLFrameBuffer +{ + typedef SystemGLFrameBuffer Super; + + void RenderTextureView(FCanvasTexture* tex, std::function renderFunc) override; + +public: + + explicit OpenGLFrameBuffer() {} + OpenGLFrameBuffer(void *hMonitor, bool fullscreen) ; + ~OpenGLFrameBuffer(); + + void InitializeState() override; + void Update() override; + + void FirstEye() override; + void NextEye(int eyecount) override; + void SetSceneRenderTarget(bool useSSAO) override; + void WaitForCommands(bool finish) override; + void CopyScreenToBuffer(int width, int height, uint8_t* buffer) override; + bool FlipSavePic() const override { return true; } + + FRenderState* RenderState() override; + + const char* DeviceName() const override; + void SetTextureFilterMode() override; + IHardwareTexture *CreateHardwareTexture(int numchannels) override; + void PrecacheMaterial(FMaterial *mat, int translation) override; + void BeginFrame() override; + void SetViewportRects(IntRect *bounds) override; + IVertexBuffer *CreateVertexBuffer() override; + IIndexBuffer *CreateIndexBuffer() override; + IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override; + + // Retrieves a buffer containing image data for a screenshot. + // Hint: Pitch can be negative for upside-down images, in which case buffer + // points to the last row in the buffer, which will be the first row output. + virtual TArray GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) override; + + void Swap(); + bool IsHWGammaActive() const { return HWGammaActive; } + + void SetVSync(bool vsync) override; + + void Draw2D() override; + void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) override; + + bool HWGammaActive = false; // Are we using hardware or software gamma? + std::shared_ptr mDebug; // Debug API + + FTexture *WipeStartScreen() override; + FTexture *WipeEndScreen() override; + + int camtexcount = 0; +}; + +} + +#endif //__GL_FRAMEBUFFER diff --git a/src/common/rendering/gles/gles_hwtexture.cpp b/src/common/rendering/gles/gles_hwtexture.cpp new file mode 100644 index 0000000000..5ce937b10d --- /dev/null +++ b/src/common/rendering/gles/gles_hwtexture.cpp @@ -0,0 +1,299 @@ +/* +** gl_hwtexture.cpp +** GL texture abstraction +** +**--------------------------------------------------------------------------- +** Copyright 2019 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +** +*/ + +#include "gles_system.h" +#include "templates.h" +#include "c_cvars.h" +#include "hw_material.h" + +#include "hw_cvars.h" +#include "gles_renderer.h" +#include "gles_samplers.h" +#include "gles_renderstate.h" +#include "gles_hwtexture.h" + +namespace OpenGLESRenderer +{ + + +TexFilter_s TexFilter[] = { + {GL_NEAREST, GL_NEAREST, false}, + {GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST, true}, + {GL_LINEAR, GL_LINEAR, false}, + {GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR, true}, + {GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, true}, + {GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST, true}, + {GL_LINEAR_MIPMAP_LINEAR, GL_NEAREST, true}, +}; + +//=========================================================================== +// +// Static texture data +// +//=========================================================================== +unsigned int FHardwareTexture::lastbound[FHardwareTexture::MAX_TEXTURES]; + +//=========================================================================== +// +// Loads the texture image into the hardware +// +// NOTE: For some strange reason I was unable to find the source buffer +// should be one line higher than the actual texture. I got extremely +// strange crashes deep inside the GL driver when I didn't do it! +// +//=========================================================================== + +unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, const char *name) +{ + int rh,rw; + int texformat = GL_RGBA;// TexFormat[gl_texture_format]; + bool deletebuffer=false; + + /* + if (forcenocompression) + { + texformat = GL_RGBA8; + } + */ + bool firstCall = glTexID == 0; + if (firstCall) + { + glGenTextures(1, &glTexID); + } + + int textureBinding = UINT_MAX; + if (texunit == -1) glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding); + if (texunit > 0) glActiveTexture(GL_TEXTURE0+texunit); + if (texunit >= 0) lastbound[texunit] = glTexID; + glBindTexture(GL_TEXTURE_2D, glTexID); + + + rw = GetTexDimension(w); + rh = GetTexDimension(h); + + if (!buffer) + { + // The texture must at least be initialized if no data is present. + mipmapped = false; + buffer=(unsigned char *)calloc(4,rw * (rh+1)); + deletebuffer=true; + //texheight=-h; + } + else + { + if (rw < w || rh < h) + { + // The texture is larger than what the hardware can handle so scale it down. + unsigned char * scaledbuffer=(unsigned char *)calloc(4,rw * (rh+1)); + if (scaledbuffer) + { + Resize(w, h, rw, rh, buffer, scaledbuffer); + deletebuffer=true; + buffer=scaledbuffer; + } + } + + + } + // store the physical size. + + int sourcetype; + + +#if USE_GLES2 + sourcetype = GL_BGRA; + texformat = GL_BGRA; +#else + sourcetype = GL_BGRA; + texformat = GL_RGBA; +#endif + glTexImage2D(GL_TEXTURE_2D, 0, texformat, rw, rh, 0, sourcetype, GL_UNSIGNED_BYTE, buffer); + + if (deletebuffer && buffer) free(buffer); + + if (mipmap && TexFilter[gl_texture_filter].mipmapping) + { + glGenerateMipmap(GL_TEXTURE_2D); + mipmapped = true; + } + + if (texunit > 0) glActiveTexture(GL_TEXTURE0); + else if (texunit == -1) glBindTexture(GL_TEXTURE_2D, textureBinding); + return glTexID; +} + + + +//=========================================================================== +// +// Destroys the texture +// +//=========================================================================== +FHardwareTexture::~FHardwareTexture() +{ + if (glTexID != 0) glDeleteTextures(1, &glTexID); +} + + +//=========================================================================== +// +// Binds this patch +// +//=========================================================================== +unsigned int FHardwareTexture::Bind(int texunit, bool needmipmap) +{ + if (glTexID != 0) + { + if (lastbound[texunit] == glTexID) return glTexID; + lastbound[texunit] = glTexID; + if (texunit != 0) glActiveTexture(GL_TEXTURE0 + texunit); + glBindTexture(GL_TEXTURE_2D, glTexID); + // Check if we need mipmaps on a texture that was creted without them. + if (needmipmap && !mipmapped && TexFilter[gl_texture_filter].mipmapping) + { + glGenerateMipmap(GL_TEXTURE_2D); + mipmapped = true; + } + if (texunit != 0) glActiveTexture(GL_TEXTURE0); + return glTexID; + } + return 0; +} + +void FHardwareTexture::Unbind(int texunit) +{ + if (lastbound[texunit] != 0) + { + if (texunit != 0) glActiveTexture(GL_TEXTURE0+texunit); + glBindTexture(GL_TEXTURE_2D, 0); + if (texunit != 0) glActiveTexture(GL_TEXTURE0); + lastbound[texunit] = 0; + } +} + +void FHardwareTexture::UnbindAll() +{ + for(int texunit = 0; texunit < 16; texunit++) + { + Unbind(texunit); + } +} + +//=========================================================================== +// +// Creates a depth buffer for this texture +// +//=========================================================================== + +int FHardwareTexture::GetDepthBuffer(int width, int height) +{ + if (glDepthID == 0) + { + glGenRenderbuffers(1, &glDepthID); + glBindRenderbuffer(GL_RENDERBUFFER, glDepthID); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, + GetTexDimension(width), GetTexDimension(height)); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + return glDepthID; +} + + +//=========================================================================== +// +// Binds this texture's surfaces to the current framrbuffer +// +//=========================================================================== + +void FHardwareTexture::BindToFrameBuffer(int width, int height) +{ + width = GetTexDimension(width); + height = GetTexDimension(height); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, glTexID, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, GetDepthBuffer(width, height)); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, GetDepthBuffer(width, height)); +} + + +//=========================================================================== +// +// Binds a texture to the renderer +// +//=========================================================================== + +bool FHardwareTexture::BindOrCreate(FTexture *tex, int texunit, int clampmode, int translation, int flags) +{ + int usebright = false; + + bool needmipmap = (clampmode <= CLAMP_XY) && !forcenofilter; + + // Bind it to the system. + if (!Bind(texunit, needmipmap)) + { + if (flags & CTF_Indexed) + { + glTextureBytes = 1; + forcenofilter = true; + needmipmap = false; + } + int w = 0, h = 0; + + // Create this texture + + FTextureBuffer texbuffer; + + if (!tex->isHardwareCanvas()) + { + texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData); + w = texbuffer.mWidth; + h = texbuffer.mHeight; + } + else + { + w = tex->GetWidth(); + h = tex->GetHeight(); + } + if (!CreateTexture(texbuffer.mBuffer, w, h, texunit, needmipmap, "FHardwareTexture.BindOrCreate")) + { + // could not create texture + return false; + } + } + if (forcenofilter && clampmode <= CLAMP_XY) clampmode += CLAMP_NOFILTER - CLAMP_NONE; + GLRenderer->mSamplerManager->Bind(texunit, clampmode, 255); + return true; +} + +} diff --git a/src/common/rendering/gles/gles_hwtexture.h b/src/common/rendering/gles/gles_hwtexture.h new file mode 100644 index 0000000000..8ff673de7e --- /dev/null +++ b/src/common/rendering/gles/gles_hwtexture.h @@ -0,0 +1,79 @@ +#pragma once +class FBitmap; +class FTexture; + +#include "tarray.h" +#include "hw_ihwtexture.h" + + +#ifdef LoadImage +#undef LoadImage +#endif + +#define SHADED_TEXTURE -1 +#define DIRECT_PALETTE -2 + +#include "tarray.h" +#include "gles_system.h" +#include "hw_ihwtexture.h" + +class FCanvasTexture; + +namespace OpenGLESRenderer +{ + +class FHardwareTexture : public IHardwareTexture +{ +public: + + static unsigned int lastbound[MAX_TEXTURES]; + + static int GetTexDimension(int value) + { + if (value > gles.max_texturesize) return gles.max_texturesize; + return value; + } + + static void InitGlobalState() { for (int i = 0; i < MAX_TEXTURES; i++) lastbound[i] = 0; } + +private: + + bool forcenofilter; + + unsigned int glTexID = 0; + unsigned int glDepthID = 0; // only used by camera textures + int glTextureBytes; + bool mipmapped = false; + + int GetDepthBuffer(int w, int h); + +public: + FHardwareTexture(int numchannels = 4, bool disablefilter = false) + { + forcenofilter = disablefilter; + glTextureBytes = numchannels; + } + + ~FHardwareTexture(); + + static void Unbind(int texunit); + static void UnbindAll(); + + void BindToFrameBuffer(int w, int h); + + unsigned int Bind(int texunit, bool needmipmap); + bool BindOrCreate(FTexture* tex, int texunit, int clampmode, int translation, int flags); + + void AllocateBuffer(int w, int h, int texelsize) {} // Not used + uint8_t* MapBuffer() { return 0; } // Not used + + unsigned int CreateTexture(unsigned char* buffer, int w, int h, int texunit, bool mipmap, const char* name); + unsigned int GetTextureHandle() + { + return glTexID; + } + + int numChannels() { return glTextureBytes; } +}; + +} diff --git a/src/common/rendering/gles/gles_postprocess.cpp b/src/common/rendering/gles/gles_postprocess.cpp new file mode 100644 index 0000000000..a618c3b2e9 --- /dev/null +++ b/src/common/rendering/gles/gles_postprocess.cpp @@ -0,0 +1,225 @@ +/* +** Postprocessing framework +** Copyright (c) 2016-2020 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "gles_system.h" +#include "m_png.h" +#include "gles_buffers.h" +#include "gles_framebuffer.h" +#include "gles_renderbuffers.h" +#include "gles_renderer.h" +#include "gles_postprocessstate.h" +#include "gles_shaderprogram.h" +#include "hwrenderer/postprocessing/hw_postprocess.h" +#include "hwrenderer/postprocessing/hw_postprocess_cvars.h" +#include "flatvertices.h" +#include "r_videoscale.h" +#include "v_video.h" +#include "templates.h" +#include "hw_vrmodes.h" +#include "v_draw.h" + +extern bool vid_hdr_active; + + +namespace OpenGLESRenderer +{ + +int gl_dither_bpc = -1; + +void FGLRenderer::RenderScreenQuad() +{ + auto buffer = static_cast(screen->mVertexData->GetBufferObjects().first); + buffer->Bind(nullptr); + glDrawArrays(GL_TRIANGLE_STRIP, FFlatVertexBuffer::PRESENT_INDEX, 3); +} + +void FGLRenderer::PostProcessScene(int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D) +{ +#ifndef NO_RENDER_BUFFER + mBuffers->BindCurrentFB(); +#endif + if (afterBloomDrawEndScene2D) afterBloomDrawEndScene2D(); +} + + + +//----------------------------------------------------------------------------- +// +// Copies the rendered screen to its final destination +// +//----------------------------------------------------------------------------- + +void FGLRenderer::Flush() +{ + CopyToBackbuffer(nullptr, true); +} + +//----------------------------------------------------------------------------- +// +// Gamma correct while copying to frame buffer +// +//----------------------------------------------------------------------------- + +void FGLRenderer::CopyToBackbuffer(const IntRect *bounds, bool applyGamma) +{ +#ifdef NO_RENDER_BUFFER + mBuffers->BindOutputFB(); +#endif + screen->Draw2D(); // draw all pending 2D stuff before copying the buffer + twod->Clear(); + + FGLPostProcessState savedState; + savedState.SaveTextureBindings(2); + + mBuffers->BindOutputFB(); + + IntRect box; + if (bounds) + { + box = *bounds; + } + else + { + ClearBorders(); + box = screen->mOutputLetterbox; + } + + mBuffers->BindCurrentTexture(0); +#ifndef NO_RENDER_BUFFER + DrawPresentTexture(box, applyGamma); +#endif +} + +void FGLRenderer::DrawPresentTexture(const IntRect &box, bool applyGamma) +{ + glViewport(box.left, box.top, box.width, box.height); + + mBuffers->BindDitherTexture(1); + + glActiveTexture(GL_TEXTURE0); + if (ViewportLinearScale()) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + } + + mPresentShader->Bind(); + if (!applyGamma || framebuffer->IsHWGammaActive()) + { + mPresentShader->Uniforms->InvGamma = 1.0f; + mPresentShader->Uniforms->Contrast = 1.0f; + mPresentShader->Uniforms->Brightness = 0.0f; + mPresentShader->Uniforms->Saturation = 1.0f; + } + else + { + mPresentShader->Uniforms->InvGamma = 1.0f / clamp(vid_gamma, 0.1f, 4.f); + mPresentShader->Uniforms->Contrast = clamp(vid_contrast, 0.1f, 3.f); + mPresentShader->Uniforms->Brightness = clamp(vid_brightness, -0.8f, 0.8f); + mPresentShader->Uniforms->Saturation = clamp(vid_saturation, -15.0f, 15.f); + mPresentShader->Uniforms->GrayFormula = static_cast(gl_satformula); + } + if (vid_hdr_active && framebuffer->IsFullscreen()) + { + // Full screen exclusive mode treats a rgba16f frame buffer as linear. + // It probably will eventually in desktop mode too, but the DWM doesn't seem to support that. + mPresentShader->Uniforms->HdrMode = 1; + mPresentShader->Uniforms->ColorScale = (gl_dither_bpc == -1) ? 1023.0f : (float)((1 << gl_dither_bpc) - 1); + } + else + { + mPresentShader->Uniforms->HdrMode = 0; + mPresentShader->Uniforms->ColorScale = (gl_dither_bpc == -1) ? 255.0f : (float)((1 << gl_dither_bpc) - 1); + } + mPresentShader->Uniforms->Scale = { screen->mScreenViewport.width / (float)mBuffers->GetWidth(), screen->mScreenViewport.height / (float)mBuffers->GetHeight() }; + mPresentShader->Uniforms->Offset = { 0.0f, 0.0f }; + mPresentShader->Uniforms.SetData(); + + + for (int n = 0; n < mPresentShader->Uniforms.mFields.size(); n++) + { + int index = -1; + UniformFieldDesc desc = mPresentShader->Uniforms.mFields[n]; + int loc = mPresentShader->Uniforms.UniformLocation[n]; + switch (desc.Type) + { + case UniformType::Int: + glUniform1i(loc, *((GLint*)(((char*)(&mPresentShader->Uniforms)) + desc.Offset))); + break; + case UniformType::Float: + glUniform1f(loc, *((GLfloat*)(((char*)(&mPresentShader->Uniforms)) + desc.Offset))); + break; + case UniformType::Vec2: + glUniform2fv(loc,1 , ((GLfloat*)(((char*)(&mPresentShader->Uniforms)) + desc.Offset))); + break; + } + } + + RenderScreenQuad(); +} + +//----------------------------------------------------------------------------- +// +// Fills the black bars around the screen letterbox +// +//----------------------------------------------------------------------------- + +void FGLRenderer::ClearBorders() +{ + const auto &box = screen->mOutputLetterbox; + + int clientWidth = framebuffer->GetClientWidth(); + int clientHeight = framebuffer->GetClientHeight(); + if (clientWidth == 0 || clientHeight == 0) + return; + + glViewport(0, 0, clientWidth, clientHeight); + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glEnable(GL_SCISSOR_TEST); + if (box.top > 0) + { + glScissor(0, 0, clientWidth, box.top); + glClear(GL_COLOR_BUFFER_BIT); + } + if (clientHeight - box.top - box.height > 0) + { + glScissor(0, box.top + box.height, clientWidth, clientHeight - box.top - box.height); + glClear(GL_COLOR_BUFFER_BIT); + } + if (box.left > 0) + { + glScissor(0, box.top, box.left, box.height); + glClear(GL_COLOR_BUFFER_BIT); + } + if (clientWidth - box.left - box.width > 0) + { + glScissor(box.left + box.width, box.top, clientWidth - box.left - box.width, box.height); + glClear(GL_COLOR_BUFFER_BIT); + } + glDisable(GL_SCISSOR_TEST); +} + +} \ No newline at end of file diff --git a/src/common/rendering/gles/gles_postprocessstate.cpp b/src/common/rendering/gles/gles_postprocessstate.cpp new file mode 100644 index 0000000000..2164061258 --- /dev/null +++ b/src/common/rendering/gles/gles_postprocessstate.cpp @@ -0,0 +1,118 @@ +/* +** Postprocessing framework +** Copyright (c) 2016-2020 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "templates.h" +#include "gles_system.h" +#include "gles_postprocessstate.h" + +namespace OpenGLESRenderer +{ + +//----------------------------------------------------------------------------- +// +// Saves state modified by post processing shaders +// +//----------------------------------------------------------------------------- + +FGLPostProcessState::FGLPostProcessState() +{ + glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex); + glActiveTexture(GL_TEXTURE0); + SaveTextureBindings(1); + + glGetBooleanv(GL_BLEND, &blendEnabled); + glGetBooleanv(GL_SCISSOR_TEST, &scissorEnabled); + glGetBooleanv(GL_DEPTH_TEST, &depthEnabled); + glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProgram); + glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRgb); + glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha); + glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRgb); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha); + glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRgb); + glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha); + + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); +} + +void FGLPostProcessState::SaveTextureBindings(unsigned int numUnits) +{ + while (textureBinding.Size() < numUnits) + { + unsigned int i = textureBinding.Size(); + + GLint texture; + glActiveTexture(GL_TEXTURE0 + i); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture); + glBindTexture(GL_TEXTURE_2D, 0); + textureBinding.Push(texture); + } + glActiveTexture(GL_TEXTURE0); +} + +//----------------------------------------------------------------------------- +// +// Restores state at the end of post processing +// +//----------------------------------------------------------------------------- + +FGLPostProcessState::~FGLPostProcessState() +{ + if (blendEnabled) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); + + if (scissorEnabled) + glEnable(GL_SCISSOR_TEST); + else + glDisable(GL_SCISSOR_TEST); + + if (depthEnabled) + glEnable(GL_DEPTH_TEST); + else + glDisable(GL_DEPTH_TEST); + + + glBlendEquationSeparate(blendEquationRgb, blendEquationAlpha); + glBlendFuncSeparate(blendSrcRgb, blendDestRgb, blendSrcAlpha, blendDestAlpha); + + glUseProgram(currentProgram); + + // Fully unbind to avoid incomplete texture warnings from Nvidia's driver when gl_debug_level 4 is active + for (unsigned int i = 0; i < textureBinding.Size(); i++) + { + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, 0); + } + + + for (unsigned int i = 0; i < textureBinding.Size(); i++) + { + glActiveTexture(GL_TEXTURE0 + i); + glBindTexture(GL_TEXTURE_2D, textureBinding[i]); + } + + glActiveTexture(activeTex); +} + +} \ No newline at end of file diff --git a/src/common/rendering/gles/gles_postprocessstate.h b/src/common/rendering/gles/gles_postprocessstate.h new file mode 100644 index 0000000000..1a5ec760f1 --- /dev/null +++ b/src/common/rendering/gles/gles_postprocessstate.h @@ -0,0 +1,40 @@ +#ifndef __GL_POSTPROCESSSTATE_H +#define __GL_POSTPROCESSSTATE_H + +#include +#include "matrix.h" +#include "c_cvars.h" + +namespace OpenGLESRenderer +{ + +class FGLPostProcessState +{ +public: + FGLPostProcessState(); + ~FGLPostProcessState(); + + void SaveTextureBindings(unsigned int numUnits); + +private: + FGLPostProcessState(const FGLPostProcessState &) = delete; + FGLPostProcessState &operator=(const FGLPostProcessState &) = delete; + + GLint activeTex; + TArray textureBinding; + TArray samplerBinding; + GLboolean blendEnabled; + GLboolean scissorEnabled; + GLboolean depthEnabled; + GLboolean multisampleEnabled; + GLint currentProgram; + GLint blendEquationRgb; + GLint blendEquationAlpha; + GLint blendSrcRgb; + GLint blendSrcAlpha; + GLint blendDestRgb; + GLint blendDestAlpha; +}; + +} +#endif diff --git a/src/common/rendering/gles/gles_renderbuffers.cpp b/src/common/rendering/gles/gles_renderbuffers.cpp new file mode 100644 index 0000000000..91f8ce4620 --- /dev/null +++ b/src/common/rendering/gles/gles_renderbuffers.cpp @@ -0,0 +1,433 @@ +/* +** Postprocessing framework +** Copyright (c) 2016-2020 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "gles_system.h" +#include "v_video.h" +#include "printf.h" +#include "hw_cvars.h" +#include "gles_renderer.h" +#include "gles_renderbuffers.h" +#include "gles_postprocessstate.h" +#include "gles_shaderprogram.h" +#include "gles_buffers.h" +#include "templates.h" +#include + +EXTERN_CVAR(Int, gl_debug_level) + +namespace OpenGLESRenderer +{ + + //========================================================================== + // + // Initialize render buffers and textures used in rendering passes + // + //========================================================================== + + FGLRenderBuffers::FGLRenderBuffers() + { + + } + + //========================================================================== + // + // Free render buffer resources + // + //========================================================================== + + FGLRenderBuffers::~FGLRenderBuffers() + { + ClearScene(); + + DeleteTexture(mDitherTexture); + } + + void FGLRenderBuffers::ClearScene() + { + DeleteFrameBuffer(mSceneFB); + DeleteRenderBuffer(mSceneDepthStencilBuf); + DeleteRenderBuffer(mSceneStencilBuf); + } + + void FGLRenderBuffers::DeleteTexture(PPGLTexture& tex) + { + if (tex.handle != 0) + glDeleteTextures(1, &tex.handle); + tex.handle = 0; + } + + void FGLRenderBuffers::DeleteRenderBuffer(PPGLRenderBuffer& buf) + { + if (buf.handle != 0) + glDeleteRenderbuffers(1, &buf.handle); + buf.handle = 0; + } + + void FGLRenderBuffers::DeleteFrameBuffer(PPGLFrameBuffer& fb) + { + if (fb.handle != 0) + glDeleteFramebuffers(1, &fb.handle); + fb.handle = 0; + } + + //========================================================================== + // + // Makes sure all render buffers have sizes suitable for rending at the + // specified resolution + // + //========================================================================== + + void FGLRenderBuffers::Setup(int width, int height, int sceneWidth, int sceneHeight) + { + if (width <= 0 || height <= 0) + I_FatalError("Requested invalid render buffer sizes: screen = %dx%d", width, height); + + GLint activeTex; + GLint textureBinding; + glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTex); + glActiveTexture(GL_TEXTURE0); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &textureBinding); + + if (width != mWidth || height != mHeight) + CreatePipeline(width, height); + + if (width != mWidth || height != mHeight ) + CreateScene(width, height); + + mWidth = width; + mHeight = height; + mSceneWidth = sceneWidth; + mSceneHeight = sceneHeight; + + glBindTexture(GL_TEXTURE_2D, textureBinding); + glActiveTexture(activeTex); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + if (FailedCreate) + { + ClearScene(); + mWidth = 0; + mHeight = 0; + mSceneWidth = 0; + mSceneHeight = 0; + I_FatalError("Unable to create render buffers."); + } + } + + //========================================================================== + // + // Creates the scene buffers + // + //========================================================================== + + void FGLRenderBuffers::CreateScene(int width, int height) + { + ClearScene(); + if(gles.depthStencilAvailable) + mSceneDepthStencilBuf = CreateRenderBuffer("SceneDepthStencil", GL_DEPTH24_STENCIL8, width, height); + else + { + mSceneDepthStencilBuf = CreateRenderBuffer("SceneDepthStencil", GL_DEPTH_COMPONENT16, width, height); + mSceneStencilBuf = CreateRenderBuffer("SceneStencil", GL_STENCIL_INDEX8, width, height); + } + mSceneFB= CreateFrameBuffer("SceneFB", mSceneTex, mSceneDepthStencilBuf, mSceneStencilBuf); + } + + //========================================================================== + // + // Creates the buffers needed for post processing steps + // + //========================================================================== + + void FGLRenderBuffers::CreatePipeline(int width, int height) + { + mSceneTex = Create2DTexture("PipelineTexture", GL_RGBA, width, height); + } + + + + //========================================================================== + // + // Creates a 2D texture defaulting to linear filtering and clamp to edge + // + //========================================================================== + + PPGLTexture FGLRenderBuffers::Create2DTexture(const char* name, GLuint format, int width, int height, const void* data) + { + PPGLTexture tex; + tex.Width = width; + tex.Height = height; + glGenTextures(1, &tex.handle); + glBindTexture(GL_TEXTURE_2D, tex.handle); + + GLenum dataformat = 0, datatype = 0; + /* + switch (format) + { + case GL_RGBA: dataformat = GL_RGBA; datatype = GL_UNSIGNED_BYTE; break; + + case GL_RGBA16: dataformat = GL_RGBA; datatype = GL_UNSIGNED_SHORT; break; + case GL_RGBA16F: dataformat = GL_RGBA; datatype = GL_FLOAT; break; + case GL_RGBA32F: dataformat = GL_RGBA; datatype = GL_FLOAT; break; + case GL_RGBA16_SNORM: dataformat = GL_RGBA; datatype = GL_SHORT; break; + case GL_R32F: dataformat = GL_RED; datatype = GL_FLOAT; break; + case GL_R16F: dataformat = GL_RED; datatype = GL_FLOAT; break; + case GL_RG32F: dataformat = GL_RG; datatype = GL_FLOAT; break; + case GL_RG16F: dataformat = GL_RG; datatype = GL_FLOAT; break; + case GL_RGB10_A2: dataformat = GL_RGBA; datatype = GL_UNSIGNED_INT_10_10_10_2; break; + case GL_DEPTH_COMPONENT24: dataformat = GL_DEPTH_COMPONENT; datatype = GL_FLOAT; break; + + case GL_STENCIL_INDEX8: dataformat = GL_STENCIL_INDEX8_OES; datatype = GL_INT; break; + case GL_DEPTH24_STENCIL8_OES: dataformat = GL_DEPTH_STENCIL_OES; datatype = GL_UNSIGNED_INT_24_8; break; + default: I_FatalError("Unknown format passed to FGLRenderBuffers.Create2DTexture"); + } + */ + format = GL_RGBA; + dataformat = GL_RGBA; + datatype = GL_UNSIGNED_BYTE; + + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, dataformat, datatype, data); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + return tex; + } + + //========================================================================== + // + // Creates a render buffer + // + //========================================================================== + + PPGLRenderBuffer FGLRenderBuffers::CreateRenderBuffer(const char* name, GLuint format, int width, int height) + { + PPGLRenderBuffer buf; + glGenRenderbuffers(1, &buf.handle); + glBindRenderbuffer(GL_RENDERBUFFER, buf.handle); + + glRenderbufferStorage(GL_RENDERBUFFER, format, width, height); + return buf; + } + + //========================================================================== + // + // Creates a frame buffer + // + //========================================================================== + + PPGLFrameBuffer FGLRenderBuffers::CreateFrameBuffer(const char* name, PPGLTexture colorbuffer) + { + PPGLFrameBuffer fb; + glGenFramebuffers(1, &fb.handle); + glBindFramebuffer(GL_FRAMEBUFFER, fb.handle); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer.handle, 0); + if (CheckFrameBufferCompleteness()) + ClearFrameBuffer(false, false); + return fb; + } + + PPGLFrameBuffer FGLRenderBuffers::CreateFrameBuffer(const char* name, PPGLTexture colorbuffer, PPGLRenderBuffer depthstencil, PPGLRenderBuffer stencil) + { + PPGLFrameBuffer fb; + glGenFramebuffers(1, &fb.handle); + glBindFramebuffer(GL_FRAMEBUFFER, fb.handle); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer.handle, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthstencil.handle); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gles.depthStencilAvailable ? depthstencil.handle : stencil.handle); + if (CheckFrameBufferCompleteness()) + ClearFrameBuffer(true, true); + return fb; + } + + PPGLFrameBuffer FGLRenderBuffers::CreateFrameBuffer(const char* name, PPGLRenderBuffer colorbuffer, PPGLRenderBuffer depthstencil, PPGLRenderBuffer stencil) + { + PPGLFrameBuffer fb; + glGenFramebuffers(1, &fb.handle); + glBindFramebuffer(GL_FRAMEBUFFER, fb.handle); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer.handle); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthstencil.handle); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gles.depthStencilAvailable ? depthstencil.handle : stencil.handle); + if (CheckFrameBufferCompleteness()) + ClearFrameBuffer(true, true); + return fb; + } + + PPGLFrameBuffer FGLRenderBuffers::CreateFrameBuffer(const char* name, PPGLTexture colorbuffer0, PPGLTexture colorbuffer1, PPGLTexture colorbuffer2, PPGLTexture depthstencil, PPGLRenderBuffer stencil) + { + PPGLFrameBuffer fb; + glGenFramebuffers(1, &fb.handle); + glBindFramebuffer(GL_FRAMEBUFFER, fb.handle); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer0.handle, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthstencil.handle); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, gles.depthStencilAvailable ? depthstencil.handle : stencil.handle); + + if (CheckFrameBufferCompleteness()) + ClearFrameBuffer(true, true); + return fb; + } + + //========================================================================== + // + // Verifies that the frame buffer setup is valid + // + //========================================================================== + + bool FGLRenderBuffers::CheckFrameBufferCompleteness() + { + GLenum result = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (result == GL_FRAMEBUFFER_COMPLETE) + return true; + + bool FailedCreate = true; + + + FString error = "glCheckFramebufferStatus failed: "; + switch (result) + { + default: error.AppendFormat("error code %d", (int)result); break; + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: error << "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: error << "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; break; + case GL_FRAMEBUFFER_UNSUPPORTED: error << "GL_FRAMEBUFFER_UNSUPPORTED"; break; + } + Printf("%s\n", error.GetChars()); + + + return false; + } + + //========================================================================== + // + // Clear frame buffer to make sure it never contains uninitialized data + // + //========================================================================== + + void FGLRenderBuffers::ClearFrameBuffer(bool stencil, bool depth) + { + GLboolean scissorEnabled; + GLint stencilValue; + GLfloat depthValue; + glGetBooleanv(GL_SCISSOR_TEST, &scissorEnabled); + glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &stencilValue); + glGetFloatv(GL_DEPTH_CLEAR_VALUE, &depthValue); + glDisable(GL_SCISSOR_TEST); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClearDepthf(0.0f); + glClearStencil(0); + GLenum flags = GL_COLOR_BUFFER_BIT; + if (stencil) + flags |= GL_STENCIL_BUFFER_BIT; + if (depth) + flags |= GL_DEPTH_BUFFER_BIT; + glClear(flags); + glClearStencil(stencilValue); + glClearDepthf(depthValue); + if (scissorEnabled) + glEnable(GL_SCISSOR_TEST); + } + + + void FGLRenderBuffers::BindDitherTexture(int texunit) + { + if (!mDitherTexture) + { + static const float data[64] = + { + .0078125, .2578125, .1328125, .3828125, .0234375, .2734375, .1484375, .3984375, + .7578125, .5078125, .8828125, .6328125, .7734375, .5234375, .8984375, .6484375, + .0703125, .3203125, .1953125, .4453125, .0859375, .3359375, .2109375, .4609375, + .8203125, .5703125, .9453125, .6953125, .8359375, .5859375, .9609375, .7109375, + .0390625, .2890625, .1640625, .4140625, .0546875, .3046875, .1796875, .4296875, + .7890625, .5390625, .9140625, .6640625, .8046875, .5546875, .9296875, .6796875, + .1015625, .3515625, .2265625, .4765625, .1171875, .3671875, .2421875, .4921875, + .8515625, .6015625, .9765625, .7265625, .8671875, .6171875, .9921875, .7421875, + }; + + glActiveTexture(GL_TEXTURE0 + texunit); + mDitherTexture = Create2DTexture("DitherTexture", GL_RGBA, 8, 8, data); + } + mDitherTexture.Bind(1, GL_NEAREST, GL_REPEAT); + } + + + //========================================================================== + // + // Makes the scene frame buffer active (multisample, depth, stecil, etc.) + // + //========================================================================== + + void FGLRenderBuffers::BindSceneFB(bool sceneData) + { + glBindFramebuffer(GL_FRAMEBUFFER, mSceneFB.handle); + } + + //========================================================================== + // + // Binds the current scene/effect/hud texture to the specified texture unit + // + //========================================================================== + + void FGLRenderBuffers::BindCurrentTexture(int index, int filter, int wrap) + { + mSceneTex.Bind(index, filter, wrap); + } + + //========================================================================== + // + // Makes the frame buffer for the current texture active + // + //========================================================================== + + void FGLRenderBuffers::BindCurrentFB() + { +#ifndef NO_RENDER_BUFFER + mSceneFB.Bind(); +#endif + } + + //========================================================================== + // + // Makes the screen frame buffer active + // + //========================================================================== + + void FGLRenderBuffers::BindOutputFB() + { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + //========================================================================== + // + // Returns true if render buffers are supported and should be used + // + //========================================================================== + + bool FGLRenderBuffers::FailedCreate = false; + + + + +} // namespace OpenGLRenderer \ No newline at end of file diff --git a/src/common/rendering/gles/gles_renderbuffers.h b/src/common/rendering/gles/gles_renderbuffers.h new file mode 100644 index 0000000000..ce052e26fd --- /dev/null +++ b/src/common/rendering/gles/gles_renderbuffers.h @@ -0,0 +1,152 @@ + +#pragma once + +#include "hwrenderer/postprocessing/hw_postprocess.h" + +namespace OpenGLESRenderer +{ + +class FGLRenderBuffers; + +class PPGLTexture +{ +public: + void Bind(int index, int filter = GL_NEAREST, int wrap = GL_CLAMP_TO_EDGE) + { + glActiveTexture(GL_TEXTURE0 + index); + glBindTexture(GL_TEXTURE_2D, handle); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap); + } + + int Width = -1; + int Height = -1; + + explicit operator bool() const { return handle != 0; } + +private: + GLuint handle = 0; + + friend class FGLRenderBuffers; + friend class PPGLTextureBackend; +}; + +class PPGLFrameBuffer +{ +public: + void Bind() + { + glBindFramebuffer(GL_FRAMEBUFFER, handle); + } + + explicit operator bool() const { return handle != 0; } + +private: + GLuint handle = 0; + + friend class FGLRenderBuffers; + friend class PPGLTextureBackend; +}; + +class PPGLRenderBuffer +{ +private: + GLuint handle = 0; + + explicit operator bool() const { return handle != 0; } + + friend class FGLRenderBuffers; +}; + +class PPGLTextureBackend : public PPTextureBackend +{ +public: + ~PPGLTextureBackend() + { + if (Tex.handle != 0) + { + glDeleteTextures(1, &Tex.handle); + Tex.handle = 0; + } + if (FB.handle != 0) + { + glDeleteFramebuffers(1, &FB.handle); + FB.handle = 0; + } + } + + PPGLTexture Tex; + PPGLFrameBuffer FB; +}; + +class FShaderProgram; + + +class FGLRenderBuffers +{ +public: + FGLRenderBuffers(); + ~FGLRenderBuffers(); + + void Setup(int width, int height, int sceneWidth, int sceneHeight); + + void BindSceneFB(bool sceneData); + + + void BindCurrentTexture(int index, int filter = GL_NEAREST, int wrap = GL_CLAMP_TO_EDGE); + void BindCurrentFB(); + void BindNextFB(); + void NextTexture(); + + + void BindOutputFB(); + + void BindDitherTexture(int texunit); + + int GetWidth() const { return mWidth; } + int GetHeight() const { return mHeight; } + + int GetSceneWidth() const { return mSceneWidth; } + int GetSceneHeight() const { return mSceneHeight; } + +private: + void ClearScene(); + + void CreateScene(int width, int height); + void CreatePipeline(int width, int height); + + PPGLTexture Create2DTexture(const char *name, GLuint format, int width, int height, const void *data = nullptr); + PPGLRenderBuffer CreateRenderBuffer(const char *name, GLuint format, int width, int height); + PPGLFrameBuffer CreateFrameBuffer(const char *name, PPGLTexture colorbuffer); + PPGLFrameBuffer CreateFrameBuffer(const char *name, PPGLTexture colorbuffer, PPGLRenderBuffer depthstencil, PPGLRenderBuffer stencil); + PPGLFrameBuffer CreateFrameBuffer(const char *name, PPGLRenderBuffer colorbuffer, PPGLRenderBuffer depthstencil, PPGLRenderBuffer stencil); + PPGLFrameBuffer CreateFrameBuffer(const char *name, PPGLTexture colorbuffer0, PPGLTexture colorbuffer1, PPGLTexture colorbuffer2, PPGLTexture depthstencil, PPGLRenderBuffer stencil); + bool CheckFrameBufferCompleteness(); + void ClearFrameBuffer(bool stencil, bool depth); + void DeleteTexture(PPGLTexture &handle); + void DeleteRenderBuffer(PPGLRenderBuffer &handle); + void DeleteFrameBuffer(PPGLFrameBuffer &handle); + + int mWidth = 0; + int mHeight = 0; + int mSceneWidth = 0; + int mSceneHeight = 0; + + // Buffers for the scene + PPGLTexture mSceneDepthStencilTex; + PPGLTexture mSceneTex; + PPGLRenderBuffer mSceneDepthStencilBuf; + PPGLRenderBuffer mSceneStencilBuf; // This is only use when combined depth-stencil is not avaliable + PPGLFrameBuffer mSceneFB; + bool mSceneUsesTextures = false; + + PPGLTexture mDitherTexture; + + static bool FailedCreate; + + friend class GLPPRenderState; +}; + +} \ No newline at end of file diff --git a/src/common/rendering/gles/gles_renderer.cpp b/src/common/rendering/gles/gles_renderer.cpp new file mode 100644 index 0000000000..b3b79ddae5 --- /dev/null +++ b/src/common/rendering/gles/gles_renderer.cpp @@ -0,0 +1,159 @@ +/* +** gl_renderer.cpp +** Renderer interface +** +**--------------------------------------------------------------------------- +** Copyright 2005-2020 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "gles_system.h" +#include "files.h" +#include "v_video.h" +#include "m_png.h" +#include "filesystem.h" +#include "i_time.h" +#include "cmdlib.h" +#include "version.h" +#include "gles_framebuffer.h" +#include "hw_cvars.h" +#include "gles_renderer.h" +#include "gles_hwtexture.h" +#include "gles_renderstate.h" +#include "gles_samplers.h" +#include "gles_renderbuffers.h" +#include "gles_shaderprogram.h" +#include "flatvertices.h" +#include "hw_lightbuffer.h" +#include "r_videoscale.h" +#include "model.h" +#include "gles_postprocessstate.h" +#include "gles_buffers.h" +#include "texturemanager.h" + +EXTERN_CVAR(Int, screenblocks) + +namespace OpenGLESRenderer +{ + +//=========================================================================== +// +// Renderer interface +// +//=========================================================================== + +//----------------------------------------------------------------------------- +// +// Initialize +// +//----------------------------------------------------------------------------- + +FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb) +{ + framebuffer = fb; +} + +void FGLRenderer::Initialize(int width, int height) +{ + mScreenBuffers = new FGLRenderBuffers(); + mBuffers = mScreenBuffers; + mPresentShader = new FPresentShader(); + + mFBID = 0; + mOldFBID = 0; + + mShaderManager = new FShaderManager; + mSamplerManager = new FSamplerManager; +} + +FGLRenderer::~FGLRenderer() +{ + FlushModels(); + TexMan.FlushAll(); + if (mShaderManager != nullptr) delete mShaderManager; + if (mFBID != 0) glDeleteFramebuffers(1, &mFBID); + + if (mBuffers) delete mBuffers; + if (mPresentShader) delete mPresentShader; +} + +//=========================================================================== +// +// +// +//=========================================================================== + +bool FGLRenderer::StartOffscreen() +{ + bool firstBind = (mFBID == 0); + if (mFBID == 0) + glGenFramebuffers(1, &mFBID); + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &mOldFBID); + glBindFramebuffer(GL_FRAMEBUFFER, mFBID); + return true; +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void FGLRenderer::EndOffscreen() +{ + glBindFramebuffer(GL_FRAMEBUFFER, mOldFBID); +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void FGLRenderer::BindToFrameBuffer(FTexture *tex) +{ + auto BaseLayer = static_cast(tex->GetHardwareTexture(0, 0)); + // must create the hardware texture first + BaseLayer->BindOrCreate(tex, 0, 0, 0, 0); + FHardwareTexture::Unbind(0); + gl_RenderState.ClearLastMaterial(); + BaseLayer->BindToFrameBuffer(tex->GetWidth(), tex->GetHeight()); +} + +//=========================================================================== +// +// +// +//=========================================================================== + +void FGLRenderer::BeginFrame() +{ + mScreenBuffers->Setup(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height); +} + +} diff --git a/src/common/rendering/gles/gles_renderer.h b/src/common/rendering/gles/gles_renderer.h new file mode 100644 index 0000000000..a196900296 --- /dev/null +++ b/src/common/rendering/gles/gles_renderer.h @@ -0,0 +1,106 @@ +#ifndef __GL_RENDERER_H +#define __GL_RENDERER_H + +#include "v_video.h" +#include "vectors.h" +#include "matrix.h" +#include "gles_renderbuffers.h" +#include + +#ifdef _MSC_VER +#pragma warning(disable:4244) +#endif + +struct particle_t; +class FCanvasTexture; +class FFlatVertexBuffer; +class FSkyVertexBuffer; +class HWPortal; +class FLightBuffer; +class DPSprite; +class FGLRenderBuffers; +class FGL2DDrawer; +class SWSceneDrawer; +class HWViewpointBuffer; +struct FRenderViewpoint; + +namespace OpenGLESRenderer +{ + class FHardwareTexture; + class FShaderManager; + class FSamplerManager; + class OpenGLFrameBuffer; + class FPresentShaderBase; + class FPresentShader; + class FPresent3DCheckerShader; + class FPresent3DColumnShader; + class FPresent3DRowShader; + class FShadowMapShader; + +class FGLRenderer +{ +public: + + OpenGLFrameBuffer *framebuffer; + int mMirrorCount = 0; + int mPlaneMirrorCount = 0; + FShaderManager *mShaderManager = nullptr; + FSamplerManager* mSamplerManager = nullptr; + unsigned int mFBID = 0; + unsigned int mStencilValue = 0; + + int mOldFBID = 0; + + FGLRenderBuffers *mBuffers = nullptr; + FGLRenderBuffers *mScreenBuffers = nullptr; + FPresentShader *mPresentShader = nullptr; + + //FRotator mAngles; + + FGLRenderer(OpenGLFrameBuffer *fb); + ~FGLRenderer() ; + + void Initialize(int width, int height); + + void ClearBorders(); + + void PresentStereo(); + void RenderScreenQuad(); + void PostProcessScene(int fixedcm, float flash, const std::function &afterBloomDrawEndScene2D); + + void CopyToBackbuffer(const IntRect *bounds, bool applyGamma); + void DrawPresentTexture(const IntRect &box, bool applyGamma); + void Flush(); + void BeginFrame(); + + bool StartOffscreen(); + void EndOffscreen(); + + void BindToFrameBuffer(FTexture* tex); + +private: + + bool QuadStereoCheckInitialRenderContextState(); + void PresentAnaglyph(bool r, bool g, bool b); + void PresentSideBySide(int); + void PresentTopBottom(); + void prepareInterleavedPresent(FPresentShaderBase& shader); + void PresentColumnInterleaved(); + void PresentRowInterleaved(); + void PresentCheckerInterleaved(); + void PresentQuadStereo(); + +}; + +struct TexFilter_s +{ + int minfilter; + int magfilter; + bool mipmapping; +} ; + + +extern FGLRenderer *GLRenderer; + +} +#endif diff --git a/src/common/rendering/gles/gles_renderstate.cpp b/src/common/rendering/gles/gles_renderstate.cpp new file mode 100644 index 0000000000..dfd9652ad9 --- /dev/null +++ b/src/common/rendering/gles/gles_renderstate.cpp @@ -0,0 +1,727 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2009-2016 Christoph Oelckers +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// +/* +** gl_renderstate.cpp +** Render state maintenance +** +*/ + +#include "templates.h" +#include "gles_system.h" +#include "hw_cvars.h" +#include "flatvertices.h" +#include "gles_shader.h" +#include "gles_renderer.h" +#include "hw_lightbuffer.h" +#include "gles_renderbuffers.h" +#include "gles_hwtexture.h" +#include "gles_buffers.h" +#include "hw_clock.h" +#include "printf.h" + +#include "hwrenderer/data/hw_viewpointbuffer.h" + +namespace OpenGLESRenderer +{ + +FGLRenderState gl_RenderState; + +static VSMatrix identityMatrix(1); + +static void matrixToGL(const VSMatrix &mat, int loc) +{ + glUniformMatrix4fv(loc, 1, false, (float*)&mat); +} + +//========================================================================== +// +// This only gets called once upon setup. +// With OpenGL the state is persistent and cannot be cleared, once set up. +// +//========================================================================== + +void FGLRenderState::Reset() +{ + FRenderState::Reset(); + mVertexBuffer = mCurrentVertexBuffer = nullptr; + mGlossiness = 0.0f; + mSpecularLevel = 0.0f; + mShaderTimer = 0.0f; + + stRenderStyle = DefaultRenderStyle(); + stSrcBlend = stDstBlend = -1; + stBlendEquation = -1; + stAlphaTest = 0; + mLastDepthClamp = true; + + mEffectState = 0; + activeShader = nullptr; + + mCurrentVertexBuffer = nullptr; + mCurrentVertexOffsets[0] = mVertexOffsets[0] = 0; + mCurrentIndexBuffer = nullptr; + +} + +//========================================================================== +// +// Apply shader settings +// +//========================================================================== + +bool FGLRenderState::ApplyShader() +{ + static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; + + // Need to calc light data now in order to select correct shader + float* lightPtr = NULL; + int modLights = 0; + int subLights = 0; + int addLights = 0; + + if (mLightIndex >= 0) + { + lightPtr = ((float*)screen->mLights->GetBuffer()->Memory()); + lightPtr += ((int64_t)mLightIndex * 4); + //float array[64]; + //memcpy(array, ptr, 4 * 64); + + // Calculate how much light data there is to upload, this is stored in the first 4 floats + modLights = int(lightPtr[1]) / LIGHT_VEC4_NUM; + subLights = (int(lightPtr[2]) - int(lightPtr[1])) / LIGHT_VEC4_NUM; + addLights = (int(lightPtr[3]) - int(lightPtr[2])) / LIGHT_VEC4_NUM; + + // Here we limit the number of lights, but dont' change the light data so priority has to be mod, sub then add + if (modLights > gles.maxlights) + modLights = gles.maxlights; + + if (modLights + subLights > gles.maxlights) + subLights = gles.maxlights - modLights; + + if (modLights + subLights + addLights > gles.maxlights) + addLights = gles.maxlights - modLights - subLights; + + + // Skip passed the first 4 floats so the upload below only contains light data + lightPtr += 4; + } + + ShaderFlavourData flavour; + + flavour.textureMode = (mTextureMode == TM_NORMAL && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode); + + if (flavour.textureMode == -1) + flavour.textureMode = 0; + + flavour.texFlags = mTextureModeFlags; if (!mBrightmapEnabled) flavour.texFlags &= ~(TEXF_Brightmap | TEXF_Glowmap); + flavour.texFlags >>= 16; //Move flags to start of word + + flavour.blendFlags = (int)(mStreamData.uTextureAddColor.a + 0.01); + + flavour.twoDFog = false; + flavour.fogEnabled = false; + flavour.fogEquationRadial = false; + flavour.colouredFog = false; + + flavour.fogEquationRadial = (gl_fogmode == 2); + + flavour.twoDFog = false; + flavour.fogEnabled = false; + flavour.colouredFog = false; + + if (mFogEnabled) + { + if (mFogEnabled == 2) + { + flavour.twoDFog = true; + } + else if (gl_fogmode) + { + flavour.fogEnabled = true; + + if ((GetFogColor() & 0xffffff) != 0) + flavour.colouredFog = true; + } + } + + flavour.doDesaturate = mStreamData.uDesaturationFactor != 0; + flavour.useULightLevel = (mLightParms[3] >= 0); //#define uLightLevel uLightAttr.a + + // Yes create shaders for all combinations of active lights to avoid more branches + flavour.dynLightsMod = (modLights > 0); + flavour.dynLightsSub = (subLights > 0); + flavour.dynLightsAdd = (addLights > 0); + + flavour.useObjectColor2 = (mStreamData.uObjectColor2.a > 0); + flavour.useGlowTopColor = mGlowEnabled && (mStreamData.uGlowTopColor[3] > 0); + flavour.useGlowBottomColor = mGlowEnabled && (mStreamData.uGlowBottomColor[3] > 0); + + flavour.useColorMap = (mColorMapSpecial >= CM_FIRSTSPECIALCOLORMAP) || (mColorMapFlash != 1); + + flavour.buildLighting = (mHwUniforms->mPalLightLevels >> 16) == 5; // Build engine mode + flavour.bandedSwLight = !!(mHwUniforms->mPalLightLevels & 0xFF); + +#ifdef NPOT_EMULATION + flavour.npotEmulation = (mStreamData.uNpotEmulation.Y != 0); +#endif + + if (mSpecialEffect > EFF_NONE) + { + activeShader = GLRenderer->mShaderManager->BindEffect(mSpecialEffect, mPassType, flavour); + } + else + { + activeShader = GLRenderer->mShaderManager->Get(mTextureEnabled ? mEffectState : SHADER_NoTexture, mAlphaThreshold >= 0.f, mPassType); + + activeShader->Bind(flavour); + } + + + if (mHwUniforms) + { + //matrixToGL(mHwUniforms->mProjectionMatrix, activeShader->cur->ProjectionMatrix_index); + activeShader->cur->muProjectionMatrix.Set(&mHwUniforms->mProjectionMatrix); + activeShader->cur->muViewMatrix.Set(&mHwUniforms->mViewMatrix); + activeShader->cur->muNormalViewMatrix.Set(&mHwUniforms->mNormalViewMatrix); + + //matrixToGL(mHwUniforms->mViewMatrix, activeShader->cur->ViewMatrix_index); + //matrixToGL(mHwUniforms->mNormalViewMatrix, activeShader->cur->NormalViewMatrix_index); + + activeShader->cur->muCameraPos.Set(&mHwUniforms->mCameraPos.X); + activeShader->cur->muClipLine.Set(&mHwUniforms->mClipLine.X); + + activeShader->cur->muGlobVis.Set(mHwUniforms->mGlobVis); + + activeShader->cur->muPalLightLevels.Set(mHwUniforms->mPalLightLevels & 0xFF); // JUST pass the pal levels, clear the top bits + activeShader->cur->muViewHeight.Set(mHwUniforms->mViewHeight); + activeShader->cur->muClipHeight.Set(mHwUniforms->mClipHeight); + activeShader->cur->muClipHeightDirection.Set(mHwUniforms->mClipHeightDirection); + //activeShader->cur->muShadowmapFilter.Set(mHwUniforms->mShadowmapFilter); + } + + glVertexAttrib4fv(VATTR_COLOR, &mStreamData.uVertexColor.X); + glVertexAttrib4fv(VATTR_NORMAL, &mStreamData.uVertexNormal.X); + + activeShader->cur->muDesaturation.Set(mStreamData.uDesaturationFactor); + //activeShader->cur->muFogEnabled.Set(fogset); + + int f = mTextureModeFlags; + if (!mBrightmapEnabled) f &= ~(TEXF_Brightmap | TEXF_Glowmap); + //activeShader->cur->muTextureMode.Set((mTextureMode == TM_NORMAL && mTempTM == TM_OPAQUE ? TM_OPAQUE : mTextureMode) | f); + activeShader->cur->muLightParms.Set(mLightParms); + activeShader->cur->muFogColor.Set(mStreamData.uFogColor); + activeShader->cur->muObjectColor.Set(mStreamData.uObjectColor); + activeShader->cur->muDynLightColor.Set(&mStreamData.uDynLightColor.X); + activeShader->cur->muInterpolationFactor.Set(mStreamData.uInterpolationFactor); + activeShader->cur->muTimer.Set((double)(screen->FrameTime - firstFrame) * (double)mShaderTimer / 1000.); + activeShader->cur->muAlphaThreshold.Set(mAlphaThreshold); + activeShader->cur->muClipSplit.Set(mClipSplit); + activeShader->cur->muSpecularMaterial.Set(mGlossiness, mSpecularLevel); + activeShader->cur->muAddColor.Set(mStreamData.uAddColor); + activeShader->cur->muTextureAddColor.Set(mStreamData.uTextureAddColor); + activeShader->cur->muTextureModulateColor.Set(mStreamData.uTextureModulateColor); + activeShader->cur->muTextureBlendColor.Set(mStreamData.uTextureBlendColor); + activeShader->cur->muDetailParms.Set(&mStreamData.uDetailParms.X); +#ifdef NPOT_EMULATION + activeShader->cur->muNpotEmulation.Set(&mStreamData.uNpotEmulation.X); +#endif + + if (flavour.useColorMap) + { + if (mColorMapSpecial < CM_FIRSTSPECIALCOLORMAP || mColorMapSpecial >= CM_MAXCOLORMAP) + { + activeShader->cur->muFixedColormapStart.Set( 0,0,0, mColorMapFlash ); + activeShader->cur->muFixedColormapRange.Set( 0,0,0, 1.f ); + } + else + { + FSpecialColormap* scm = &SpecialColormaps[mColorMapSpecial - CM_FIRSTSPECIALCOLORMAP]; + + //uniforms.MapStart = { scm->ColorizeStart[0], scm->ColorizeStart[1], scm->ColorizeStart[2], flash }; + activeShader->cur->muFixedColormapStart.Set( scm->ColorizeStart[0], scm->ColorizeStart[1], scm->ColorizeStart[2], mColorMapFlash ); + activeShader->cur->muFixedColormapRange.Set( scm->ColorizeEnd[0] - scm->ColorizeStart[0], + scm->ColorizeEnd[1] - scm->ColorizeStart[1], scm->ColorizeEnd[2] - scm->ColorizeStart[2], 0.f ); + } + } + + if (mGlowEnabled || activeShader->cur->currentglowstate) + { + activeShader->cur->muGlowTopColor.Set(&mStreamData.uGlowTopColor.X); + activeShader->cur->muGlowBottomColor.Set(&mStreamData.uGlowBottomColor.X); + activeShader->cur->muGlowTopPlane.Set(&mStreamData.uGlowTopPlane.X); + activeShader->cur->muGlowBottomPlane.Set(&mStreamData.uGlowBottomPlane.X); + activeShader->cur->currentglowstate = mGlowEnabled; + } + + if (mGradientEnabled || activeShader->cur->currentgradientstate) + { + activeShader->cur->muObjectColor2.Set(mStreamData.uObjectColor2); + activeShader->cur->muGradientTopPlane.Set(&mStreamData.uGradientTopPlane.X); + activeShader->cur->muGradientBottomPlane.Set(&mStreamData.uGradientBottomPlane.X); + activeShader->cur->currentgradientstate = mGradientEnabled; + } + + if (mSplitEnabled || activeShader->cur->currentsplitstate) + { + activeShader->cur->muSplitTopPlane.Set(&mStreamData.uSplitTopPlane.X); + activeShader->cur->muSplitBottomPlane.Set(&mStreamData.uSplitBottomPlane.X); + activeShader->cur->currentsplitstate = mSplitEnabled; + } + + + if (mTextureMatrixEnabled) + { + matrixToGL(mTextureMatrix, activeShader->cur->texturematrix_index); + activeShader->cur->currentTextureMatrixState = true; + } + else if (activeShader->cur->currentTextureMatrixState) + { + activeShader->cur->currentTextureMatrixState = false; + matrixToGL(identityMatrix, activeShader->cur->texturematrix_index); + } + + if (mModelMatrixEnabled) + { + matrixToGL(mModelMatrix, activeShader->cur->modelmatrix_index); + VSMatrix norm; + norm.computeNormalMatrix(mModelMatrix); + matrixToGL(norm, activeShader->cur->normalmodelmatrix_index); + activeShader->cur->currentModelMatrixState = true; + } + else if (activeShader->cur->currentModelMatrixState) + { + activeShader->cur->currentModelMatrixState = false; + matrixToGL(identityMatrix, activeShader->cur->modelmatrix_index); + matrixToGL(identityMatrix, activeShader->cur->normalmodelmatrix_index); + } + + // Upload the light data + if (mLightIndex >= 0) + { + int totalLights = modLights + subLights + addLights; + + // Calculate the total number of vec4s we need + int totalVectors = totalLights * LIGHT_VEC4_NUM; + + // TODO!!! If there are too many lights we need to remove some of the lights and modify the data + // At the moment the shader will just try to read off the end of the array... + if (totalVectors > gles.numlightvectors) + totalVectors = gles.numlightvectors; + + glUniform4fv(activeShader->cur->lights_index, totalVectors, lightPtr); + + int range[4] = { 0, + modLights * LIGHT_VEC4_NUM, + (modLights + subLights) * LIGHT_VEC4_NUM, + (modLights + subLights + addLights) * LIGHT_VEC4_NUM }; + + activeShader->cur->muLightRange.Set(range); + } + + return true; +} + + +//========================================================================== +// +// Apply State +// +//========================================================================== + +void FGLRenderState::ApplyState() +{ + if (mRenderStyle != stRenderStyle) + { + ApplyBlendMode(); + stRenderStyle = mRenderStyle; + } + + if (mSplitEnabled != stSplitEnabled) + { + /* + if (mSplitEnabled) + { + glEnable(GL_CLIP_DISTANCE3); + glEnable(GL_CLIP_DISTANCE4); + } + else + { + glDisable(GL_CLIP_DISTANCE3); + glDisable(GL_CLIP_DISTANCE4); + } + */ + stSplitEnabled = mSplitEnabled; + } + + if (mMaterial.mChanged) + { + ApplyMaterial(mMaterial.mMaterial, mMaterial.mClampMode, mMaterial.mTranslation, mMaterial.mOverrideShader); + mMaterial.mChanged = false; + } + + if (mBias.mChanged) + { + if (mBias.mFactor == 0 && mBias.mUnits == 0) + { + glDisable(GL_POLYGON_OFFSET_FILL); + } + else + { + glEnable(GL_POLYGON_OFFSET_FILL); + } + glPolygonOffset(mBias.mFactor, mBias.mUnits); + mBias.mChanged = false; + } +} + +void FGLRenderState::ApplyBuffers() +{ + if (mVertexBuffer != mCurrentVertexBuffer || mVertexOffsets[0] != mCurrentVertexOffsets[0] || mVertexOffsets[1] != mCurrentVertexOffsets[1]) + { + assert(mVertexBuffer != nullptr); + static_cast(mVertexBuffer)->Bind(mVertexOffsets); + mCurrentVertexBuffer = mVertexBuffer; + mCurrentVertexOffsets[0] = mVertexOffsets[0]; + mCurrentVertexOffsets[1] = mVertexOffsets[1]; + } + if (mIndexBuffer != mCurrentIndexBuffer) + { + if (mIndexBuffer) static_cast(mIndexBuffer)->Bind(); + mCurrentIndexBuffer = mIndexBuffer; + } +} + +void FGLRenderState::Apply() +{ + ApplyState(); + ApplyBuffers(); + ApplyShader(); +} + +//=========================================================================== +// +// Binds a texture to the renderer +// +//=========================================================================== + +void FGLRenderState::ApplyMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader) +{ + if (mat->Source()->isHardwareCanvas()) + { + mTempTM = TM_OPAQUE; + } + else + { + mTempTM = TM_NORMAL; + } + auto tex = mat->Source(); + mEffectState = overrideshader >= 0 ? overrideshader : mat->GetShaderIndex(); + mShaderTimer = tex->GetShaderSpeed(); + SetSpecular(tex->GetGlossiness(), tex->GetSpecularLevel()); + if (tex->isHardwareCanvas()) static_cast(tex->GetTexture())->NeedUpdate(); + + clampmode = tex->GetClampMode(clampmode); + + // avoid rebinding the same texture multiple times. + if (mat == lastMaterial && lastClamp == clampmode && translation == lastTranslation) return; + lastMaterial = mat; + lastClamp = clampmode; + lastTranslation = translation; + + int usebright = false; + int maxbound = 0; + + int numLayers = mat->NumLayers(); + MaterialLayerInfo* layer; + auto base = static_cast(mat->GetLayer(0, translation, &layer)); + + if (base->BindOrCreate(tex->GetTexture(), 0, clampmode, translation, layer->scaleFlags)) + { + if (!(layer->scaleFlags & CTF_Indexed)) + { + for (int i = 1; i < numLayers; i++) + { + auto systex = static_cast(mat->GetLayer(i, 0, &layer)); + // fixme: Upscale flags must be disabled for certain layers. + systex->BindOrCreate(layer->layerTexture, i, clampmode, 0, layer->scaleFlags); + maxbound = i; + } + } + else + { + for (int i = 1; i < 3; i++) + { + auto systex = static_cast(mat->GetLayer(i, translation, &layer)); + systex->Bind(i, false); + maxbound = i; + } + } + } + // unbind everything from the last texture that's still active + for (int i = maxbound + 1; i <= maxBoundMaterial; i++) + { + FHardwareTexture::Unbind(i); + maxBoundMaterial = maxbound; + } +} + +//========================================================================== +// +// Apply blend mode from RenderStyle +// +//========================================================================== + +void FGLRenderState::ApplyBlendMode() +{ + static int blendstyles[] = { GL_ZERO, GL_ONE, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA }; + static int renderops[] = { 0, GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 }; + + int srcblend = blendstyles[mRenderStyle.SrcAlpha%STYLEALPHA_MAX]; + int dstblend = blendstyles[mRenderStyle.DestAlpha%STYLEALPHA_MAX]; + int blendequation = renderops[mRenderStyle.BlendOp & 15]; + + if (blendequation == -1) // This was a fuzz style. + { + srcblend = GL_DST_COLOR; + dstblend = GL_ONE_MINUS_SRC_ALPHA; + blendequation = GL_FUNC_ADD; + } + + // Checks must be disabled until all draw code has been converted. + if (srcblend != stSrcBlend || dstblend != stDstBlend) + { + stSrcBlend = srcblend; + stDstBlend = dstblend; + glBlendFunc(srcblend, dstblend); + } + if (blendequation != stBlendEquation) + { + stBlendEquation = blendequation; + glBlendEquation(blendequation); + } + +} + +//========================================================================== +// +// API dependent draw calls +// +//========================================================================== + +static int dt2gl[] = { GL_POINTS, GL_LINES, GL_TRIANGLES, GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP }; + +void FGLRenderState::Draw(int dt, int index, int count, bool apply) +{ + if (apply) + { + Apply(); + } + drawcalls.Clock(); + glDrawArrays(dt2gl[dt], index, count); + drawcalls.Unclock(); +} + +void FGLRenderState::DrawIndexed(int dt, int index, int count, bool apply) +{ + if (apply) + { + Apply(); + } + drawcalls.Clock(); + glDrawElements(dt2gl[dt], count, GL_UNSIGNED_INT, (void*)(intptr_t)(index * sizeof(uint32_t))); + drawcalls.Unclock(); +} + +void FGLRenderState::SetDepthMask(bool on) +{ + glDepthMask(on); +} + +void FGLRenderState::SetDepthFunc(int func) +{ + static int df2gl[] = { GL_LESS, GL_LEQUAL, GL_ALWAYS }; + glDepthFunc(df2gl[func]); +} + +void FGLRenderState::SetDepthRange(float min, float max) +{ + glDepthRangef(min, max); +} + +void FGLRenderState::SetColorMask(bool r, bool g, bool b, bool a) +{ + glColorMask(r, g, b, a); +} + +void FGLRenderState::SetStencil(int offs, int op, int flags = -1) +{ + static int op2gl[] = { GL_KEEP, GL_INCR, GL_DECR }; + + glStencilFunc(GL_EQUAL, screen->stencilValue + offs, ~0); // draw sky into stencil + glStencilOp(GL_KEEP, GL_KEEP, op2gl[op]); // this stage doesn't modify the stencil + + if (flags != -1) + { + bool cmon = !(flags & SF_ColorMaskOff); + glColorMask(cmon, cmon, cmon, cmon); // don't write to the graphics buffer + glDepthMask(!(flags & SF_DepthMaskOff)); + } +} + +void FGLRenderState::ToggleState(int state, bool on) +{ + if (on) + { + glEnable(state); + } + else + { + glDisable(state); + } +} + +void FGLRenderState::SetCulling(int mode) +{ + if (mode != Cull_None) + { + glEnable(GL_CULL_FACE); + glFrontFace(mode == Cull_CCW ? GL_CCW : GL_CW); + } + else + { + glDisable(GL_CULL_FACE); + } +} + +void FGLRenderState::EnableClipDistance(int num, bool state) +{ + +} + +void FGLRenderState::Clear(int targets) +{ + // This always clears to default values. + int gltarget = 0; + if (targets & CT_Depth) + { + gltarget |= GL_DEPTH_BUFFER_BIT; + + glClearDepthf(1); + } + if (targets & CT_Stencil) + { + gltarget |= GL_STENCIL_BUFFER_BIT; + glClearStencil(0); + } + if (targets & CT_Color) + { + gltarget |= GL_COLOR_BUFFER_BIT; + glClearColor(screen->mSceneClearColor[0], screen->mSceneClearColor[1], screen->mSceneClearColor[2], screen->mSceneClearColor[3]); + } + glClear(gltarget); +} + +void FGLRenderState::EnableStencil(bool on) +{ + ToggleState(GL_STENCIL_TEST, on); +} + +void FGLRenderState::SetScissor(int x, int y, int w, int h) +{ + if (w > -1) + { + glEnable(GL_SCISSOR_TEST); + glScissor(x, y, w, h); + } + else + { + glDisable(GL_SCISSOR_TEST); + } +} + +void FGLRenderState::SetViewport(int x, int y, int w, int h) +{ + glViewport(x, y, w, h); +} + +void FGLRenderState::EnableDepthTest(bool on) +{ + ToggleState(GL_DEPTH_TEST, on); +} + +void FGLRenderState::EnableMultisampling(bool on) +{ + +} + +void FGLRenderState::EnableLineSmooth(bool on) +{ + +} + + +//========================================================================== +// +// +// +//========================================================================== +void FGLRenderState::ClearScreen() +{ + + screen->mViewpoints->Set2D(*this, SCREENWIDTH, SCREENHEIGHT); + SetColor(0, 0, 0); + Apply(); + + glDisable(GL_DEPTH_TEST); + + glDrawArrays(GL_TRIANGLE_STRIP, FFlatVertexBuffer::FULLSCREEN_INDEX, 4); + + glEnable(GL_DEPTH_TEST); + +} + + + +//========================================================================== +// +// Below are less frequently altrered state settings which do not get +// buffered by the state object, but set directly instead. +// +//========================================================================== + +bool FGLRenderState::SetDepthClamp(bool on) +{ + bool res = mLastDepthClamp; + /* + if (!on) glDisable(GL_DEPTH_CLAMP); + else glEnable(GL_DEPTH_CLAMP); + */ + mLastDepthClamp = on; + return res; +} +void FGLRenderState::ApplyViewport(void* data) +{ + mHwUniforms = reinterpret_cast(static_cast(data)); + +} +} diff --git a/src/common/rendering/gles/gles_renderstate.h b/src/common/rendering/gles/gles_renderstate.h new file mode 100644 index 0000000000..7b77685416 --- /dev/null +++ b/src/common/rendering/gles/gles_renderstate.h @@ -0,0 +1,152 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2009-2016 Christoph Oelckers +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// + +#ifndef __GL_RENDERSTATE_H +#define __GL_RENDERSTATE_H + +#include +#include +#include "matrix.h" +#include "hw_renderstate.h" +#include "hw_material.h" +#include "c_cvars.h" +#include "hwrenderer/data/hw_viewpointuniforms.h" + +namespace OpenGLESRenderer +{ + +class FShader; +struct HWSectorPlane; + +class FGLRenderState final : public FRenderState +{ + uint8_t mLastDepthClamp : 1; + + float mGlossiness, mSpecularLevel; + float mShaderTimer; + + int mEffectState; + int mTempTM = TM_NORMAL; + + FRenderStyle stRenderStyle; + int stSrcBlend, stDstBlend; + bool stAlphaTest; + bool stSplitEnabled; + int stBlendEquation; + + FShader *activeShader; + + int mNumDrawBuffers = 1; + + bool ApplyShader(); + void ApplyState(); + + // Texture binding state + FMaterial *lastMaterial = nullptr; + int lastClamp = 0; + int lastTranslation = 0; + int maxBoundMaterial = -1; + size_t mLastMappedLightIndex = SIZE_MAX; + + IVertexBuffer *mCurrentVertexBuffer; + int mCurrentVertexOffsets[2]; // one per binding point + IIndexBuffer *mCurrentIndexBuffer; + + HWViewpointUniforms* mHwUniforms = nullptr; + +public: + + FGLRenderState() + { + Reset(); + } + + void Reset(); + + void ClearLastMaterial() + { + lastMaterial = nullptr; + } + + void ApplyMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader); + + void Apply(); + void ApplyBuffers(); + void ApplyBlendMode(); + + void ResetVertexBuffer() + { + // forces rebinding with the next 'apply' call. + mCurrentVertexBuffer = nullptr; + mCurrentIndexBuffer = nullptr; + } + + void SetSpecular(float glossiness, float specularLevel) + { + mGlossiness = glossiness; + mSpecularLevel = specularLevel; + } + + void EnableDrawBuffers(int count, bool apply = false) override + { + /* + count = std::min(count, 3); + if (mNumDrawBuffers != count) + { + static GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 }; + glDrawBuffers(count, buffers); + mNumDrawBuffers = count; + } + if (apply) Apply(); + */ + } + + void ToggleState(int state, bool on); + + void ClearScreen() override; + void Draw(int dt, int index, int count, bool apply = true) override; + void DrawIndexed(int dt, int index, int count, bool apply = true) override; + + bool SetDepthClamp(bool on) override; + void SetDepthMask(bool on) override; + void SetDepthFunc(int func) override; + void SetDepthRange(float min, float max) override; + void SetColorMask(bool r, bool g, bool b, bool a) override; + void SetStencil(int offs, int op, int flags) override; + void SetCulling(int mode) override; + void EnableClipDistance(int num, bool state) override; + void Clear(int targets) override; + void EnableStencil(bool on) override; + void SetScissor(int x, int y, int w, int h) override; + void SetViewport(int x, int y, int w, int h) override; + void EnableDepthTest(bool on) override; + void EnableMultisampling(bool on) override; + void EnableLineSmooth(bool on) override; + + void ApplyViewport(void* data); +}; + +extern FGLRenderState gl_RenderState; + +} + +#endif diff --git a/src/common/rendering/gles/gles_samplers.cpp b/src/common/rendering/gles/gles_samplers.cpp new file mode 100644 index 0000000000..1e3b16d2de --- /dev/null +++ b/src/common/rendering/gles/gles_samplers.cpp @@ -0,0 +1,178 @@ +/* +** gl_samplers.cpp +** +** Texture sampler handling +** +**--------------------------------------------------------------------------- +** Copyright 2015-2019 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ +#include "gles_system.h" +#include "c_cvars.h" + +#include "hw_cvars.h" + +#include "gles_renderer.h" +#include "gles_samplers.h" +#include "hw_material.h" +#include "i_interface.h" + +namespace OpenGLESRenderer +{ + +extern TexFilter_s TexFilter[]; + + +FSamplerManager::FSamplerManager() +{ + SetTextureFilterMode(); +} + +FSamplerManager::~FSamplerManager() +{ + +} + +void FSamplerManager::UnbindAll() +{ + +} + +uint8_t FSamplerManager::Bind(int texunit, int num, int lastval) +{ + + int filter = sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter() ? 0 : gl_texture_filter; + + glActiveTexture(GL_TEXTURE0 + texunit); + switch (num) + { + case CLAMP_NONE: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + if (lastval >= CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + } + break; + + case CLAMP_X: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + if (lastval >= CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + } + break; + + case CLAMP_Y: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (lastval >= CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + } + break; + + case CLAMP_XY: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + if (lastval >= CLAMP_XY_NOMIP) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + } + break; + + case CLAMP_XY_NOMIP: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].magfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + break; + + case CLAMP_NOFILTER: + case CLAMP_NOFILTER_X: + case CLAMP_NOFILTER_Y: + case CLAMP_NOFILTER_XY: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + break; + + case CLAMP_CAMTEX: + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, TexFilter[filter].magfilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + break; + } + glActiveTexture(GL_TEXTURE0); + return 255; +} + + +void FSamplerManager::SetTextureFilterMode() +{ + /* + GLRenderer->FlushTextures(); + + GLint bounds[IHardwareTexture::MAX_TEXTURES]; + + // Unbind all + for(int i = IHardwareTexture::MAX_TEXTURES-1; i >= 0; i--) + { + glActiveTexture(GL_TEXTURE0 + i); + glGetIntegerv(GL_SAMPLER_BINDING, &bounds[i]); + glBindSampler(i, 0); + } + + int filter = sysCallbacks.DisableTextureFilter && sysCallbacks.DisableTextureFilter() ? 0 : gl_texture_filter; + + for (int i = 0; i < 4; i++) + { + glSamplerParameteri(mSamplers[i], GL_TEXTURE_MIN_FILTER, TexFilter[filter].minfilter); + glSamplerParameteri(mSamplers[i], GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + glSamplerParameterf(mSamplers[i], GL_TEXTURE_MAX_ANISOTROPY_EXT, filter > 0? gl_texture_filter_anisotropic : 1.0); + } + glSamplerParameteri(mSamplers[CLAMP_XY_NOMIP], GL_TEXTURE_MIN_FILTER, TexFilter[filter].magfilter); + glSamplerParameteri(mSamplers[CLAMP_XY_NOMIP], GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + glSamplerParameteri(mSamplers[CLAMP_CAMTEX], GL_TEXTURE_MIN_FILTER, TexFilter[filter].magfilter); + glSamplerParameteri(mSamplers[CLAMP_CAMTEX], GL_TEXTURE_MAG_FILTER, TexFilter[filter].magfilter); + for(int i = 0; i < IHardwareTexture::MAX_TEXTURES; i++) + { + glBindSampler(i, bounds[i]); + } + */ +} + + +} \ No newline at end of file diff --git a/src/common/rendering/gles/gles_samplers.h b/src/common/rendering/gles/gles_samplers.h new file mode 100644 index 0000000000..541b409b78 --- /dev/null +++ b/src/common/rendering/gles/gles_samplers.h @@ -0,0 +1,27 @@ +#ifndef __GLES_SAMPLERS_H +#define __GLES_SAMPLERS_H + +#include "gles_hwtexture.h" +#include "textures.h" + +namespace OpenGLESRenderer +{ + + +class FSamplerManager +{ + void UnbindAll(); + +public: + + FSamplerManager(); + ~FSamplerManager(); + + uint8_t Bind(int texunit, int num, int lastval); + void SetTextureFilterMode(); + +}; + +} +#endif + diff --git a/src/common/rendering/gles/gles_shader.cpp b/src/common/rendering/gles/gles_shader.cpp new file mode 100644 index 0000000000..4587fd84ad --- /dev/null +++ b/src/common/rendering/gles/gles_shader.cpp @@ -0,0 +1,952 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2004-2016 Christoph Oelckers +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// +/* +** gl_shader.cpp +** +** GLSL shader handling +** +*/ + +#include "gles_system.h" +#include "c_cvars.h" +#include "v_video.h" +#include "filesystem.h" +#include "engineerrors.h" +#include "cmdlib.h" +#include "md5.h" +#include "gles_shader.h" +#include "hw_shaderpatcher.h" +#include "shaderuniforms.h" +#include "hw_viewpointuniforms.h" +#include "hw_lightbuffer.h" +#include "i_specialpaths.h" +#include "printf.h" +#include "version.h" + +#include "matrix.h" +#include "gles_renderer.h" +#include +#include + +namespace OpenGLESRenderer +{ + +CVAR(Int, gles_glsl_precision, 2, 0); // 0 = low, 1 = medium, 2 = high + +FString GetGLSLPrecision() +{ + FString str = "precision highp int;\n \ + precision highp float;\n"; + + if (gles_glsl_precision == 0) + str.Substitute("highp", "lowp"); + else if (gles_glsl_precision == 1) + str.Substitute("highp", "mediump"); + + return str; +} + +struct ProgramBinary +{ + uint32_t format; + TArray data; +}; + +static const char *ShaderMagic = "ZDSC"; + +static std::map> ShaderCache; // Not a TMap because it doesn't support unique_ptr move semantics + +bool IsShaderCacheActive() +{ + static bool active = true; + static bool firstcall = true; + + if (firstcall) + { + const char *vendor = (const char *)glGetString(GL_VENDOR); + active = !(strstr(vendor, "Intel") == nullptr); + firstcall = false; + } + return active; +} + +static FString CalcProgramBinaryChecksum(const FString &vertex, const FString &fragment) +{ + const GLubyte *vendor = glGetString(GL_VENDOR); + const GLubyte *renderer = glGetString(GL_RENDERER); + const GLubyte *version = glGetString(GL_VERSION); + + uint8_t digest[16]; + MD5Context md5; + md5.Update(vendor, (unsigned int)strlen((const char*)vendor)); + md5.Update(renderer, (unsigned int)strlen((const char*)renderer)); + md5.Update(version, (unsigned int)strlen((const char*)version)); + md5.Update((const uint8_t *)vertex.GetChars(), (unsigned int)vertex.Len()); + md5.Update((const uint8_t *)fragment.GetChars(), (unsigned int)fragment.Len()); + md5.Final(digest); + + char hexdigest[33]; + for (int i = 0; i < 16; i++) + { + int v = digest[i] >> 4; + hexdigest[i * 2] = v < 10 ? ('0' + v) : ('a' + v - 10); + v = digest[i] & 15; + hexdigest[i * 2 + 1] = v < 10 ? ('0' + v) : ('a' + v - 10); + } + hexdigest[32] = 0; + return hexdigest; +} + +static FString CreateProgramCacheName(bool create) +{ + FString path = M_GetCachePath(create); + if (create) CreatePath(path); + path << "/shadercache.zdsc"; + return path; +} + +static void LoadShaders() +{ + static bool loaded = false; + if (loaded) + return; + loaded = true; + + try + { + FString path = CreateProgramCacheName(false); + FileReader fr; + if (!fr.OpenFile(path)) + I_Error("Could not open shader file"); + + char magic[4]; + fr.Read(magic, 4); + if (memcmp(magic, ShaderMagic, 4) != 0) + I_Error("Not a shader cache file"); + + uint32_t count = fr.ReadUInt32(); + if (count > 512) + I_Error("Too many shaders cached"); + + for (uint32_t i = 0; i < count; i++) + { + char hexdigest[33]; + if (fr.Read(hexdigest, 32) != 32) + I_Error("Read error"); + hexdigest[32] = 0; + + std::unique_ptr binary(new ProgramBinary()); + binary->format = fr.ReadUInt32(); + uint32_t size = fr.ReadUInt32(); + if (size > 1024 * 1024) + I_Error("Shader too big, probably file corruption"); + + binary->data.Resize(size); + if (fr.Read(binary->data.Data(), binary->data.Size()) != binary->data.Size()) + I_Error("Read error"); + + ShaderCache[hexdigest] = std::move(binary); + } + } + catch (...) + { + ShaderCache.clear(); + } +} + +static void SaveShaders() +{ + FString path = CreateProgramCacheName(true); + std::unique_ptr fw(FileWriter::Open(path)); + if (fw) + { + uint32_t count = (uint32_t)ShaderCache.size(); + fw->Write(ShaderMagic, 4); + fw->Write(&count, sizeof(uint32_t)); + for (const auto &it : ShaderCache) + { + uint32_t size = it.second->data.Size(); + fw->Write(it.first.GetChars(), 32); + fw->Write(&it.second->format, sizeof(uint32_t)); + fw->Write(&size, sizeof(uint32_t)); + fw->Write(it.second->data.Data(), it.second->data.Size()); + } + } +} + +TArray LoadCachedProgramBinary(const FString &vertex, const FString &fragment, uint32_t &binaryFormat) +{ + LoadShaders(); + + auto it = ShaderCache.find(CalcProgramBinaryChecksum(vertex, fragment)); + if (it != ShaderCache.end()) + { + binaryFormat = it->second->format; + return it->second->data; + } + else + { + binaryFormat = 0; + return {}; + } +} + +void SaveCachedProgramBinary(const FString &vertex, const FString &fragment, const TArray &binary, uint32_t binaryFormat) +{ + auto &entry = ShaderCache[CalcProgramBinaryChecksum(vertex, fragment)]; + entry.reset(new ProgramBinary()); + entry->format = binaryFormat; + entry->data = binary; + + SaveShaders(); +} + +bool FShader::Configure(const char* name, const char* vert_prog_lump, const char* fragprog, const char* fragprog2, const char* light_fragprog, const char* defines) +{ + mVertProg = vert_prog_lump; + mFragProg = fragprog; + mFragProg2 = fragprog2; + mLightProg = light_fragprog; + mDefinesBase = defines; + + return true; +} + +void FShader::LoadVariant() +{ + //mDefinesBase + Load(mName.GetChars(), mVertProg, mFragProg, mFragProg2, mLightProg, mDefinesBase); +} + +bool FShader::Load(const char * name, const char * vert_prog_lump_, const char * frag_prog_lump_, const char * proc_prog_lump_, const char * light_fragprog_, const char * defines) +{ + ShaderVariantData* shaderData = new ShaderVariantData(); + + FString vert_prog_lump = vert_prog_lump_; + FString frag_prog_lump = frag_prog_lump_; + FString proc_prog_lump = proc_prog_lump_; + FString light_fragprog = light_fragprog_; + + vert_prog_lump.Substitute("shaders/", "shaders_gles/"); + frag_prog_lump.Substitute("shaders/", "shaders_gles/"); + proc_prog_lump.Substitute("shaders/", "shaders_gles/"); + light_fragprog.Substitute("shaders/", "shaders_gles/"); + + //light_fragprog.Substitute("material_pbr", "material_normal"); + + if(light_fragprog.Len()) + light_fragprog = "shaders_gles/glsl/material_normal.fp"; // NOTE: Always use normal material for now, ignore others + + + static char buffer[10000]; + FString error; + + FString i_data = GetGLSLPrecision(); + + i_data += R"( + + // light buffers + uniform vec4 lights[MAXIMUM_LIGHT_VECTORS]; + + uniform mat4 ProjectionMatrix; + uniform mat4 ViewMatrix; + uniform mat4 NormalViewMatrix; + + uniform vec4 uCameraPos; + uniform vec4 uClipLine; + + uniform float uGlobVis; // uGlobVis = R_GetGlobVis(r_visibility) / 32.0 + uniform int uPalLightLevels; + uniform int uViewHeight; // Software fuzz scaling + uniform float uClipHeight; + uniform float uClipHeightDirection; + uniform int uShadowmapFilter; + + uniform int uTextureMode; + uniform vec2 uClipSplit; + uniform float uAlphaThreshold; + + // colors + uniform vec4 uObjectColor; + uniform vec4 uObjectColor2; + uniform vec4 uDynLightColor; + uniform vec4 uAddColor; + uniform vec4 uTextureBlendColor; + uniform vec4 uTextureModulateColor; + uniform vec4 uTextureAddColor; + uniform vec4 uFogColor; + uniform float uDesaturationFactor; + uniform float uInterpolationFactor; + + // Glowing walls stuff + uniform vec4 uGlowTopPlane; + uniform vec4 uGlowTopColor; + uniform vec4 uGlowBottomPlane; + uniform vec4 uGlowBottomColor; + + uniform vec4 uGradientTopPlane; + uniform vec4 uGradientBottomPlane; + + uniform vec4 uSplitTopPlane; + uniform vec4 uSplitBottomPlane; + + uniform vec4 uDetailParms; + // Lighting + Fog + uniform vec4 uLightAttr; + #define uLightLevel uLightAttr.a + #define uFogDensity uLightAttr.b + #define uLightFactor uLightAttr.g + #define uLightDist uLightAttr.r + //uniform int uFogEnabled; + + // dynamic lights + uniform ivec4 uLightRange; + + // Blinn glossiness and specular level + uniform vec2 uSpecularMaterial; + + // matrices + uniform mat4 ModelMatrix; + uniform mat4 NormalModelMatrix; + uniform mat4 TextureMatrix; + + uniform vec4 uFixedColormapStart; + uniform vec4 uFixedColormapRange; + + // textures + uniform sampler2D tex; + uniform sampler2D ShadowMap; + uniform sampler2D texture2; + uniform sampler2D texture3; + uniform sampler2D texture4; + uniform sampler2D texture5; + uniform sampler2D texture6; + uniform sampler2D texture7; + uniform sampler2D texture8; + uniform sampler2D texture9; + uniform sampler2D texture10; + uniform sampler2D texture11; + + // timer data + uniform float timer; + + // material types + #if defined(SPECULAR) + #define normaltexture texture2 + #define speculartexture texture3 + #define brighttexture texture4 + #define detailtexture texture5 + #define glowtexture texture6 + #elif defined(PBR) + #define normaltexture texture2 + #define metallictexture texture3 + #define roughnesstexture texture4 + #define aotexture texture5 + #define brighttexture texture6 + #define detailtexture texture7 + #define glowtexture texture8 + #else + #define brighttexture texture2 + #define detailtexture texture3 + #define glowtexture texture4 + #endif + )"; + +#ifdef NPOT_EMULATION + i_data += "#define NPOT_EMULATION\nuniform vec2 uNpotEmulation;\n"; +#endif + + int vp_lump = fileSystem.CheckNumForFullName(vert_prog_lump, 0); + if (vp_lump == -1) I_Error("Unable to load '%s'", vert_prog_lump.GetChars()); + FileData vp_data = fileSystem.ReadFile(vp_lump); + + int fp_lump = fileSystem.CheckNumForFullName(frag_prog_lump, 0); + if (fp_lump == -1) I_Error("Unable to load '%s'", frag_prog_lump.GetChars()); + FileData fp_data = fileSystem.ReadFile(fp_lump); + + + +// +// The following code uses GetChars on the strings to get rid of terminating 0 characters. Do not remove or the code may break! +// + FString vp_comb; + + assert(screen->mLights != NULL); + + bool lightbuffertype = screen->mLights->GetBufferType(); + unsigned int lightbuffersize = screen->mLights->GetBlockSize(); + + vp_comb.Format("#version 100\n#define NUM_UBO_LIGHTS %d\n#define NO_CLIPDISTANCE_SUPPORT\n", lightbuffersize); + + FString fp_comb = vp_comb; + vp_comb << defines << i_data.GetChars(); + fp_comb << "$placeholder$\n" << defines << i_data.GetChars(); + + vp_comb << "#line 1\n"; + fp_comb << "#line 1\n"; + + vp_comb << RemoveLayoutLocationDecl(vp_data.GetString(), "out").GetChars() << "\n"; + fp_comb << RemoveLayoutLocationDecl(fp_data.GetString(), "in").GetChars() << "\n"; + FString placeholder = "\n"; + + if (proc_prog_lump.Len()) + { + fp_comb << "#line 1\n"; + + if (*proc_prog_lump != '#') + { + int pp_lump = fileSystem.CheckNumForFullName(proc_prog_lump); + if (pp_lump == -1) I_Error("Unable to load '%s'", proc_prog_lump.GetChars()); + FileData pp_data = fileSystem.ReadFile(pp_lump); + + if (pp_data.GetString().IndexOf("ProcessMaterial") < 0 && pp_data.GetString().IndexOf("SetupMaterial") < 0) + { + // this looks like an old custom hardware shader. + + if (pp_data.GetString().IndexOf("GetTexCoord") >= 0) + { + int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultmat2.fp", 0); + if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultmat2.fp"); + FileData pl_data = fileSystem.ReadFile(pl_lump); + fp_comb << "\n" << pl_data.GetString().GetChars(); + } + else + { + int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultmat.fp", 0); + if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultmat.fp"); + FileData pl_data = fileSystem.ReadFile(pl_lump); + fp_comb << "\n" << pl_data.GetString().GetChars(); + + if (pp_data.GetString().IndexOf("ProcessTexel") < 0) + { + // this looks like an even older custom hardware shader. + // We need to replace the ProcessTexel call to make it work. + + fp_comb.Substitute("material.Base = ProcessTexel();", "material.Base = Process(vec4(1.0));"); + } + } + + if (pp_data.GetString().IndexOf("ProcessLight") >= 0) + { + // The ProcessLight signatured changed. Forward to the old one. + fp_comb << "\nvec4 ProcessLight(vec4 color);\n"; + fp_comb << "\nvec4 ProcessLight(Material material, vec4 color) { return ProcessLight(color); }\n"; + } + } + + fp_comb << RemoveLegacyUserUniforms(pp_data.GetString()).GetChars(); + fp_comb.Substitute("gl_TexCoord[0]", "vTexCoord"); // fix old custom shaders. + + if (pp_data.GetString().IndexOf("ProcessLight") < 0) + { + int pl_lump = fileSystem.CheckNumForFullName("shaders_gles/glsl/func_defaultlight.fp", 0); + if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders_gles/glsl/func_defaultlight.fp"); + FileData pl_data = fileSystem.ReadFile(pl_lump); + fp_comb << "\n" << pl_data.GetString().GetChars(); + } + + // ProcessMaterial must be considered broken because it requires the user to fill in data they possibly cannot know all about. + if (pp_data.GetString().IndexOf("ProcessMaterial") >= 0 && pp_data.GetString().IndexOf("SetupMaterial") < 0) + { + // This reactivates the old logic and disables all features that cannot be supported with that method. + placeholder << "#define LEGACY_USER_SHADER\n"; + } + } + else + { + // Proc_prog_lump is not a lump name but the source itself (from generated shaders) + fp_comb << proc_prog_lump.GetChars() + 1; + } + } + fp_comb.Substitute("$placeholder$", placeholder); + + if (light_fragprog.Len()) + { + int pp_lump = fileSystem.CheckNumForFullName(light_fragprog, 0); + if (pp_lump == -1) I_Error("Unable to load '%s'", light_fragprog.GetChars()); + FileData pp_data = fileSystem.ReadFile(pp_lump); + fp_comb << pp_data.GetString().GetChars() << "\n"; + } + + if (gles.flags & RFL_NO_CLIP_PLANES) + { + // On ATI's GL3 drivers we have to disable gl_ClipDistance because it's hopelessly broken. + // This will cause some glitches and regressions but is the only way to avoid total display garbage. + vp_comb.Substitute("gl_ClipDistance", "//"); + } + + shaderData->hShader = glCreateProgram(); + + uint32_t binaryFormat = 0; + TArray binary; + if (IsShaderCacheActive()) + binary = LoadCachedProgramBinary(vp_comb, fp_comb, binaryFormat); + + bool linked = false; + + if (!linked) + { + shaderData->hVertProg = glCreateShader(GL_VERTEX_SHADER); + shaderData->hFragProg = glCreateShader(GL_FRAGMENT_SHADER); + + int vp_size = (int)vp_comb.Len(); + int fp_size = (int)fp_comb.Len(); + + const char *vp_ptr = vp_comb.GetChars(); + const char *fp_ptr = fp_comb.GetChars(); + + glShaderSource(shaderData->hVertProg, 1, &vp_ptr, &vp_size); + glShaderSource(shaderData->hFragProg, 1, &fp_ptr, &fp_size); + + glCompileShader(shaderData->hVertProg); + glCompileShader(shaderData->hFragProg); + + glAttachShader(shaderData->hShader, shaderData->hVertProg); + glAttachShader(shaderData->hShader, shaderData->hFragProg); + + + glBindAttribLocation(shaderData->hShader, VATTR_VERTEX, "aPosition"); + glBindAttribLocation(shaderData->hShader, VATTR_TEXCOORD, "aTexCoord"); + glBindAttribLocation(shaderData->hShader, VATTR_COLOR, "aColor"); + glBindAttribLocation(shaderData->hShader, VATTR_VERTEX2, "aVertex2"); + glBindAttribLocation(shaderData->hShader, VATTR_NORMAL, "aNormal"); + glBindAttribLocation(shaderData->hShader, VATTR_NORMAL2, "aNormal2"); + + + glLinkProgram(shaderData->hShader); + + glGetShaderInfoLog(shaderData->hVertProg, 10000, NULL, buffer); + if (*buffer) + { + error << "Vertex shader:\n" << buffer << "\n"; + } + glGetShaderInfoLog(shaderData->hFragProg, 10000, NULL, buffer); + if (*buffer) + { + error << "Fragment shader:\n" << buffer << "\n"; + } + + glGetProgramInfoLog(shaderData->hShader, 10000, NULL, buffer); + if (*buffer) + { + error << "Linking:\n" << buffer << "\n"; + } + GLint status = 0; + glGetProgramiv(shaderData->hShader, GL_LINK_STATUS, &status); + linked = (status == GL_TRUE); + + if (!linked) + { + // only print message if there's an error. + I_Error("Init Shader '%s':\n%s\n", name, error.GetChars()); + } + } + else + { + shaderData->hVertProg = 0; + shaderData->hFragProg = 0; + } + + shaderData->muProjectionMatrix.Init(shaderData->hShader, "ProjectionMatrix"); + shaderData->muViewMatrix.Init(shaderData->hShader, "ViewMatrix"); + shaderData->muNormalViewMatrix.Init(shaderData->hShader, "NormalViewMatrix"); + + //shaderData->ProjectionMatrix_index = glGetUniformLocation(shaderData->hShader, "ProjectionMatrix"); + //shaderData->ViewMatrix_index = glGetUniformLocation(shaderData->hShader, "ViewMatrix"); + //shaderData->NormalViewMatrix_index = glGetUniformLocation(shaderData->hShader, "NormalViewMatrix"); + + shaderData->muCameraPos.Init(shaderData->hShader, "uCameraPos"); + shaderData->muClipLine.Init(shaderData->hShader, "uClipLine"); + + shaderData->muGlobVis.Init(shaderData->hShader, "uGlobVis"); + shaderData->muPalLightLevels.Init(shaderData->hShader, "uPalLightLevels"); + shaderData->muViewHeight.Init(shaderData->hShader, "uViewHeight"); + shaderData->muClipHeight.Init(shaderData->hShader, "uClipHeight"); + shaderData->muClipHeightDirection.Init(shaderData->hShader, "uClipHeightDirection"); + shaderData->muShadowmapFilter.Init(shaderData->hShader, "uShadowmapFilter"); + + //// + + shaderData->muDesaturation.Init(shaderData->hShader, "uDesaturationFactor"); + shaderData->muFogEnabled.Init(shaderData->hShader, "uFogEnabled"); + shaderData->muTextureMode.Init(shaderData->hShader, "uTextureMode"); + shaderData->muLightParms.Init(shaderData->hShader, "uLightAttr"); + shaderData->muClipSplit.Init(shaderData->hShader, "uClipSplit"); + shaderData->muLightRange.Init(shaderData->hShader, "uLightRange"); + shaderData->muFogColor.Init(shaderData->hShader, "uFogColor"); + shaderData->muDynLightColor.Init(shaderData->hShader, "uDynLightColor"); + shaderData->muObjectColor.Init(shaderData->hShader, "uObjectColor"); + shaderData->muObjectColor2.Init(shaderData->hShader, "uObjectColor2"); + shaderData->muGlowBottomColor.Init(shaderData->hShader, "uGlowBottomColor"); + shaderData->muGlowTopColor.Init(shaderData->hShader, "uGlowTopColor"); + shaderData->muGlowBottomPlane.Init(shaderData->hShader, "uGlowBottomPlane"); + shaderData->muGlowTopPlane.Init(shaderData->hShader, "uGlowTopPlane"); + shaderData->muGradientBottomPlane.Init(shaderData->hShader, "uGradientBottomPlane"); + shaderData->muGradientTopPlane.Init(shaderData->hShader, "uGradientTopPlane"); + shaderData->muSplitBottomPlane.Init(shaderData->hShader, "uSplitBottomPlane"); + shaderData->muSplitTopPlane.Init(shaderData->hShader, "uSplitTopPlane"); + shaderData->muDetailParms.Init(shaderData->hShader, "uDetailParms"); + shaderData->muInterpolationFactor.Init(shaderData->hShader, "uInterpolationFactor"); + shaderData->muAlphaThreshold.Init(shaderData->hShader, "uAlphaThreshold"); + shaderData->muSpecularMaterial.Init(shaderData->hShader, "uSpecularMaterial"); + shaderData->muAddColor.Init(shaderData->hShader, "uAddColor"); + shaderData->muTextureAddColor.Init(shaderData->hShader, "uTextureAddColor"); + shaderData->muTextureModulateColor.Init(shaderData->hShader, "uTextureModulateColor"); + shaderData->muTextureBlendColor.Init(shaderData->hShader, "uTextureBlendColor"); + shaderData->muTimer.Init(shaderData->hShader, "timer"); +#ifdef NPOT_EMULATION + shaderData->muNpotEmulation.Init(shaderData->hShader, "uNpotEmulation"); +#endif + shaderData->muFixedColormapStart.Init(shaderData->hShader, "uFixedColormapStart"); + shaderData->muFixedColormapRange.Init(shaderData->hShader, "uFixedColormapRange"); + + shaderData->lights_index = glGetUniformLocation(shaderData->hShader, "lights"); + shaderData->modelmatrix_index = glGetUniformLocation(shaderData->hShader, "ModelMatrix"); + shaderData->texturematrix_index = glGetUniformLocation(shaderData->hShader, "TextureMatrix"); + shaderData->normalmodelmatrix_index = glGetUniformLocation(shaderData->hShader, "NormalModelMatrix"); + + + glUseProgram(shaderData->hShader); + + // set up other texture units (if needed by the shader) + for (int i = 2; i<16; i++) + { + char stringbuf[20]; + mysnprintf(stringbuf, 20, "texture%d", i); + int tempindex = glGetUniformLocation(shaderData->hShader, stringbuf); + if (tempindex > 0) glUniform1i(tempindex, i - 1); + } + + int shadowmapindex = glGetUniformLocation(shaderData->hShader, "ShadowMap"); + if (shadowmapindex > 0) glUniform1i(shadowmapindex, 16); + + glUseProgram(0); + + cur = shaderData; + + return linked; +} + +//========================================================================== +// +// +// +//========================================================================== + +FShader::~FShader() +{ + /* + glDeleteProgram(hShader); + if (hVertProg != 0) + glDeleteShader(hVertProg); + if (hFragProg != 0) + glDeleteShader(hFragProg); + */ +} + + +//========================================================================== +// +// +// +//========================================================================== + +bool FShader::Bind(ShaderFlavourData& flavour) +{ + uint32_t tag = CreateShaderTag(flavour); + + auto pos = variants.find(tag); + + if (pos == variants.end()) + { + FString variantConfig = "\n"; + + variantConfig.AppendFormat("#define MAXIMUM_LIGHT_VECTORS %d\n", gles.numlightvectors); + variantConfig.AppendFormat("#define DEF_TEXTURE_MODE %d\n", flavour.textureMode); + variantConfig.AppendFormat("#define DEF_TEXTURE_FLAGS %d\n", flavour.texFlags); + variantConfig.AppendFormat("#define DEF_BLEND_FLAGS %d\n", flavour.blendFlags); + variantConfig.AppendFormat("#define DEF_FOG_2D %d\n", flavour.twoDFog); + variantConfig.AppendFormat("#define DEF_FOG_ENABLED %d\n", flavour.fogEnabled); + variantConfig.AppendFormat("#define DEF_FOG_RADIAL %d\n", flavour.fogEquationRadial); + variantConfig.AppendFormat("#define DEF_FOG_COLOURED %d\n", flavour.colouredFog); + variantConfig.AppendFormat("#define DEF_USE_U_LIGHT_LEVEL %d\n", flavour.useULightLevel); + + variantConfig.AppendFormat("#define DEF_DO_DESATURATE %d\n", flavour.doDesaturate); + + variantConfig.AppendFormat("#define DEF_DYNAMIC_LIGHTS_MOD %d\n", flavour.dynLightsMod); + variantConfig.AppendFormat("#define DEF_DYNAMIC_LIGHTS_SUB %d\n", flavour.dynLightsSub); + variantConfig.AppendFormat("#define DEF_DYNAMIC_LIGHTS_ADD %d\n", flavour.dynLightsAdd); + + variantConfig.AppendFormat("#define DEF_USE_OBJECT_COLOR_2 %d\n", flavour.useObjectColor2); + variantConfig.AppendFormat("#define DEF_USE_GLOW_TOP_COLOR %d\n", flavour.useGlowTopColor); + variantConfig.AppendFormat("#define DEF_USE_GLOW_BOTTOM_COLOR %d\n", flavour.useGlowBottomColor); + + variantConfig.AppendFormat("#define DEF_USE_COLOR_MAP %d\n", flavour.useColorMap); + variantConfig.AppendFormat("#define DEF_BUILD_LIGHTING %d\n", flavour.buildLighting); + variantConfig.AppendFormat("#define DEF_BANDED_SW_LIGHTING %d\n", flavour.bandedSwLight); + + variantConfig.AppendFormat("#define USE_GLSL_V100 %d\n", gles.forceGLSLv100); + +#ifdef NPOT_EMULATION + variantConfig.AppendFormat("#define DEF_NPOT_EMULATION %d\n", flavour.npotEmulation); +#endif + + // Printf("Shader: %s, %08x %s", mFragProg2.GetChars(), tag, variantConfig.GetChars()); + + Load(mName.GetChars(), mVertProg, mFragProg, mFragProg2, mLightProg, mDefinesBase + variantConfig); + + if (variants.insert(std::make_pair(tag, cur)).second == false) + { + Printf("ERROR INSERTING"); + } + } + else + { + cur = pos->second; + } + + GLRenderer->mShaderManager->SetActiveShader(this->cur); + return true; +} + +//========================================================================== +// +// Since all shaders are REQUIRED, any error here needs to be fatal +// +//========================================================================== + +FShader *FShaderCollection::Compile (const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType) +{ + FString defines; + defines += shaderdefines; + // this can't be in the shader code due to ATI strangeness. + if (!usediscard) defines += "#define NO_ALPHATEST\n"; + + FShader *shader = NULL; + try + { + shader = new FShader(ShaderName); + if (!shader->Configure(ShaderName, "shaders_gles/glsl/main.vp", "shaders_gles/glsl/main.fp", ShaderPath, LightModePath, defines.GetChars())) + { + I_FatalError("Unable to load shader %s\n", ShaderName); + } + } + catch(CRecoverableError &err) + { + if (shader != NULL) delete shader; + shader = NULL; + I_FatalError("Unable to load shader %s:\n%s\n", ShaderName, err.GetMessage()); + } + return shader; +} + +//========================================================================== +// +// +// +//========================================================================== + +FShaderManager::FShaderManager() +{ + for (int passType = 0; passType < MAX_PASS_TYPES; passType++) + mPassShaders.Push(new FShaderCollection((EPassType)passType)); +} + +FShaderManager::~FShaderManager() +{ + glUseProgram(0); + mActiveShader = NULL; + + for (auto collection : mPassShaders) + delete collection; +} + +void FShaderManager::SetActiveShader(FShader::ShaderVariantData *sh) +{ + if (mActiveShader != sh) + { + glUseProgram(sh!= NULL? sh->GetHandle() : 0); + mActiveShader = sh; + } +} + +FShader *FShaderManager::BindEffect(int effect, EPassType passType, ShaderFlavourData &flavour) +{ + if (passType < mPassShaders.Size()) + return mPassShaders[passType]->BindEffect(effect, flavour); + else + return nullptr; +} + +FShader *FShaderManager::Get(unsigned int eff, bool alphateston, EPassType passType) +{ + if (passType < mPassShaders.Size()) + return mPassShaders[passType]->Get(eff, alphateston); + else + return nullptr; +} + +//========================================================================== +// +// +// +//========================================================================== + +FShaderCollection::FShaderCollection(EPassType passType) +{ + CompileShaders(passType); +} + +//========================================================================== +// +// +// +//========================================================================== + +FShaderCollection::~FShaderCollection() +{ + Clean(); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FShaderCollection::CompileShaders(EPassType passType) +{ + mMaterialShaders.Clear(); + mMaterialShadersNAT.Clear(); + for (int i = 0; i < MAX_EFFECTS; i++) + { + mEffectShaders[i] = NULL; + } + + for(int i=0;defaultshaders[i].ShaderName != NULL;i++) + { + FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, true, passType); + mMaterialShaders.Push(shc); + if (i < SHADER_NoTexture) + { + FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc, defaultshaders[i].lightfunc, defaultshaders[i].Defines, false, passType); + mMaterialShadersNAT.Push(shc); + } + } + +#if 0 + for(unsigned i = 0; i < usershaders.Size(); i++) + { + FString name = ExtractFileBase(usershaders[i].shader); + FString defines = defaultshaders[usershaders[i].shaderType].Defines + usershaders[i].defines; + FShader *shc = Compile(name, usershaders[i].shader, defaultshaders[usershaders[i].shaderType].lightfunc, defines, true, passType); + mMaterialShaders.Push(shc); + } +#endif + + for(int i=0;iConfigure(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1, + effectshaders[i].fp2, effectshaders[i].fp3, effectshaders[i].defines)) + { + delete eff; + } + else mEffectShaders[i] = eff; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void FShaderCollection::Clean() +{ + for (unsigned int i = 0; i < mMaterialShadersNAT.Size(); i++) + { + if (mMaterialShadersNAT[i] != NULL) delete mMaterialShadersNAT[i]; + } + for (unsigned int i = 0; i < mMaterialShaders.Size(); i++) + { + if (mMaterialShaders[i] != NULL) delete mMaterialShaders[i]; + } + for (int i = 0; i < MAX_EFFECTS; i++) + { + if (mEffectShaders[i] != NULL) delete mEffectShaders[i]; + mEffectShaders[i] = NULL; + } + mMaterialShaders.Clear(); + mMaterialShadersNAT.Clear(); +} + +//========================================================================== +// +// +// +//========================================================================== + +int FShaderCollection::Find(const char * shn) +{ + FName sfn = shn; + + for(unsigned int i=0;imName == sfn) + { + return i; + } + } + return -1; +} + + +//========================================================================== +// +// +// +//========================================================================== + +FShader *FShaderCollection::BindEffect(int effect, ShaderFlavourData& flavour) +{ + if (effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[effect] != NULL) + { + mEffectShaders[effect]->Bind(flavour); + return mEffectShaders[effect]; + } + return NULL; +} + + +//========================================================================== +// +// +// +//========================================================================== + +void gl_DestroyUserShaders() +{ + // todo +} + +} diff --git a/src/common/rendering/gles/gles_shader.h b/src/common/rendering/gles/gles_shader.h new file mode 100644 index 0000000000..7f07c8615b --- /dev/null +++ b/src/common/rendering/gles/gles_shader.h @@ -0,0 +1,484 @@ +// +//--------------------------------------------------------------------------- +// +// Copyright(C) 2004-2016 Christoph Oelckers +// All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with this program. If not, see http://www.gnu.org/licenses/ +// +//-------------------------------------------------------------------------- +// + +#ifndef __GL_SHADERS_H__ +#define __GL_SHADERS_H__ + +#include + +#include "gles_renderstate.h" +#include "name.h" + +extern bool gl_shaderactive; + +struct HWViewpointUniforms; + +namespace OpenGLESRenderer +{ + class FShaderCollection; + +//========================================================================== +// +// +//========================================================================== + +class FUniform1i +{ + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + } + + void Set(int newvalue) + { + glUniform1i(mIndex, newvalue); + } +}; + +class FBufferedUniform1i +{ + int mBuffer; + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + mBuffer = 0; + } + + void Set(int newvalue) + { + if (newvalue != mBuffer) + { + mBuffer = newvalue; + glUniform1i(mIndex, newvalue); + } + } +}; + +class FBufferedUniform4i +{ + int mBuffer[4]; + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + memset(mBuffer, 0, sizeof(mBuffer)); + } + + void Set(const int *newvalue) + { + if (memcmp(newvalue, mBuffer, sizeof(mBuffer))) + { + memcpy(mBuffer, newvalue, sizeof(mBuffer)); + glUniform4iv(mIndex, 1, newvalue); + } + } +}; + +class FBufferedUniform1f +{ + float mBuffer; + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + mBuffer = 0; + } + + void Set(float newvalue) + { + if (newvalue != mBuffer) + { + mBuffer = newvalue; + glUniform1f(mIndex, newvalue); + } + } +}; + +class FBufferedUniform2f +{ + float mBuffer[2]; + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + memset(mBuffer, 0, sizeof(mBuffer)); + } + + void Set(const float *newvalue) + { + if (memcmp(newvalue, mBuffer, sizeof(mBuffer))) + { + memcpy(mBuffer, newvalue, sizeof(mBuffer)); + glUniform2fv(mIndex, 1, newvalue); + } + } + + void Set(float f1, float f2) + { + if (mBuffer[0] != f1 || mBuffer[1] != f2) + { + mBuffer[0] = f1; + mBuffer[1] = f2; + glUniform2fv(mIndex, 1, mBuffer); + } + } + +}; + +class FBufferedUniform4f +{ + float mBuffer[4]; + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + memset(mBuffer, 0, sizeof(mBuffer)); + } + + void Set(const float *newvalue) + { + if (memcmp(newvalue, mBuffer, sizeof(mBuffer))) + { + memcpy(mBuffer, newvalue, sizeof(mBuffer)); + glUniform4fv(mIndex, 1, newvalue); + } + } +}; + +class FUniform4f +{ + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + } + + void Set(const float *newvalue) + { + glUniform4fv(mIndex, 1, newvalue); + } + + void Set(float a, float b, float c, float d) + { + glUniform4f(mIndex, a, b, c, d); + } + + void Set(PalEntry newvalue) + { + glUniform4f(mIndex, newvalue.r / 255.f, newvalue.g / 255.f, newvalue.b / 255.f, newvalue.a / 255.f); + } + +}; + +class FBufferedUniformPE +{ + FVector4PalEntry mBuffer; + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + mBuffer = 0; + } + + void Set(const FVector4PalEntry &newvalue) + { + if (newvalue != mBuffer) + { + mBuffer = newvalue; + glUniform4f(mIndex, newvalue.r, newvalue.g, newvalue.b, newvalue.a); + } + } +}; + +class FBufferedUniformMat4fv +{ + VSMatrix mBuffer; + int mIndex; + +public: + void Init(GLuint hShader, const GLchar* name) + { + mIndex = glGetUniformLocation(hShader, name); + mBuffer = 0; + } + + void Set(const VSMatrix* newvalue) + { + //if (memcmp(newvalue, &mBuffer, sizeof(mBuffer))) // Breaks 2D menu for some reason.. + { + mBuffer = *newvalue; + glUniformMatrix4fv(mIndex, 1, false, (float*)newvalue); + } + } +}; + +class ShaderFlavourData +{ +public: + int textureMode; + int texFlags; + int blendFlags; + bool twoDFog; + bool fogEnabled; + bool fogEquationRadial; + bool colouredFog; + bool doDesaturate; + bool dynLightsMod; + bool dynLightsSub; + bool dynLightsAdd; + bool useULightLevel; + bool useObjectColor2; + bool useGlowTopColor; + bool useGlowBottomColor; + bool useColorMap; + + bool buildLighting; + bool bandedSwLight; + +#ifdef NPOT_EMULATION + bool npotEmulation; +#endif +}; + +class FShader +{ + friend class FShaderCollection; + friend class FGLRenderState; + + FName mName; + + FString mVertProg; + FString mFragProg; + FString mFragProg2; + FString mLightProg; + FString mDefinesBase; + + ///// +public: class ShaderVariantData + { + public: + + unsigned int hShader = 0; + unsigned int hVertProg = 0; + unsigned int hFragProg = 0; + + //int ProjectionMatrix_index = 0; + //int ViewMatrix_index = 0; + //int NormalViewMatrix_index = 0; + + FBufferedUniformMat4fv muProjectionMatrix; + FBufferedUniformMat4fv muViewMatrix; + FBufferedUniformMat4fv muNormalViewMatrix; + + FUniform4f muCameraPos; + FUniform4f muClipLine; + + FBufferedUniform1f muGlobVis; + FBufferedUniform1i muPalLightLevels; + FBufferedUniform1i muViewHeight; + FBufferedUniform1f muClipHeight; + FBufferedUniform1f muClipHeightDirection; + FBufferedUniform1i muShadowmapFilter; + ///// + + FBufferedUniform1f muDesaturation; + FBufferedUniform1i muFogEnabled; + FBufferedUniform1i muTextureMode; + FBufferedUniform4f muLightParms; + FBufferedUniform2f muClipSplit; + FBufferedUniform4i muLightRange; + FBufferedUniformPE muFogColor; + FBufferedUniform4f muDynLightColor; + FBufferedUniformPE muObjectColor; + FBufferedUniformPE muObjectColor2; + FBufferedUniformPE muAddColor; + FBufferedUniformPE muTextureBlendColor; + FBufferedUniformPE muTextureModulateColor; + FBufferedUniformPE muTextureAddColor; + FUniform4f muGlowBottomColor; + FUniform4f muGlowTopColor; + FUniform4f muGlowBottomPlane; + FUniform4f muGlowTopPlane; + FUniform4f muGradientBottomPlane; + FUniform4f muGradientTopPlane; + FUniform4f muSplitBottomPlane; + FUniform4f muSplitTopPlane; + FUniform4f muDetailParms; + FBufferedUniform1f muInterpolationFactor; + FBufferedUniform1f muAlphaThreshold; + FBufferedUniform2f muSpecularMaterial; + FBufferedUniform1f muTimer; +#ifdef NPOT_EMULATION + FBufferedUniform2f muNpotEmulation; +#endif + FUniform4f muFixedColormapStart; + FUniform4f muFixedColormapRange; + + + int lights_index = 0; + int modelmatrix_index = 0; + int normalmodelmatrix_index = 0; + int texturematrix_index = 0; + + int currentglowstate = 0; + int currentgradientstate = 0; + int currentsplitstate = 0; + int currentcliplinestate = 0; + int currentfixedcolormap = 0; + bool currentTextureMatrixState = true;// by setting the matrix state to 'true' it is guaranteed to be set the first time the render state gets applied. + bool currentModelMatrixState = true; + + unsigned int GetHandle() const { return hShader; } + }; + + std::map variants; + + ShaderVariantData* cur = 0; + +public: + FShader(const char *name) + : mName(name) + { + + } + + ~FShader(); + + bool Load(const char * name, const char * vert_prog_lump, const char * fragprog, const char * fragprog2, const char * light_fragprog, const char *defines); + bool Configure(const char* name, const char* vert_prog_lump, const char* fragprog, const char* fragprog2, const char* light_fragprog, const char* defines); + + void LoadVariant(); + + + uint32_t CreateShaderTag(ShaderFlavourData &flavour) + { + uint32_t tag = 0; + tag |= (flavour.textureMode & 0x7); + + tag |= (flavour.texFlags & 7) << 3; + + tag |= (flavour.blendFlags & 7) << 6; + + tag |= (flavour.twoDFog & 1) << 7; + tag |= (flavour.fogEnabled & 1) << 8; + tag |= (flavour.fogEquationRadial & 1) << 9; + tag |= (flavour.colouredFog & 1) << 10; + + tag |= (flavour.doDesaturate & 1) << 11; + + tag |= (flavour.dynLightsMod & 1) << 12; + tag |= (flavour.dynLightsSub & 1) << 13; + tag |= (flavour.dynLightsAdd & 1) << 14; + tag |= (flavour.useULightLevel & 1) << 15; + tag |= (flavour.useObjectColor2 & 1) << 16; + tag |= (flavour.useGlowTopColor & 1) << 17; + tag |= (flavour.useGlowBottomColor & 1) << 18; + tag |= (flavour.useColorMap & 1) << 19; + tag |= (flavour.buildLighting & 1) << 20; + tag |= (flavour.bandedSwLight & 1) << 21; + +#ifdef NPOT_EMULATION + tag |= (flavour.npotEmulation & 1) << 22; +#endif + return tag; + } + + bool Bind(ShaderFlavourData& flavour); + + +}; + +//========================================================================== +// +// The global shader manager +// +//========================================================================== +class FShaderManager +{ +public: + FShaderManager(); + ~FShaderManager(); + + FShader *BindEffect(int effect, EPassType passType, ShaderFlavourData& flavour); + FShader *Get(unsigned int eff, bool alphateston, EPassType passType); + + void SetActiveShader(FShader::ShaderVariantData *sh); +private: + + FShader::ShaderVariantData *mActiveShader = nullptr; + TArray mPassShaders; + + friend class FShader; +}; + +class FShaderCollection +{ + TArray mMaterialShaders; + TArray mMaterialShadersNAT; + FShader *mEffectShaders[MAX_EFFECTS]; + + void Clean(); + void CompileShaders(EPassType passType); + +public: + FShaderCollection(EPassType passType); + ~FShaderCollection(); + FShader *Compile(const char *ShaderName, const char *ShaderPath, const char *LightModePath, const char *shaderdefines, bool usediscard, EPassType passType); + int Find(const char *mame); + FShader *BindEffect(int effect, ShaderFlavourData& flavour); + + FShader *Get(unsigned int eff, bool alphateston) + { + // indices 0-2 match the warping modes, 3 no texture, the following are custom + if (!alphateston && eff <= 2) + { + return mMaterialShadersNAT[eff]; // Non-alphatest shaders are only created for default, warp1+2 and brightmap. The rest won't get used anyway + } + if (eff < mMaterialShaders.Size()) + { + return mMaterialShaders[eff]; + } + return NULL; + } +}; + +} +#endif + diff --git a/src/common/rendering/gles/gles_shaderprogram.cpp b/src/common/rendering/gles/gles_shaderprogram.cpp new file mode 100644 index 0000000000..26906f57a7 --- /dev/null +++ b/src/common/rendering/gles/gles_shaderprogram.cpp @@ -0,0 +1,293 @@ +/* +** Postprocessing framework +** Copyright (c) 2016-2020 Magnus Norddahl +** +** This software is provided 'as-is', without any express or implied +** warranty. In no event will the authors be held liable for any damages +** arising from the use of this software. +** +** Permission is granted to anyone to use this software for any purpose, +** including commercial applications, and to alter it and redistribute it +** freely, subject to the following restrictions: +** +** 1. The origin of this software must not be misrepresented; you must not +** claim that you wrote the original software. If you use this software +** in a product, an acknowledgment in the product documentation would be +** appreciated but is not required. +** 2. Altered source versions must be plainly marked as such, and must not be +** misrepresented as being the original software. +** 3. This notice may not be removed or altered from any source distribution. +*/ + +#include "gles_system.h" +#include "v_video.h" +#include "hw_cvars.h" +#include "gles_shaderprogram.h" +#include "hw_shaderpatcher.h" +#include "filesystem.h" +#include "printf.h" + +namespace OpenGLESRenderer +{ + +FString GetGLSLPrecision(); + +bool IsShaderCacheActive(); +TArray LoadCachedProgramBinary(const FString &vertex, const FString &fragment, uint32_t &binaryFormat); +void SaveCachedProgramBinary(const FString &vertex, const FString &fragment, const TArray &binary, uint32_t binaryFormat); + +FShaderProgram::FShaderProgram() +{ + for (int i = 0; i < NumShaderTypes; i++) + mShaders[i] = 0; +} + +//========================================================================== +// +// Free shader program resources +// +//========================================================================== + +FShaderProgram::~FShaderProgram() +{ + if (mProgram != 0) + glDeleteProgram(mProgram); + + for (int i = 0; i < NumShaderTypes; i++) + { + if (mShaders[i] != 0) + glDeleteShader(mShaders[i]); + } +} + +//========================================================================== +// +// Creates an OpenGL shader object for the specified type of shader +// +//========================================================================== + +void FShaderProgram::CreateShader(ShaderType type) +{ + GLenum gltype = 0; + switch (type) + { + default: + case Vertex: gltype = GL_VERTEX_SHADER; break; + case Fragment: gltype = GL_FRAGMENT_SHADER; break; + } + mShaders[type] = glCreateShader(gltype); +} + +//========================================================================== +// +// Compiles a shader and attaches it the program object +// +//========================================================================== + +void FShaderProgram::Compile(ShaderType type, const char *lumpName, const char *defines, int maxGlslVersion) +{ + int lump = fileSystem.CheckNumForFullName(lumpName); + if (lump == -1) I_FatalError("Unable to load '%s'", lumpName); + FString code = fileSystem.ReadFile(lump).GetString().GetChars(); + Compile(type, lumpName, code, defines, maxGlslVersion); +} + +void FShaderProgram::Compile(ShaderType type, const char *name, const FString &code, const char *defines, int maxGlslVersion) +{ + mShaderNames[type] = name; + mShaderSources[type] = PatchShader(type, code, defines, maxGlslVersion); +} + +void FShaderProgram::CompileShader(ShaderType type) +{ + CreateShader(type); + + const auto &handle = mShaders[type]; + + + const FString &patchedCode = mShaderSources[type]; + int lengths[1] = { (int)patchedCode.Len() }; + const char *sources[1] = { patchedCode.GetChars() }; + glShaderSource(handle, 1, sources, lengths); + + glCompileShader(handle); + + GLint status = 0; + glGetShaderiv(handle, GL_COMPILE_STATUS, &status); + if (status == GL_FALSE) + { + I_FatalError("Compile Shader '%s':\n%s\n", mShaderNames[type].GetChars(), GetShaderInfoLog(handle).GetChars()); + } + else + { + if (mProgram == 0) + mProgram = glCreateProgram(); + glAttachShader(mProgram, handle); + } +} + +//========================================================================== +// +// Links a program with the compiled shaders +// +//========================================================================== + +void FShaderProgram::Link(const char *name) +{ + + uint32_t binaryFormat = 0; + TArray binary; + if (IsShaderCacheActive()) + binary = LoadCachedProgramBinary(mShaderSources[Vertex], mShaderSources[Fragment], binaryFormat); + + bool loadedFromBinary = false; + + if (!loadedFromBinary) + { + CompileShader(Vertex); + CompileShader(Fragment); + + glLinkProgram(mProgram); + + GLint status = 0; + glGetProgramiv(mProgram, GL_LINK_STATUS, &status); + if (status == GL_FALSE) + { + I_FatalError("Link Shader '%s':\n%s\n", name, GetProgramInfoLog(mProgram).GetChars()); + } + } + + // This is only for old OpenGL which didn't allow to set the binding from within the shader. + if (screen->glslversion < 4.20) + { + glUseProgram(mProgram); + for (auto &uni : samplerstobind) + { + auto index = glGetUniformLocation(mProgram, uni.first); + if (index >= 0) + { + glUniform1i(index, uni.second); + } + } + } + samplerstobind.Clear(); + samplerstobind.ShrinkToFit(); +} + +//========================================================================== +// +// Set uniform buffer location (only useful for GL 3.3) +// +//========================================================================== + +void FShaderProgram::SetUniformBufferLocation(int index, const char *name) +{ + +} + +//========================================================================== +// +// Makes the shader the active program +// +//========================================================================== + +void FShaderProgram::Bind() +{ + glUseProgram(mProgram); +} + +//========================================================================== +// +// Returns the shader info log (warnings and compile errors) +// +//========================================================================== + +FString FShaderProgram::GetShaderInfoLog(GLuint handle) +{ + static char buffer[10000]; + GLsizei length = 0; + buffer[0] = 0; + glGetShaderInfoLog(handle, 10000, &length, buffer); + return FString(buffer); +} + +//========================================================================== +// +// Returns the program info log (warnings and compile errors) +// +//========================================================================== + +FString FShaderProgram::GetProgramInfoLog(GLuint handle) +{ + static char buffer[10000]; + GLsizei length = 0; + buffer[0] = 0; + glGetProgramInfoLog(handle, 10000, &length, buffer); + return FString(buffer); +} + +//========================================================================== +// +// Patches a shader to be compatible with the version of OpenGL in use +// +//========================================================================== + +FString FShaderProgram::PatchShader(ShaderType type, const FString &code, const char *defines, int maxGlslVersion) +{ + FString patchedCode; + + patchedCode.AppendFormat("#version %d\n", 100); // Set to GLES2 + + patchedCode += GetGLSLPrecision(); + + + if (defines) + patchedCode << defines; + + + patchedCode << "#line 1\n"; + patchedCode << RemoveLayoutLocationDecl(code, type == Vertex ? "out" : "in"); + + if (maxGlslVersion < 420) + { + // Here we must strip out all layout(binding) declarations for sampler uniforms and store them in 'samplerstobind' which can then be processed by the link function. + patchedCode = RemoveSamplerBindings(patchedCode, samplerstobind); + } + + return patchedCode; +} + +///////////////////////////////////////////////////////////////////////////// + +void FPresentShaderBase::Init(const char * vtx_shader_name, const char * program_name) +{ + FString prolog = Uniforms.CreateDeclaration("Uniforms", PresentUniforms::Desc()); + + mShader.reset(new FShaderProgram()); + mShader->Compile(FShaderProgram::Vertex, "shaders_gles/pp/screenquad.vp", prolog, 330); + mShader->Compile(FShaderProgram::Fragment, vtx_shader_name, prolog, 330); + mShader->Link(program_name); + mShader->Bind(); + Uniforms.Init(); + + Uniforms.UniformLocation.resize(Uniforms.mFields.size()); + + for (int n = 0; n < Uniforms.mFields.size(); n++) + { + int index = -1; + UniformFieldDesc desc = Uniforms.mFields[n]; + index = glGetUniformLocation(mShader->mProgram, desc.Name); + Uniforms.UniformLocation[n] = index; + } +} + +void FPresentShader::Bind() +{ + if (!mShader) + { + Init("shaders_gles/pp/present.fp", "shaders_gles/pp/present"); + } + mShader->Bind(); +} + +} \ No newline at end of file diff --git a/src/common/rendering/gles/gles_shaderprogram.h b/src/common/rendering/gles/gles_shaderprogram.h new file mode 100644 index 0000000000..a8dc97428b --- /dev/null +++ b/src/common/rendering/gles/gles_shaderprogram.h @@ -0,0 +1,159 @@ + +#pragma once + +#include "gles_system.h" +#include "gles_shader.h" +#include "hwrenderer/postprocessing/hw_postprocess.h" + +namespace OpenGLESRenderer +{ + +class FShaderProgram : public PPShaderBackend +{ +public: + FShaderProgram(); + ~FShaderProgram(); + + enum ShaderType + { + Vertex, + Fragment, + NumShaderTypes + }; + + void Compile(ShaderType type, const char *lumpName, const char *defines, int maxGlslVersion); + void Compile(ShaderType type, const char *name, const FString &code, const char *defines, int maxGlslVersion); + void Link(const char *name); + void SetUniformBufferLocation(int index, const char *name); + + void Bind(); + + GLuint Handle() { return mProgram; } + //explicit operator bool() const { return mProgram != 0; } + + std::unique_ptr Uniforms; + GLuint mProgram = 0; +private: + FShaderProgram(const FShaderProgram &) = delete; + FShaderProgram &operator=(const FShaderProgram &) = delete; + + void CompileShader(ShaderType type); + FString PatchShader(ShaderType type, const FString &code, const char *defines, int maxGlslVersion); + + void CreateShader(ShaderType type); + FString GetShaderInfoLog(GLuint handle); + FString GetProgramInfoLog(GLuint handle); + + + GLuint mShaders[NumShaderTypes]; + FString mShaderSources[NumShaderTypes]; + FString mShaderNames[NumShaderTypes]; + TArray> samplerstobind; +}; + +template +class ShaderUniformsGles +{ +public: + ShaderUniformsGles() + { + memset(&Values, 0, sizeof(Values)); + } + + ~ShaderUniformsGles() + { + if (mBuffer != nullptr) + delete mBuffer; + } + + FString CreateDeclaration(const char* name, const std::vector& fields) + { + mFields = fields; + FString decl; + decl += "\n"; + for (size_t i = 0; i < fields.size(); i++) + { + decl.AppendFormat("\tuniform %s %s;\n", GetTypeStr(fields[i].Type), fields[i].Name); + } + decl += "\n"; + return decl; + } + + void Init() + { + if (mBuffer == nullptr) + mBuffer = screen->CreateDataBuffer(-1, false, false); + } + + void SetData() + { + if (mBuffer != nullptr) + mBuffer->SetData(sizeof(T), &Values); + } + + IDataBuffer* GetBuffer() const + { + // OpenGL needs to mess around with this in ways that should not be part of the interface. + return mBuffer; + } + + T* operator->() { return &Values; } + const T* operator->() const { return &Values; } + + T Values; + + std::vector mFields; + std::vector UniformLocation; + +private: + ShaderUniformsGles(const ShaderUniformsGles&) = delete; + ShaderUniformsGles& operator=(const ShaderUniformsGles&) = delete; + + IDataBuffer* mBuffer = nullptr; + +private: + static const char* GetTypeStr(UniformType type) + { + switch (type) + { + default: + case UniformType::Int: return "int"; + case UniformType::UInt: return "uint"; + case UniformType::Float: return "float"; + case UniformType::Vec2: return "vec2"; + case UniformType::Vec3: return "vec3"; + case UniformType::Vec4: return "vec4"; + case UniformType::IVec2: return "ivec2"; + case UniformType::IVec3: return "ivec3"; + case UniformType::IVec4: return "ivec4"; + case UniformType::UVec2: return "uvec2"; + case UniformType::UVec3: return "uvec3"; + case UniformType::UVec4: return "uvec4"; + case UniformType::Mat4: return "mat4"; + } + } +}; + + +class FPresentShaderBase +{ +public: + virtual ~FPresentShaderBase() {} + virtual void Bind() = 0; + + ShaderUniformsGles Uniforms; + +protected: + virtual void Init(const char * vtx_shader_name, const char * program_name); + std::unique_ptr mShader; +}; + +class FPresentShader : public FPresentShaderBase +{ +public: + void Bind() override; + +}; + + +} \ No newline at end of file diff --git a/src/common/rendering/gles/gles_system.cpp b/src/common/rendering/gles/gles_system.cpp new file mode 100644 index 0000000000..f58051e64a --- /dev/null +++ b/src/common/rendering/gles/gles_system.cpp @@ -0,0 +1,188 @@ + + +#include "gles_system.h" +#include "tarray.h" +#include "v_video.h" +#include "printf.h" + +CVAR(Bool, gles_use_mapped_buffer, false, 0); +CVAR(Bool, gles_force_glsl_v100, false, 0); +CVAR(Int, gles_max_lights_per_surface, 32, 0); +EXTERN_CVAR(Bool, gl_customshader); + + +#if USE_GLES2 + +PFNGLMAPBUFFERRANGEEXTPROC glMapBufferRange = NULL; +PFNGLUNMAPBUFFEROESPROC glUnmapBuffer = NULL; +#ifdef __ANDROID__ +#include + +static void* LoadGLES2Proc(const char* name) +{ + static void *glesLib = NULL; + + if(!glesLib) + { + int flags = RTLD_LOCAL | RTLD_NOW; + + glesLib = dlopen("libGLESv2_CM.so", flags); + if(!glesLib) + { + glesLib = dlopen("libGLESv2.so", flags); + } + } + + void * ret = NULL; + ret = dlsym(glesLib, name); + + if(!ret) + { + //LOGI("Failed to load: %s", name); + } + else + { + //LOGI("Loaded %s func OK", name); + } + + return ret; +} + +#elif defined _WIN32 + +#include + +static HMODULE opengl32dll; +static PROC(WINAPI* getprocaddress)(LPCSTR name); + +static void* LoadGLES2Proc(const char* name) +{ + + HINSTANCE hGetProcIDDLL = LoadLibraryA("libGLESv2.dll"); + + int error = GetLastError(); + + void* addr = GetProcAddress(hGetProcIDDLL, name); + if (!addr) + { + //exit(1); + } + else + { + return addr; + } +} + +#endif + +#endif // USE_GLES2 + +static TArray m_Extensions; + + +static void CollectExtensions() +{ + const char* supported = (char*)glGetString(GL_EXTENSIONS); + + if (nullptr != supported) + { + char* extensions = new char[strlen(supported) + 1]; + strcpy(extensions, supported); + + char* extension = strtok(extensions, " "); + + while (extension) + { + m_Extensions.Push(FString(extension)); + extension = strtok(nullptr, " "); + } + + delete[] extensions; + } +} + + +static bool CheckExtension(const char* ext) +{ + for (unsigned int i = 0; i < m_Extensions.Size(); ++i) + { + if (m_Extensions[i].CompareNoCase(ext) == 0) return true; + } + + return false; +} + +namespace OpenGLESRenderer +{ + RenderContextGLES gles; + + void InitGLES() + { + +#if USE_GLES2 + + if (!gladLoadGLES2Loader(&LoadGLES2Proc)) + { + exit(-1); + } + + glMapBufferRange = (PFNGLMAPBUFFERRANGEEXTPROC)LoadGLES2Proc("glMapBufferRange"); + glUnmapBuffer = (PFNGLUNMAPBUFFEROESPROC)LoadGLES2Proc("glUnmapBuffer"); + +#else + static bool first = true; + + if (first) + { + if (ogl_LoadFunctions() == ogl_LOAD_FAILED) + { + //I_FatalError("Failed to load OpenGL functions."); + } + } + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); +#endif + CollectExtensions(); + + Printf("GL_VENDOR: %s\n", glGetString(GL_VENDOR)); + Printf("GL_RENDERER: %s\n", glGetString(GL_RENDERER)); + Printf("GL_VERSION: %s\n", glGetString(GL_VERSION)); + Printf("GL_SHADING_LANGUAGE_VERSION: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION)); + Printf("GL_EXTENSIONS:\n"); + for (unsigned i = 0; i < m_Extensions.Size(); i++) + { + Printf(" %s\n", m_Extensions[i].GetChars()); + } + + + gles.flags = RFL_NO_CLIP_PLANES; + + gles.useMappedBuffers = gles_use_mapped_buffer; + gles.forceGLSLv100 = gles_force_glsl_v100; + gles.maxlights = gles_max_lights_per_surface; + + gles.modelstring = (char*)glGetString(GL_RENDERER); + gles.vendorstring = (char*)glGetString(GL_VENDOR); + + gl_customshader = false; + + GLint maxTextureSize[1]; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxTextureSize); + + gles.max_texturesize = maxTextureSize[0]; + + Printf("GL_MAX_TEXTURE_SIZE: %d\n", gles.max_texturesize); + +#if USE_GLES2 + gles.depthStencilAvailable = CheckExtension("GL_OES_packed_depth_stencil"); + gles.npotAvailable = CheckExtension("GL_OES_texture_npot"); +#else + gles.depthStencilAvailable = true; + gles.npotAvailable = true; + gles.useMappedBuffers = true; +#endif + + gles.numlightvectors = (gles.maxlights * LIGHT_VEC4_NUM); + } +} diff --git a/src/common/rendering/gles/gles_system.h b/src/common/rendering/gles/gles_system.h new file mode 100644 index 0000000000..0214993624 --- /dev/null +++ b/src/common/rendering/gles/gles_system.h @@ -0,0 +1,91 @@ +#ifndef __GLES_SYSTEM_H +#define __GLES_SYSTEM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__DragonFly__) +#include +#endif +#include + +#include +#include +#include + +#define USE_GLES2 0 + +#if (USE_GLES2) + #include "glad/glad.h" + +// Below are used extensions for GLES +typedef void* (APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +GLAPI PFNGLMAPBUFFERRANGEEXTPROC glMapBufferRange; + +typedef GLboolean(APIENTRYP PFNGLUNMAPBUFFEROESPROC)(GLenum target); +GLAPI PFNGLUNMAPBUFFEROESPROC glUnmapBuffer; + +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_MAP_PERSISTENT_BIT 0x0040 +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_BGRA 0x80E1 + +#else + #include "gl_load/gl_load.h" +#endif + +#if defined(__APPLE__) + #include +#endif + +// This is the number of vec4s make up the light data +#define LIGHT_VEC4_NUM 4 + +//#define NO_RENDER_BUFFER + +//#define NPOT_EMULATION + +namespace OpenGLESRenderer +{ + struct RenderContextGLES + { + unsigned int flags; + unsigned int maxlights; + unsigned int numlightvectors; + bool useMappedBuffers; + bool depthStencilAvailable; + bool npotAvailable; + bool forceGLSLv100; + int max_texturesize; + char* vendorstring; + char* modelstring; + }; + + extern RenderContextGLES gles; + + void InitGLES(); +} + +#ifdef _MSC_VER +#pragma warning(disable : 4244) // MIPS +#pragma warning(disable : 4136) // X86 +#pragma warning(disable : 4051) // ALPHA + +#pragma warning(disable : 4018) // signed/unsigned mismatch +#pragma warning(disable : 4305) // truncate from double to float +#endif + +#endif //__GL_PCH_H diff --git a/src/common/rendering/hwrenderer/data/buffers.h b/src/common/rendering/hwrenderer/data/buffers.h index 8ef57174e7..7f4402c1c3 100644 --- a/src/common/rendering/hwrenderer/data/buffers.h +++ b/src/common/rendering/hwrenderer/data/buffers.h @@ -5,6 +5,14 @@ class FRenderState; +#ifdef __ANDROID__ +#define HW_MAX_PIPELINE_BUFFERS 8 +#define HW_BLOCK_SSBO 1 +#else +// On desktop this is only useful fpr letting the GPU run in parallel with the playsim and for that 2 buffers are enough. +#define HW_MAX_PIPELINE_BUFFERS 2 +#endif + // The low level code needs to know which attributes exist. // OpenGL needs to change the state of all of them per buffer binding. // VAOs are mostly useless for this because they lump buffer and binding state together which the model code does not want. @@ -54,10 +62,15 @@ public: virtual void *Lock(unsigned int size) = 0; virtual void Unlock() = 0; virtual void Resize(size_t newsize) = 0; + + virtual void Upload(size_t start, size_t size) {} // For unmappable buffers + virtual void Map() {} // Only needed by old OpenGL but this needs to be in the interface. virtual void Unmap() {} void *Memory() { return map; } size_t Size() { return buffersize; } + virtual void GPUDropSync() {} + virtual void GPUWaitSync() {} }; class IVertexBuffer : virtual public IBuffer diff --git a/src/common/rendering/hwrenderer/data/flatvertices.cpp b/src/common/rendering/hwrenderer/data/flatvertices.cpp index 5bc37bcb79..9a34b45ff9 100644 --- a/src/common/rendering/hwrenderer/data/flatvertices.cpp +++ b/src/common/rendering/hwrenderer/data/flatvertices.cpp @@ -45,7 +45,8 @@ // //========================================================================== -FFlatVertexBuffer::FFlatVertexBuffer(int width, int height) +FFlatVertexBuffer::FFlatVertexBuffer(int width, int height, int pipelineNbr): + mPipelineNbr(pipelineNbr) { vbo_shadowdata.Resize(NUM_RESERVED); @@ -78,19 +79,27 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height) vbo_shadowdata[18].Set(32767.0f, -32767.0f, 32767.0f, 0, 0); vbo_shadowdata[19].Set(32767.0f, -32767.0f, -32767.0f, 0, 0); - mVertexBuffer = screen->CreateVertexBuffer(); mIndexBuffer = screen->CreateIndexBuffer(); int data[4] = {}; mIndexBuffer->SetData(4, data); // On Vulkan this may not be empty, so set some dummy defaults to avoid crashes. - unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex); - mVertexBuffer->SetData(bytesize, nullptr, false); - static const FVertexBufferAttribute format[] = { - { 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FFlatVertex, x) }, - { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) } - }; - mVertexBuffer->SetFormat(1, 2, sizeof(FFlatVertex), format); + for (int n = 0; n < mPipelineNbr; n++) + { + mVertexBufferPipeline[n] = screen->CreateVertexBuffer(); + + unsigned int bytesize = BUFFER_SIZE * sizeof(FFlatVertex); + mVertexBufferPipeline[n]->SetData(bytesize, nullptr, false); + + static const FVertexBufferAttribute format[] = { + { 0, VATTR_VERTEX, VFmt_Float3, (int)myoffsetof(FFlatVertex, x) }, + { 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) } + }; + + mVertexBufferPipeline[n]->SetFormat(1, 2, sizeof(FFlatVertex), format); + } + + mVertexBuffer = mVertexBufferPipeline[mPipelinePos]; mIndex = mCurIndex = NUM_RESERVED; mNumReserved = NUM_RESERVED; @@ -105,8 +114,12 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height) FFlatVertexBuffer::~FFlatVertexBuffer() { + for (int n = 0; n < mPipelineNbr; n++) + { + delete mVertexBufferPipeline[n]; + } + delete mIndexBuffer; - delete mVertexBuffer; mIndexBuffer = nullptr; mVertexBuffer = nullptr; } @@ -153,8 +166,17 @@ std::pair FFlatVertexBuffer::AllocVertices(unsigned void FFlatVertexBuffer::Copy(int start, int count) { - Map(); - memcpy(GetBuffer(start), &vbo_shadowdata[0], count * sizeof(FFlatVertex)); - Unmap(); + IVertexBuffer* old = mVertexBuffer; + + for (int n = 0; n < mPipelineNbr; n++) + { + mVertexBuffer = mVertexBufferPipeline[n]; + Map(); + memcpy(GetBuffer(start), &vbo_shadowdata[0], count * sizeof(FFlatVertex)); + Unmap(); + mVertexBuffer->Upload(start * sizeof(FFlatVertex), count * sizeof(FFlatVertex)); + } + + mVertexBuffer = old; } diff --git a/src/common/rendering/hwrenderer/data/flatvertices.h b/src/common/rendering/hwrenderer/data/flatvertices.h index d28339ee79..619128a33b 100644 --- a/src/common/rendering/hwrenderer/data/flatvertices.h +++ b/src/common/rendering/hwrenderer/data/flatvertices.h @@ -45,13 +45,20 @@ public: TArray vbo_shadowdata; TArray ibo_data; - IVertexBuffer *mVertexBuffer; + int mPipelineNbr; + int mPipelinePos = 0; + + IVertexBuffer* mVertexBuffer; + IVertexBuffer *mVertexBufferPipeline[HW_MAX_PIPELINE_BUFFERS]; IIndexBuffer *mIndexBuffer; + + unsigned int mIndex; std::atomic mCurIndex; unsigned int mNumReserved; + unsigned int mMapStart; static const unsigned int BUFFER_SIZE = 2000000; static const unsigned int BUFFER_SIZE_TO_USE = BUFFER_SIZE-500; @@ -68,7 +75,7 @@ public: NUM_RESERVED = 20 }; - FFlatVertexBuffer(int width, int height); + FFlatVertexBuffer(int width, int height, int pipelineNbr = 1); ~FFlatVertexBuffer(); void OutputResized(int width, int height); @@ -97,16 +104,40 @@ public: mCurIndex = mIndex; } + void NextPipelineBuffer() + { + mPipelinePos++; + mPipelinePos %= mPipelineNbr; + + mVertexBuffer = mVertexBufferPipeline[mPipelinePos]; + } + void Map() { + mMapStart = mCurIndex; mVertexBuffer->Map(); } void Unmap() { mVertexBuffer->Unmap(); + mVertexBuffer->Upload(mMapStart * sizeof(FFlatVertex), (mCurIndex - mMapStart) * sizeof(FFlatVertex)); } + void DropSync() + { + mVertexBuffer->GPUDropSync(); + } + + void WaitSync() + { + mVertexBuffer->GPUWaitSync(); + } + + int GetPipelinePos() + { + return mPipelinePos; + } }; #endif diff --git a/src/common/rendering/hwrenderer/data/hw_lightbuffer.cpp b/src/common/rendering/hwrenderer/data/hw_lightbuffer.cpp index 2783ab6695..e0283d58e6 100644 --- a/src/common/rendering/hwrenderer/data/hw_lightbuffer.cpp +++ b/src/common/rendering/hwrenderer/data/hw_lightbuffer.cpp @@ -33,7 +33,8 @@ static const int ELEMENTS_PER_LIGHT = 4; // each light needs 4 vec4's. static const int ELEMENT_SIZE = (4*sizeof(float)); -FLightBuffer::FLightBuffer() +FLightBuffer::FLightBuffer(int pipelineNbr): + mPipelineNbr(pipelineNbr) { int maxNumberOfLights = 80000; @@ -43,7 +44,7 @@ FLightBuffer::FLightBuffer() // Hack alert: On Intel's GL driver SSBO's perform quite worse than UBOs. // We only want to disable using SSBOs for lights but not disable the feature entirely. // Note that using an uniform buffer here will limit the number of lights per surface so it isn't done for NVidia and AMD. - if (screen->IsVulkan() || screen->IsPoly() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && !strstr(screen->vendorstring, "Intel"))) + if (screen->IsVulkan() || screen->IsPoly() || ((screen->hwcaps & RFL_SHADER_STORAGE_BUFFER) && screen->allowSSBO() && !strstr(screen->vendorstring, "Intel"))) { mBufferType = true; mBlockAlign = 0; @@ -56,11 +57,15 @@ FLightBuffer::FLightBuffer() mBlockSize = screen->maxuniformblock / ELEMENT_SIZE; mBlockAlign = screen->uniformblockalignment / ELEMENT_SIZE; mMaxUploadSize = (mBlockSize - mBlockAlign); - mByteSize += screen->maxuniformblock; // to avoid mapping beyond the end of the buffer. + + //mByteSize += screen->maxuniformblock; // to avoid mapping beyond the end of the buffer. REMOVED this...This can try to allocate 100's of MB.. } - mBuffer = screen->CreateDataBuffer(LIGHTBUF_BINDINGPOINT, mBufferType, false); - mBuffer->SetData(mByteSize, nullptr, false); + for (int n = 0; n < mPipelineNbr; n++) + { + mBufferPipeline[n] = screen->CreateDataBuffer(LIGHTBUF_BINDINGPOINT, mBufferType, false); + mBufferPipeline[n]->SetData(mByteSize, nullptr, false); + } Clear(); } @@ -73,6 +78,11 @@ FLightBuffer::~FLightBuffer() void FLightBuffer::Clear() { mIndex = 0; + + mPipelinePos++; + mPipelinePos %= mPipelineNbr; + + mBuffer = mBufferPipeline[mPipelinePos]; } int FLightBuffer::UploadLights(FDynLightData &data) diff --git a/src/common/rendering/hwrenderer/data/hw_lightbuffer.h b/src/common/rendering/hwrenderer/data/hw_lightbuffer.h index 2e5849346c..441dc55ff3 100644 --- a/src/common/rendering/hwrenderer/data/hw_lightbuffer.h +++ b/src/common/rendering/hwrenderer/data/hw_lightbuffer.h @@ -12,6 +12,9 @@ class FRenderState; class FLightBuffer { IDataBuffer *mBuffer; + IDataBuffer* mBufferPipeline[HW_MAX_PIPELINE_BUFFERS]; + int mPipelineNbr; + int mPipelinePos = 0; bool mBufferType; std::atomic mIndex; @@ -25,7 +28,7 @@ class FLightBuffer public: - FLightBuffer(); + FLightBuffer(int pipelineNbr = 1); ~FLightBuffer(); void Clear(); int UploadLights(FDynLightData &data); diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index e6c63ba446..040a511138 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -226,6 +226,10 @@ protected: float mAlphaThreshold; float mClipSplit[2]; + + int mColorMapSpecial; + float mColorMapFlash; + StreamData mStreamData = {}; PalEntry mFogColor; @@ -278,6 +282,9 @@ public: mBias.Reset(); mPassType = NORMAL_PASS; + mColorMapSpecial = 0; + mColorMapFlash = 1; + mVertexBuffer = nullptr; mVertexOffsets[0] = mVertexOffsets[1] = 0; mIndexBuffer = nullptr; @@ -677,6 +684,12 @@ public: return mPassType; } + void SetSpecialColormap(int cm, float flash) + { + mColorMapSpecial = cm; + mColorMapFlash = flash; + } + // API-dependent render interface // Draw commands diff --git a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp index a265e7d110..c37306b8a9 100644 --- a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp +++ b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.cpp @@ -33,13 +33,19 @@ static const int INITIAL_BUFFER_SIZE = 100; // 100 viewpoints per frame should nearly always be enough -HWViewpointBuffer::HWViewpointBuffer() +HWViewpointBuffer::HWViewpointBuffer(int pipelineNbr): + mPipelineNbr(pipelineNbr) { mBufferSize = INITIAL_BUFFER_SIZE; mBlockAlign = ((sizeof(HWViewpointUniforms) / screen->uniformblockalignment) + 1) * screen->uniformblockalignment; mByteSize = mBufferSize * mBlockAlign; - mBuffer = screen->CreateDataBuffer(VIEWPOINT_BINDINGPOINT, false, true); - mBuffer->SetData(mByteSize, nullptr, false); + + for (int n = 0; n < mPipelineNbr; n++) + { + mBufferPipeline[n] = screen->CreateDataBuffer(VIEWPOINT_BINDINGPOINT, false, true); + mBufferPipeline[n]->SetData(mByteSize, nullptr, false); + } + Clear(); mLastMappedIndex = UINT_MAX; mClipPlaneInfo.Push(0); @@ -57,7 +63,10 @@ void HWViewpointBuffer::CheckSize() { mBufferSize *= 2; mByteSize *= 2; - mBuffer->Resize(mByteSize); + for (int n = 0; n < mPipelineNbr; n++) + { + mBufferPipeline[n]->Resize(mByteSize); + } m2DHeight = m2DWidth = -1; } } @@ -89,9 +98,14 @@ void HWViewpointBuffer::Set2D(FRenderState &di, int width, int height, int pll) matrices.mProjectionMatrix.ortho(0, (float)width, (float)height, 0, -1.0f, 1.0f); matrices.CalcDependencies(); - mBuffer->Map(); - memcpy(mBuffer->Memory(), &matrices, sizeof(matrices)); - mBuffer->Unmap(); + + for (int n = 0; n < mPipelineNbr; n++) + { + mBufferPipeline[n]->Map(); + memcpy(mBufferPipeline[n]->Memory(), &matrices, sizeof(matrices)); + mBufferPipeline[n]->Unmap(); + } + m2DWidth = width; m2DHeight = height; mLastMappedIndex = -1; @@ -115,5 +129,10 @@ void HWViewpointBuffer::Clear() // Index 0 is reserved for the 2D projection. mUploadIndex = 1; mClipPlaneInfo.Resize(1); + + mPipelinePos++; + mPipelinePos %= mPipelineNbr; + + mBuffer = mBufferPipeline[mPipelinePos]; } diff --git a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h index 42c0967045..0fbd46dfae 100644 --- a/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h +++ b/src/common/rendering/hwrenderer/data/hw_viewpointbuffer.h @@ -8,6 +8,9 @@ class FRenderState; class HWViewpointBuffer { IDataBuffer *mBuffer; + IDataBuffer* mBufferPipeline[HW_MAX_PIPELINE_BUFFERS]; + int mPipelineNbr; + int mPipelinePos = 0; unsigned int mBufferSize; unsigned int mBlockAlign; @@ -24,7 +27,7 @@ class HWViewpointBuffer public: - HWViewpointBuffer(); + HWViewpointBuffer(int pipelineNbr = 1); ~HWViewpointBuffer(); void Clear(); int Bind(FRenderState &di, unsigned int index); diff --git a/src/common/rendering/v_video.cpp b/src/common/rendering/v_video.cpp index 815b73a6bc..f978372391 100644 --- a/src/common/rendering/v_video.cpp +++ b/src/common/rendering/v_video.cpp @@ -72,6 +72,13 @@ CVAR(Int, win_w, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Int, win_h, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, win_maximized, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +// 0 means 'no pipelining' for non GLES2 and 4 elements for GLES2 +CUSTOM_CVAR(Int, gl_pipeline_depth, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) +{ + if (self < 0 || self >= HW_MAX_PIPELINE_BUFFERS) self = 0; + Printf("Changing the pipeline depth requires a restart for " GAMENAME ".\n"); +} + CUSTOM_CVAR(Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { if (self < GameTicRate && self != 0) @@ -92,6 +99,11 @@ CUSTOM_CVAR(Int, vid_preferbackend, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_N switch(self) { +#ifdef HAVE_GLES2 + case 3: + Printf("Selecting OpenGLES 2.0 backend...\n"); + break; +#endif case 2: Printf("Selecting SoftPoly backend...\n"); break; diff --git a/src/common/rendering/v_video.h b/src/common/rendering/v_video.h index c9124e05f5..b78afd4b09 100644 --- a/src/common/rendering/v_video.h +++ b/src/common/rendering/v_video.h @@ -43,6 +43,7 @@ #include "v_2ddrawer.h" #include "intrect.h" #include "hw_shadowmap.h" +#include "buffers.h" struct FPortalSceneState; @@ -148,6 +149,9 @@ public: IntRect mOutputLetterbox; float mSceneClearColor[4]{ 0,0,0,255 }; + int mPipelineNbr = 1; // Number of HW buffers to pipeline + int mPipelineType = 0; + public: DFrameBuffer (int width=1, int height=1); virtual ~DFrameBuffer(); @@ -158,6 +162,14 @@ public: { mShadowMap.SetAABBTree(tree); } + bool allowSSBO() + { +#ifndef HW_BLOCK_SSBO + return true; +#else + return mPipelineType == 0; +#endif + } virtual DCanvas* GetCanvas() { return nullptr; } diff --git a/src/common/textures/hw_material.cpp b/src/common/textures/hw_material.cpp index a157cbc079..3f149d7289 100644 --- a/src/common/textures/hw_material.cpp +++ b/src/common/textures/hw_material.cpp @@ -29,6 +29,10 @@ #include "c_cvars.h" #include "v_video.h" + +CVAR(Bool, gl_customshader, true, 0); + + static IHardwareTexture* (*layercallback)(int layer, int translation); TArray usershaders; @@ -124,17 +128,20 @@ FMaterial::FMaterial(FGameTexture * tx, int scaleflags) } auto index = tx->GetShaderIndex(); - if (index >= FIRST_USER_SHADER) + if (gl_customshader) { - const UserShaderDesc &usershader = usershaders[index - FIRST_USER_SHADER]; - if (usershader.shaderType == mShaderIndex) // Only apply user shader if it matches the expected material + if (index >= FIRST_USER_SHADER) { - for (auto &texture : tx->CustomShaderTextures) + const UserShaderDesc& usershader = usershaders[index - FIRST_USER_SHADER]; + if (usershader.shaderType == mShaderIndex) // Only apply user shader if it matches the expected material { - if (texture == nullptr) continue; - mTextureLayers.Push({ texture.get(), 0 }); // scalability should be user-definable. + for (auto& texture : tx->CustomShaderTextures) + { + if (texture == nullptr) continue; + mTextureLayers.Push({ texture.get(), 0 }); // scalability should be user-definable. + } + mShaderIndex = index; } - mShaderIndex = index; } } } diff --git a/src/gamedata/r_defs.h b/src/gamedata/r_defs.h index d7fb686cf2..c2606635ad 100644 --- a/src/gamedata/r_defs.h +++ b/src/gamedata/r_defs.h @@ -38,6 +38,8 @@ #include "texmanip.h" #include "fcolormap.h" +#include "hwrenderer/data/buffers.h" + // Some more or less basic data types // we depend on. #include "m_fixed.h" @@ -701,7 +703,7 @@ struct sector_t int vboindex[4]; // VBO indices of the 4 planes this sector uses during rendering. This is only needed for updating plane heights. int iboindex[4]; // IBO indices of the 4 planes this sector uses during rendering - double vboheight[2]; // Last calculated height for the 2 planes of this actual sector + double vboheight[HW_MAX_PIPELINE_BUFFERS][2]; // Last calculated height for the 2 planes of this actual sector int vbocount[2]; // Total count of vertices belonging to this sector's planes. This is used when a sector height changes and also contains all attached planes. int ibocount; // number of indices per plane (identical for all planes.) If this is -1 the index buffer is not in use. diff --git a/src/rendering/hwrenderer/hw_entrypoint.cpp b/src/rendering/hwrenderer/hw_entrypoint.cpp index 475c52272a..85ada6613f 100644 --- a/src/rendering/hwrenderer/hw_entrypoint.cpp +++ b/src/rendering/hwrenderer/hw_entrypoint.cpp @@ -108,7 +108,7 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou R_SetupFrame(mainvp, r_viewwindow, camera); - if (mainview && toscreen && !(camera->Level->flags3 & LEVEL3_NOSHADOWMAP) && camera->Level->HasDynamicLights && gl_light_shadowmap && (screen->hwcaps & RFL_SHADER_STORAGE_BUFFER)) + if (mainview && toscreen && !(camera->Level->flags3 & LEVEL3_NOSHADOWMAP) && camera->Level->HasDynamicLights && gl_light_shadowmap && screen->allowSSBO() && (screen->hwcaps & RFL_SHADER_STORAGE_BUFFER)) { screen->SetAABBTree(camera->Level->aabbTree); screen->mShadowMap.SetCollectLights([=] { @@ -152,6 +152,10 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou di->SetViewArea(); auto cm = di->SetFullbrightFlags(mainview ? vp.camera->player : nullptr); float flash = 1.f; + + // Only used by the GLES2 renderer + RenderState.SetSpecialColormap(cm, flash); + di->Viewpoint.FieldOfView = fov; // Set the real FOV for the current scene (it's not necessarily the same as the global setting in r_viewpoint) // Stereo mode specific perspective projection @@ -162,6 +166,9 @@ sector_t* RenderViewpoint(FRenderViewpoint& mainvp, AActor* camera, IntRect* bou di->ProcessScene(toscreen); + // Reset colormap so 2D drawing isn't affected + RenderState.SetSpecialColormap(CM_DEFAULT, 1); + if (mainview) { PostProcess.Clock(); @@ -263,8 +270,8 @@ void WriteSavePic(player_t* player, FileWriter* file, int width, int height) screen->ImageTransitionScene(true); hw_ClearFakeFlat(); - RenderState.SetVertexBuffer(screen->mVertexData); screen->mVertexData->Reset(); + RenderState.SetVertexBuffer(screen->mVertexData); screen->mLights->Clear(); screen->mViewpoints->Clear(); diff --git a/src/rendering/hwrenderer/hw_vertexbuilder.cpp b/src/rendering/hwrenderer/hw_vertexbuilder.cpp index 459b1e605c..bf5dd8bd0a 100644 --- a/src/rendering/hwrenderer/hw_vertexbuilder.cpp +++ b/src/rendering/hwrenderer/hw_vertexbuilder.cpp @@ -26,7 +26,7 @@ #include "hw_vertexbuilder.h" #include "flatvertices.h" #include "earcut.hpp" - +#include "v_video.h" //============================================================================= // @@ -222,7 +222,8 @@ static int CreateIndexedVertices(FFlatVertexBuffer* fvb, int h, sector_t* sec, c auto& vbo_shadowdata = fvb->vbo_shadowdata; sec->vboindex[h] = vbo_shadowdata.Size(); // First calculate the vertices for the sector itself - sec->vboheight[h] = sec->GetPlaneTexZ(h); + for (int n = 0; n < screen->mPipelineNbr; n++) + sec->vboheight[n][h] = sec->GetPlaneTexZ(h); sec->ibocount = verts[sec->Index()].indices.Size(); sec->iboindex[h] = CreateIndexedSectorVertices(fvb, sec, plane, floor, verts[sec->Index()]); @@ -335,6 +336,8 @@ static void UpdatePlaneVertices(FFlatVertexBuffer *fvb, sector_t* sec, int plane if (plane == sector_t::floor && sec->transdoor) vt->z -= 1; mapvt->z = vt->z; } + + fvb->mVertexBuffer->Upload(startvt * sizeof(FFlatVertex), countvt * sizeof(FFlatVertex)); } //========================================================================== @@ -357,15 +360,15 @@ static void CreateVertices(FFlatVertexBuffer* fvb, TArray& sectors) static void CheckPlanes(FFlatVertexBuffer* fvb, sector_t* sector) { - if (sector->GetPlaneTexZ(sector_t::ceiling) != sector->vboheight[sector_t::ceiling]) + if (sector->GetPlaneTexZ(sector_t::ceiling) != sector->vboheight[screen->mVertexData->GetPipelinePos()][sector_t::ceiling]) { UpdatePlaneVertices(fvb, sector, sector_t::ceiling); - sector->vboheight[sector_t::ceiling] = sector->GetPlaneTexZ(sector_t::ceiling); + sector->vboheight[screen->mVertexData->GetPipelinePos()][sector_t::ceiling] = sector->GetPlaneTexZ(sector_t::ceiling); } - if (sector->GetPlaneTexZ(sector_t::floor) != sector->vboheight[sector_t::floor]) + if (sector->GetPlaneTexZ(sector_t::floor) != sector->vboheight[screen->mVertexData->GetPipelinePos()][sector_t::floor]) { UpdatePlaneVertices(fvb, sector, sector_t::floor); - sector->vboheight[sector_t::floor] = sector->GetPlaneTexZ(sector_t::floor); + sector->vboheight[screen->mVertexData->GetPipelinePos()][sector_t::floor] = sector->GetPlaneTexZ(sector_t::floor); } } diff --git a/src/rendering/hwrenderer/scene/hw_fakeflat.cpp b/src/rendering/hwrenderer/scene/hw_fakeflat.cpp index a436c12098..1839d3be6d 100644 --- a/src/rendering/hwrenderer/scene/hw_fakeflat.cpp +++ b/src/rendering/hwrenderer/scene/hw_fakeflat.cpp @@ -266,7 +266,8 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca dest->SetTexture(sector_t::floor, s->GetTexture(sector_t::floor), false); dest->SetPlaneTexZQuick(sector_t::floor, s->GetPlaneTexZ(sector_t::floor)); dest->iboindex[sector_t::floor] = sec->iboindex[sector_t::vbo_fakefloor]; - dest->vboheight[sector_t::floor] = s->vboheight[sector_t::floor]; + for (int n = 0; n < screen->mPipelineNbr; n++) + dest->vboheight[n][sector_t::floor] = s->vboheight[n][sector_t::floor]; } else if (s->MoreFlags & SECMF_FAKEFLOORONLY) { @@ -292,7 +293,8 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca dest->floorplane = s->floorplane; dest->iboindex[sector_t::floor] = sec->iboindex[sector_t::vbo_fakefloor]; - dest->vboheight[sector_t::floor] = s->vboheight[sector_t::floor]; + for (int n = 0; n < screen->mPipelineNbr; n++) + dest->vboheight[n][sector_t::floor] = s->vboheight[n][sector_t::floor]; } if (!(s->MoreFlags&SECMF_FAKEFLOORONLY)) @@ -304,7 +306,8 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca dest->SetTexture(sector_t::ceiling, s->GetTexture(sector_t::ceiling), false); dest->SetPlaneTexZQuick(sector_t::ceiling, s->GetPlaneTexZ(sector_t::ceiling)); dest->iboindex[sector_t::ceiling] = sec->iboindex[sector_t::vbo_fakeceiling]; - dest->vboheight[sector_t::ceiling] = s->vboheight[sector_t::ceiling]; + for (int n = 0; n < screen->mPipelineNbr; n++) + dest->vboheight[n][sector_t::ceiling] = s->vboheight[n][sector_t::ceiling]; } } else @@ -312,7 +315,8 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca dest->ceilingplane = s->ceilingplane; dest->SetPlaneTexZQuick(sector_t::ceiling, s->GetPlaneTexZ(sector_t::ceiling)); dest->iboindex[sector_t::ceiling] = sec->iboindex[sector_t::vbo_fakeceiling]; - dest->vboheight[sector_t::ceiling] = s->vboheight[sector_t::ceiling]; + for (int n = 0; n < screen->mPipelineNbr; n++) + dest->vboheight[n][sector_t::ceiling] = s->vboheight[n][sector_t::ceiling]; } } @@ -326,10 +330,12 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca dest->ceilingplane.FlipVert(); dest->iboindex[sector_t::floor] = sec->iboindex[sector_t::floor]; - dest->vboheight[sector_t::floor] = sec->vboheight[sector_t::floor]; + for (int n = 0; n < screen->mPipelineNbr; n++) + dest->vboheight[n][sector_t::floor] = sec->vboheight[n][sector_t::floor]; dest->iboindex[sector_t::ceiling] = sec->iboindex[sector_t::vbo_fakefloor]; - dest->vboheight[sector_t::ceiling] = s->vboheight[sector_t::floor]; + for (int n = 0; n < screen->mPipelineNbr; n++) + dest->vboheight[n][sector_t::ceiling] = s->vboheight[n][sector_t::floor]; dest->ClearPortal(sector_t::ceiling); @@ -379,10 +385,12 @@ sector_t * hw_FakeFlat(sector_t * sec, area_t in_area, bool back, sector_t *loca dest->floorplane.FlipVert(); dest->iboindex[sector_t::floor] = sec->iboindex[sector_t::vbo_fakeceiling]; - dest->vboheight[sector_t::floor] = s->vboheight[sector_t::ceiling]; + for (int n = 0; n < screen->mPipelineNbr; n++) + dest->vboheight[n][sector_t::floor] = sec->vboheight[n][sector_t::ceiling]; dest->iboindex[sector_t::ceiling] = sec->iboindex[sector_t::ceiling]; - dest->vboheight[sector_t::ceiling] = sec->vboheight[sector_t::ceiling]; + for (int n = 0; n < screen->mPipelineNbr; n++) + dest->vboheight[n][sector_t::ceiling] = s->vboheight[n][sector_t::ceiling]; dest->ClearPortal(sector_t::floor); diff --git a/src/rendering/hwrenderer/scene/hw_portal.h b/src/rendering/hwrenderer/scene/hw_portal.h index a08ddceb35..6a3b461700 100644 --- a/src/rendering/hwrenderer/scene/hw_portal.h +++ b/src/rendering/hwrenderer/scene/hw_portal.h @@ -158,6 +158,8 @@ public: struct HWLinePortal : public HWScenePortalBase { + uint32_t PAD; // This fixes walls not being drawn in portals in 32bit machines..seems to be OK this is here for 64bit also.. + // this must be the same as at the start of line_t, so that we can pass in this structure directly to P_ClipLineToPortal. vertex_t *v1, *v2; // vertices, from v1 to v2 DVector2 delta; // precalculated v2 - v1 for side checking diff --git a/src/win32/zdoom.rc b/src/win32/zdoom.rc index f29410a13d..0e55d0efed 100644 --- a/src/win32/zdoom.rc +++ b/src/win32/zdoom.rc @@ -226,9 +226,12 @@ BEGIN PUSHBUTTON "E&xit",IDCANCEL,166,227,50,14 CONTROL "&OpenGL",IDC_WELCOME_VULKAN1,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,13,167,41,10 #ifdef HAVE_VULKAN - CONTROL "&Vulkan",IDC_WELCOME_VULKAN2,"Button",BS_AUTORADIOBUTTON,13,177,37,10 + CONTROL "&Vulkan",IDC_WELCOME_VULKAN2,"Button",BS_AUTORADIOBUTTON,13,176,37,10 +#endif + CONTROL "&SoftPoly",IDC_WELCOME_VULKAN3,"Button",BS_AUTORADIOBUTTON,13,185,43,10 +#ifdef HAVE_GLES2 + CONTROL "OpenGL &ES",IDC_WELCOME_VULKAN4,"Button",BS_AUTORADIOBUTTON,13,194,53,10 #endif - CONTROL "&SoftPoly",IDC_WELCOME_VULKAN3,"Button",BS_AUTORADIOBUTTON,13,188,43,10 END IDD_CRASHDIALOG DIALOGEX 0, 0, 415, 308 diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index ce0e995481..8e7a316db9 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -906,6 +906,7 @@ OptionValue PreferBackend 0, "$OPTVAL_OPENGL" 1, "$OPTVAL_VULKAN" 2, "$OPTVAL_SOFTPOLY" + 3, "$OPTVAL_OPENGLES" } OptionMenu "TrueColorOptions" protected diff --git a/wadsrc/static/shaders_gles/Uniform usage notes.txt b/wadsrc/static/shaders_gles/Uniform usage notes.txt new file mode 100644 index 0000000000..cae1bc255c --- /dev/null +++ b/wadsrc/static/shaders_gles/Uniform usage notes.txt @@ -0,0 +1,90 @@ +How can I remove the alpha test discard? + + +MISSING: +All post processing gone +Present shader missing dither +Shadow maps gone +HDR modes gone +Materials gone +gl_satformula does not do anything (remove an 'if' in shader) + +Broken to be fixed: +Texture filtering modes, currently fixed to linear mipmap + + + + + + +-------------------------------------- +uTextureMode + +0xFFFF = +(USES all) + TM_NORMAL = 0, // (r, g, b, a) + TM_STENCIL, // (1, 1, 1, a) + TM_OPAQUE, // (r, g, b, 1) + TM_INVERSE, // (1-r, 1-g, 1-b, a) + TM_ALPHATEXTURE, // (1, 1, 1, r) + TM_CLAMPY, // (r, g, b, (t >= 0.0 && t <= 1.0)? a:0) + TM_INVERTOPAQUE, // (1-r, 1-g, 1-b, 1) + TM_FOGLAYER, // (renders a fog layer in the shape of the active texture) + TM_FIXEDCOLORMAP = TM_FOGLAYER, + +0xF0000 = +(USES all) + TEXF_Brightmap = 0x10000, + TEXF_Detailmap = 0x20000, + TEXF_Glowmap = 0x40000, + + + + + + +uPalLightLevels + +0xFF = + 32 0r 0 or 1 + +0xFF00 = +gl_fogmode : +(USES 2) + 0, "$OPTVAL_OFF" + 1, "$OPTVAL_STANDARD" + 2, "$OPTVAL_RADIAL" + +0xFF0000 +gl_lightmode: +(USES 16, 5) + 0, "$OPTVAL_STANDARD" + 1, "$OPTVAL_BRIGHT" + 2, "$OPTVAL_DOOM" + 3, "$OPTVAL_DARK" + 4, "$OPTVAL_LEGACY" + 5, "$OPTVAL_BUILD" + 8, "$OPTVAL_SOFTWARE" + 16, "$OPTVAL_VANILLA" + + + + + +uTextureAddColor.a -> blendflags +0x7 = +(USES all) +const int Tex_Blend_Alpha = 1; +const int Tex_Blend_Screen = 2; +const int Tex_Blend_Overlay = 3; +const int Tex_Blend_Hardlight = 4; + + +0x8 = +Invert blend bit + + + + +uDesaturationFactor +> 0 diff --git a/wadsrc/static/shaders_gles/glsl/burn.fp b/wadsrc/static/shaders_gles/glsl/burn.fp new file mode 100644 index 0000000000..040311711d --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/burn.fp @@ -0,0 +1,13 @@ + +varying vec4 vTexCoord; +varying vec4 vColor; + +void main() +{ + vec4 frag = vColor; + + vec4 t1 = texture2D(tex, vTexCoord.xy); + vec4 t2 = texture2D(texture2, vec2(vTexCoord.x, 1.0-vTexCoord.y)); + + gl_FragColor = frag * vec4(t1.r, t1.g, t1.b, t2.a); +} diff --git a/wadsrc/static/shaders_gles/glsl/fogboundary.fp b/wadsrc/static/shaders_gles/glsl/fogboundary.fp new file mode 100644 index 0000000000..9a6448bee3 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/fogboundary.fp @@ -0,0 +1,30 @@ +varying vec4 pixelpos; + +//=========================================================================== +// +// Main shader routine +// +//=========================================================================== + +void main() +{ + float fogdist; + float fogfactor; + + // + // calculate fog factor + // +#if (DEF_FOG_ENABLED == 1) && (DEF_FOG_RADIAL == 0) && (DEF_FOG_COLOURED == 1) // This was uFogEnabled = -1,, TODO check this + { + fogdist = pixelpos.w; + } +#else + { + fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz)); + } +#endif + fogfactor = exp2 (uFogDensity * fogdist); + + gl_FragColor = vec4(uFogColor.rgb, 1.0 - fogfactor); +} + diff --git a/wadsrc/static/shaders_gles/glsl/func_defaultlight.fp b/wadsrc/static/shaders_gles/glsl/func_defaultlight.fp new file mode 100644 index 0000000000..6738af8f5f --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/func_defaultlight.fp @@ -0,0 +1,5 @@ + +vec4 ProcessLight(Material material, vec4 color) +{ + return color; +} diff --git a/wadsrc/static/shaders_gles/glsl/func_defaultmat.fp b/wadsrc/static/shaders_gles/glsl/func_defaultmat.fp new file mode 100644 index 0000000000..35006820c8 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/func_defaultmat.fp @@ -0,0 +1,7 @@ + +void SetupMaterial(inout Material material) +{ + material.Base = ProcessTexel(); + material.Normal = ApplyNormalMap(vTexCoord.st); + material.Bright = texture2D(brighttexture, vTexCoord.st); +} diff --git a/wadsrc/static/shaders_gles/glsl/func_defaultmat2.fp b/wadsrc/static/shaders_gles/glsl/func_defaultmat2.fp new file mode 100644 index 0000000000..b2beb254e6 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/func_defaultmat2.fp @@ -0,0 +1,6 @@ + +void SetupMaterial(inout Material material) +{ + vec2 texCoord = GetTexCoord(); + SetMaterialProps(material, texCoord); +} diff --git a/wadsrc/static/shaders_gles/glsl/func_normal.fp b/wadsrc/static/shaders_gles/glsl/func_normal.fp new file mode 100644 index 0000000000..49dfadd9aa --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/func_normal.fp @@ -0,0 +1,5 @@ + +void SetupMaterial(inout Material material) +{ + SetMaterialProps(material, vTexCoord.st); +} diff --git a/wadsrc/static/shaders_gles/glsl/func_notexture.fp b/wadsrc/static/shaders_gles/glsl/func_notexture.fp new file mode 100644 index 0000000000..9337ad6b13 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/func_notexture.fp @@ -0,0 +1,6 @@ + +vec4 ProcessTexel() +{ + return desaturate(uObjectColor); +} + diff --git a/wadsrc/static/shaders_gles/glsl/func_paletted.fp b/wadsrc/static/shaders_gles/glsl/func_paletted.fp new file mode 100644 index 0000000000..8de8f07478 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/func_paletted.fp @@ -0,0 +1,10 @@ + +vec4 ProcessTexel() +{ + float index = getTexel(vTexCoord.st).r; + index = ((index * 255.0) + 0.5) / 256.0; + vec4 tex = texture2D(texture2, vec2(index, 0.5)); + tex.a = 1.0; + return tex; +} + diff --git a/wadsrc/static/shaders_gles/glsl/func_pbr.fp b/wadsrc/static/shaders_gles/glsl/func_pbr.fp new file mode 100644 index 0000000000..49dfadd9aa --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/func_pbr.fp @@ -0,0 +1,5 @@ + +void SetupMaterial(inout Material material) +{ + SetMaterialProps(material, vTexCoord.st); +} diff --git a/wadsrc/static/shaders_gles/glsl/func_spec.fp b/wadsrc/static/shaders_gles/glsl/func_spec.fp new file mode 100644 index 0000000000..f2574a521c --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/func_spec.fp @@ -0,0 +1,8 @@ + +void SetupMaterial(inout Material material) +{ + SetMaterialProps(material, vTexCoord.st); + material.Specular = texture2D(speculartexture, vTexCoord.st).rgb; + material.Glossiness = uSpecularMaterial.x; + material.SpecularLevel = uSpecularMaterial.y; +} diff --git a/wadsrc/static/shaders_gles/glsl/func_warp1.fp b/wadsrc/static/shaders_gles/glsl/func_warp1.fp new file mode 100644 index 0000000000..dfadf8ada8 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/func_warp1.fp @@ -0,0 +1,19 @@ + +vec2 GetTexCoord() +{ + vec2 texCoord = vTexCoord.st; + + const float pi = 3.14159265358979323846; + vec2 offset = vec2(0,0); + + offset.y = sin(pi * 2.0 * (texCoord.x + timer * 0.125)) * 0.1; + offset.x = sin(pi * 2.0 * (texCoord.y + timer * 0.125)) * 0.1; + + return texCoord + offset; +} + +vec4 ProcessTexel() +{ + return getTexel(GetTexCoord()); +} + diff --git a/wadsrc/static/shaders_gles/glsl/func_warp2.fp b/wadsrc/static/shaders_gles/glsl/func_warp2.fp new file mode 100644 index 0000000000..1ee0f7fd02 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/func_warp2.fp @@ -0,0 +1,20 @@ + + +vec2 GetTexCoord() +{ + vec2 texCoord = vTexCoord.st; + + const float pi = 3.14159265358979323846; + vec2 offset = vec2(0.0,0.0); + + offset.y = 0.5 + sin(pi * 2.0 * (texCoord.y + timer * 0.61 + 900.0/8192.0)) + sin(pi * 2.0 * (texCoord.x * 2.0 + timer * 0.36 + 300.0/8192.0)); + offset.x = 0.5 + sin(pi * 2.0 * (texCoord.y + timer * 0.49 + 700.0/8192.0)) + sin(pi * 2.0 * (texCoord.x * 2.0 + timer * 0.49 + 1200.0/8192.0)); + + return texCoord + offset * 0.025; +} + +vec4 ProcessTexel() +{ + return getTexel(GetTexCoord()); +} + diff --git a/wadsrc/static/shaders_gles/glsl/func_warp3.fp b/wadsrc/static/shaders_gles/glsl/func_warp3.fp new file mode 100644 index 0000000000..9edea0004e --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/func_warp3.fp @@ -0,0 +1,21 @@ + + +vec2 GetTexCoord() +{ + vec2 texCoord = vTexCoord.st; + + const float pi = 3.14159265358979323846; + vec2 offset = vec2(0.0,0.0); + + float siny = sin(pi * 2.0 * (texCoord.y * 2.0 + timer * 0.75)) * 0.03; + offset.y = siny + sin(pi * 2.0 * (texCoord.x + timer * 0.75)) * 0.03; + offset.x = siny + sin(pi * 2.0 * (texCoord.x + timer * 0.45)) * 0.02; + + return texCoord + offset; +} + +vec4 ProcessTexel() +{ + return getTexel(GetTexCoord()); +} + diff --git a/wadsrc/static/shaders_gles/glsl/func_wavex.fp b/wadsrc/static/shaders_gles/glsl/func_wavex.fp new file mode 100644 index 0000000000..3b892da9d7 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/func_wavex.fp @@ -0,0 +1,17 @@ + +vec2 GetTexCoord() +{ + vec2 texCoord = vTexCoord.st; + + const float pi = 3.14159265358979323846; + + texCoord.x += sin(pi * 2.0 * (texCoord.y + timer * 0.125)) * 0.1; + + return texCoord; +} + +vec4 ProcessTexel() +{ + return getTexel(GetTexCoord()); +} + diff --git a/wadsrc/static/shaders_gles/glsl/fuzz_jagged.fp b/wadsrc/static/shaders_gles/glsl/fuzz_jagged.fp new file mode 100644 index 0000000000..083c220689 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/fuzz_jagged.fp @@ -0,0 +1,24 @@ +//created by Evil Space Tomato + +vec4 ProcessTexel() +{ + vec2 texCoord = vTexCoord.st; + + vec2 texSplat; + const float pi = 3.14159265358979323846; + texSplat.x = texCoord.x + mod(sin(pi * 2.0 * (texCoord.y + timer * 2.0)),0.1) * 0.1; + texSplat.y = texCoord.y + mod(cos(pi * 2.0 * (texCoord.x + timer * 2.0)),0.1) * 0.1; + + vec4 basicColor = getTexel(texSplat); + + float texX = sin(texCoord.x * 100.0 + timer*5.0); + float texY = cos(texCoord.x * 100.0 + timer*5.0); + float vX = (texX/texY)*21.0; + float vY = (texY/texX)*13.0; + + float test = mod(timer*2.0+(vX + vY), 0.5); + + basicColor.a = basicColor.a * test; + + return basicColor; +} diff --git a/wadsrc/static/shaders_gles/glsl/fuzz_noise.fp b/wadsrc/static/shaders_gles/glsl/fuzz_noise.fp new file mode 100644 index 0000000000..0107ebbd2f --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/fuzz_noise.fp @@ -0,0 +1,20 @@ +//created by Evil Space Tomato + +vec4 ProcessTexel() +{ + vec2 texCoord = vTexCoord.st; + vec4 basicColor = getTexel(texCoord); + + texCoord.x = float( int(texCoord.x * 128.0) ) / 128.0; + texCoord.y = float( int(texCoord.y * 128.0) ) / 128.0; + + float texX = sin(mod(texCoord.x * 100.0 + timer*5.0, 3.489)) + texCoord.x / 4.0; + float texY = cos(mod(texCoord.y * 100.0 + timer*5.0, 3.489)) + texCoord.y / 4.0; + float vX = (texX/texY)*21.0; + float vY = (texY/texX)*13.0; + + float test = mod(timer*2.0+(vX + vY), 0.5); + basicColor.a = basicColor.a * test; + basicColor.rgb = vec3(0.0,0.0,0.0); + return basicColor; +} diff --git a/wadsrc/static/shaders_gles/glsl/fuzz_smooth.fp b/wadsrc/static/shaders_gles/glsl/fuzz_smooth.fp new file mode 100644 index 0000000000..3c642c399a --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/fuzz_smooth.fp @@ -0,0 +1,18 @@ +//created by Evil Space Tomato + +vec4 ProcessTexel() +{ + vec2 texCoord = vTexCoord.st; + vec4 basicColor = getTexel(texCoord); + + float texX = texCoord.x / 3.0 + 0.66; + float texY = 0.34 - texCoord.y / 3.0; + float vX = (texX/texY)*21.0; + float vY = (texY/texX)*13.0; + float test = mod(timer*2.0+(vX + vY), 0.5); + + basicColor.a = basicColor.a * test; + basicColor.r = basicColor.g = basicColor.b = 0.0; + + return basicColor; +} diff --git a/wadsrc/static/shaders_gles/glsl/fuzz_smoothnoise.fp b/wadsrc/static/shaders_gles/glsl/fuzz_smoothnoise.fp new file mode 100644 index 0000000000..d446a3d0a9 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/fuzz_smoothnoise.fp @@ -0,0 +1,19 @@ +//created by Evil Space Tomato + +vec4 ProcessTexel() +{ + vec2 texCoord = vTexCoord.st; + vec4 basicColor = getTexel(texCoord); + + float texX = sin(mod(texCoord.x * 100.0 + timer*5.0, 3.489)) + texCoord.x / 4.0; + float texY = cos(mod(texCoord.y * 100.0 + timer*5.0, 3.489)) + texCoord.y / 4.0; + float vX = (texX/texY)*21.0; + float vY = (texY/texX)*13.0; + + + float test = mod(timer*2.0+(vX + vY), 0.5); + basicColor.a = basicColor.a * test; + + basicColor.rgb = vec3(0.0,0.0,0.0); + return basicColor; +} diff --git a/wadsrc/static/shaders_gles/glsl/fuzz_smoothtranslucent.fp b/wadsrc/static/shaders_gles/glsl/fuzz_smoothtranslucent.fp new file mode 100644 index 0000000000..1b727a1bc6 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/fuzz_smoothtranslucent.fp @@ -0,0 +1,18 @@ +//created by Evil Space Tomato + +vec4 ProcessTexel() +{ + vec2 texCoord = vTexCoord.st; + vec4 basicColor = getTexel(texCoord); + + float texX = sin(texCoord.x * 100.0 + timer*5.0); + float texY = cos(texCoord.x * 100.0 + timer*5.0); + float vX = (texX/texY)*21.0; + float vY = (texY/texX)*13.0; + + float test = mod(timer*2.0+(vX + vY), 0.5); + + basicColor.a = basicColor.a * test; + + return basicColor; +} diff --git a/wadsrc/static/shaders_gles/glsl/fuzz_software.fp b/wadsrc/static/shaders_gles/glsl/fuzz_software.fp new file mode 100644 index 0000000000..1edcb0099e --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/fuzz_software.fp @@ -0,0 +1,21 @@ +//created by Evil Space Tomato + +vec4 ProcessTexel() +{ + vec2 texCoord = vTexCoord.st; + vec4 basicColor = getTexel(texCoord); + + texCoord.x = float( int(texCoord.x * 128.0) ) / 128.0; + texCoord.y = float( int(texCoord.y * 128.0) ) / 128.0; + + float texX = texCoord.x / 3.0 + 0.66; + float texY = 0.34 - texCoord.y / 3.0; + float vX = (texX/texY)*21.0; + float vY = (texY/texX)*13.0; + float test = mod(timer*2.0+(vX + vY), 0.5); + + basicColor.a = basicColor.a * test; + basicColor.r = basicColor.g = basicColor.b = 0.0; + + return basicColor; +} diff --git a/wadsrc/static/shaders_gles/glsl/fuzz_standard.fp b/wadsrc/static/shaders_gles/glsl/fuzz_standard.fp new file mode 100644 index 0000000000..1edcb0099e --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/fuzz_standard.fp @@ -0,0 +1,21 @@ +//created by Evil Space Tomato + +vec4 ProcessTexel() +{ + vec2 texCoord = vTexCoord.st; + vec4 basicColor = getTexel(texCoord); + + texCoord.x = float( int(texCoord.x * 128.0) ) / 128.0; + texCoord.y = float( int(texCoord.y * 128.0) ) / 128.0; + + float texX = texCoord.x / 3.0 + 0.66; + float texY = 0.34 - texCoord.y / 3.0; + float vX = (texX/texY)*21.0; + float vY = (texY/texX)*13.0; + float test = mod(timer*2.0+(vX + vY), 0.5); + + basicColor.a = basicColor.a * test; + basicColor.r = basicColor.g = basicColor.b = 0.0; + + return basicColor; +} diff --git a/wadsrc/static/shaders_gles/glsl/fuzz_swirly.fp b/wadsrc/static/shaders_gles/glsl/fuzz_swirly.fp new file mode 100644 index 0000000000..266858999e --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/fuzz_swirly.fp @@ -0,0 +1,18 @@ +//created by Evil Space Tomato + +vec4 ProcessTexel() +{ + vec2 texCoord = vTexCoord.st; + vec4 basicColor = getTexel(texCoord); + + float texX = sin(texCoord.x * 100.0 + timer*5.0); + float texY = cos(texCoord.x * 100.0 + timer*5.0); + float vX = (texX/texY)*21.0; + float vY = (texY/texX)*13.0; + float test = mod(timer*2.0+(vX + vY), 0.5); + + basicColor.a = basicColor.a * test; + basicColor.r = basicColor.g = basicColor.b = 0.0; + + return basicColor; +} diff --git a/wadsrc/static/shaders_gles/glsl/main.fp b/wadsrc/static/shaders_gles/glsl/main.fp new file mode 100644 index 0000000000..92e77eefe9 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/main.fp @@ -0,0 +1,566 @@ + +varying vec4 vTexCoord; +varying vec4 vColor; +varying vec4 pixelpos; +varying vec3 glowdist; +varying vec3 gradientdist; +varying vec4 vWorldNormal; +varying vec4 vEyeNormal; + +#ifdef NO_CLIPDISTANCE_SUPPORT +varying vec4 ClipDistanceA; +varying vec4 ClipDistanceB; +#endif + + +struct Material +{ + vec4 Base; + vec4 Bright; + vec4 Glow; + vec3 Normal; + vec3 Specular; + float Glossiness; + float SpecularLevel; +}; + +vec4 Process(vec4 color); +vec4 ProcessTexel(); +Material ProcessMaterial(); // note that this is deprecated. Use SetupMaterial! +void SetupMaterial(inout Material mat); +vec4 ProcessLight(Material mat, vec4 color); +vec3 ProcessMaterialLight(Material material, vec3 color); +vec2 GetTexCoord(); + +// These get Or'ed into uTextureMode because it only uses its 3 lowermost bits. +//const int TEXF_Brightmap = 0x10000; +//const int TEXF_Detailmap = 0x20000; +//const int TEXF_Glowmap = 0x40000; + + +//=========================================================================== +// +// Color to grayscale +// +//=========================================================================== + +float grayscale(vec4 color) +{ + return dot(color.rgb, vec3(0.3, 0.56, 0.14)); +} + +//=========================================================================== +// +// Desaturate a color +// +//=========================================================================== + +vec4 dodesaturate(vec4 texel, float factor) +{ + if (factor != 0.0) + { + float gray = grayscale(texel); + return mix (texel, vec4(gray,gray,gray,texel.a), factor); + } + else + { + return texel; + } +} + +//=========================================================================== +// +// Desaturate a color +// +//=========================================================================== + +vec4 desaturate(vec4 texel) +{ +#if (DEF_DO_DESATURATE == 1) + return dodesaturate(texel, uDesaturationFactor); +#else + return texel; +#endif +} + +//=========================================================================== +// +// Texture tinting code originally from JFDuke but with a few more options +// +//=========================================================================== + +const int Tex_Blend_Alpha = 1; +const int Tex_Blend_Screen = 2; +const int Tex_Blend_Overlay = 3; +const int Tex_Blend_Hardlight = 4; + + vec4 ApplyTextureManipulation(vec4 texel) + { + // Step 1: desaturate according to the material's desaturation factor. + texel = dodesaturate(texel, uTextureModulateColor.a); + + // Step 2: Invert if requested // TODO FIX + //if ((blendflags & 8) != 0) + //{ + // texel.rgb = vec3(1.0 - texel.r, 1.0 - texel.g, 1.0 - texel.b); + //} + + // Step 3: Apply additive color + texel.rgb += uTextureAddColor.rgb; + + // Step 4: Colorization, including gradient if set. + texel.rgb *= uTextureModulateColor.rgb; + + // Before applying the blend the value needs to be clamped to [0..1] range. + texel.rgb = clamp(texel.rgb, 0.0, 1.0); + + // Step 5: Apply a blend. This may just be a translucent overlay or one of the blend modes present in current Build engines. +#if (DEF_BLEND_FLAGS != 0) + + vec3 tcol = texel.rgb * 255.0; // * 255.0 to make it easier to reuse the integer math. + vec4 tint = uTextureBlendColor * 255.0; + +#if (DEF_BLEND_FLAGS == 1) + + tcol.b = tcol.b * (1.0 - uTextureBlendColor.a) + tint.b * uTextureBlendColor.a; + tcol.g = tcol.g * (1.0 - uTextureBlendColor.a) + tint.g * uTextureBlendColor.a; + tcol.r = tcol.r * (1.0 - uTextureBlendColor.a) + tint.r * uTextureBlendColor.a; + +#elif (DEF_BLEND_FLAGS == 2) // Tex_Blend_Screen: + tcol.b = 255.0 - (((255.0 - tcol.b) * (255.0 - tint.r)) / 256.0); + tcol.g = 255.0 - (((255.0 - tcol.g) * (255.0 - tint.g)) / 256.0); + tcol.r = 255.0 - (((255.0 - tcol.r) * (255.0 - tint.b)) / 256.0); + +#elif (DEF_BLEND_FLAGS == 3) // Tex_Blend_Overlay: + + tcol.b = tcol.b < 128.0? (tcol.b * tint.b) / 128.0 : 255.0 - (((255.0 - tcol.b) * (255.0 - tint.b)) / 128.0); + tcol.g = tcol.g < 128.0? (tcol.g * tint.g) / 128.0 : 255.0 - (((255.0 - tcol.g) * (255.0 - tint.g)) / 128.0); + tcol.r = tcol.r < 128.0? (tcol.r * tint.r) / 128.0 : 255.0 - (((255.0 - tcol.r) * (255.0 - tint.r)) / 128.0); + +#elif (DEF_BLEND_FLAGS == 4) // Tex_Blend_Hardlight: + + tcol.b = tint.b < 128.0 ? (tcol.b * tint.b) / 128.0 : 255.0 - (((255.0 - tcol.b) * (255.0 - tint.b)) / 128.0); + tcol.g = tint.g < 128.0 ? (tcol.g * tint.g) / 128.0 : 255.0 - (((255.0 - tcol.g) * (255.0 - tint.g)) / 128.0); + tcol.r = tint.r < 128.0 ? (tcol.r * tint.r) / 128.0 : 255.0 - (((255.0 - tcol.r) * (255.0 - tint.r)) / 128.0); + +#endif + + texel.rgb = tcol / 255.0; + +#endif + + return texel; +} + +//=========================================================================== +// +// This function is common for all (non-special-effect) fragment shaders +// +//=========================================================================== + +vec4 getTexel(vec2 st) +{ + vec4 texel = texture2D(tex, st); + +#if (DEF_TEXTURE_MODE == 1) + + texel.rgb = vec3(1.0,1.0,1.0); + +#elif (DEF_TEXTURE_MODE == 2)// TM_OPAQUE + + texel.a = 1.0; + +#elif (DEF_TEXTURE_MODE == 3)// TM_INVERSE + + texel = vec4(1.0-texel.r, 1.0-texel.b, 1.0-texel.g, texel.a); + +#elif (DEF_TEXTURE_MODE == 4)// TM_ALPHATEXTURE + + float gray = grayscale(texel); + texel = vec4(1.0, 1.0, 1.0, gray*texel.a); + +#elif (DEF_TEXTURE_MODE == 5)// TM_CLAMPY + + if (st.t < 0.0 || st.t > 1.0) + { + texel.a = 0.0; + } + +#elif (DEF_TEXTURE_MODE == 6)// TM_OPAQUEINVERSE + + texel = vec4(1.0-texel.r, 1.0-texel.b, 1.0-texel.g, 1.0); + + +#elif (DEF_TEXTURE_MODE == 7)//TM_FOGLAYER + + return texel; + +#endif + + // Apply the texture modification colors. +#if (DEF_BLEND_FLAGS != 0) + + // only apply the texture manipulation if it contains something. + texel = ApplyTextureManipulation(texel, DEF_BLEND_FLAGS); + +#endif + + // Apply the Doom64 style material colors on top of everything from the texture modification settings. + // This may be a bit redundant in terms of features but the data comes from different sources so this is unavoidable. + + texel.rgb += uAddColor.rgb; + +#if (DEF_USE_OBJECT_COLOR_2 == 1) + texel *= mix(uObjectColor, uObjectColor2, gradientdist.z); +#else + texel *= uObjectColor; +#endif + + // Last but not least apply the desaturation from the sector's light. + return desaturate(texel); +} + + + + +//=========================================================================== +// +// Doom software lighting equation +// +//=========================================================================== + +#define DOOMLIGHTFACTOR 232.0 + +float R_DoomLightingEquation_OLD(float light) +{ + // z is the depth in view space, positive going into the screen + float z = pixelpos.w; + + + /* L in the range 0 to 63 */ + float L = light * 63.0/31.0; + + float min_L = clamp(36.0/31.0 - L, 0.0, 1.0); + + // Fix objects getting totally black when close. + if (z < 0.0001) + z = 0.0001; + + float scale = 1.0 / z; + float index = (59.0/31.0 - L) - (scale * DOOMLIGHTFACTOR/31.0 - DOOMLIGHTFACTOR/31.0); + + // Result is the normalized colormap index (0 bright .. 1 dark) + return clamp(index, min_L, 1.0) / 32.0; +} + + +//=========================================================================== +// +// zdoom colormap equation +// +//=========================================================================== +float R_ZDoomColormap(float light, float z) +{ + float L = light * 255.0; + float vis = min(uGlobVis / z, 24.0 / 32.0); + float shade = 2.0 - (L + 12.0) / 128.0; + float lightscale = shade - vis; + return lightscale * 31.0; +} + +//=========================================================================== +// +// Doom software lighting equation +// +//=========================================================================== +float R_DoomLightingEquation(float light) +{ + // z is the depth in view space, positive going into the screen + float z; + +#if (DEF_FOG_RADIAL == 1) + z = distance(pixelpos.xyz, uCameraPos.xyz); +#else + z = pixelpos.w; +#endif + +#if (DEF_BUILD_LIGHTING == 1) // gl_lightmode 5: Build software lighting emulation. + // This is a lot more primitive than Doom's lighting... + float numShades = float(uPalLightLevels); + float curshade = (1.0 - light) * (numShades - 1.0); + float visibility = max(uGlobVis * uLightFactor * abs(z), 0.0); + float shade = clamp((curshade + visibility), 0.0, numShades - 1.0); + return clamp(shade * uLightDist, 0.0, 1.0); +#endif + + float colormap = R_ZDoomColormap(light, z); // ONLY Software mode, vanilla not yet working + +#if (DEF_BANDED_SW_LIGHTING == 1) + colormap = floor(colormap) + 0.5; +#endif + + // Result is the normalized colormap index (0 bright .. 1 dark) + return clamp(colormap, 0.0, 31.0) / 32.0; +} + + +float shadowAttenuation(vec4 lightpos, float lightcolorA) +{ + return 1.0; +} + + +float spotLightAttenuation(vec4 lightpos, vec3 spotdir, float lightCosInnerAngle, float lightCosOuterAngle) +{ + vec3 lightDirection = normalize(lightpos.xyz - pixelpos.xyz); + float cosDir = dot(lightDirection, spotdir); + return smoothstep(lightCosOuterAngle, lightCosInnerAngle, cosDir); +} + +vec3 ApplyNormalMap(vec2 texcoord) +{ + return normalize(vWorldNormal.xyz); +} + +//=========================================================================== +// +// Sets the common material properties. +// +//=========================================================================== + +void SetMaterialProps(inout Material material, vec2 texCoord) +{ + +#ifdef NPOT_EMULATION + +#if (DEF_NPOT_EMULATION == 1) + float period = floor(texCoord.t / uNpotEmulation.y); + texCoord.s += uNpotEmulation.x * floor(mod(texCoord.t, uNpotEmulation.y)); + texCoord.t = period + mod(texCoord.t, uNpotEmulation.y); +#endif + +#endif + + material.Base = getTexel(texCoord.st); + material.Normal = ApplyNormalMap(texCoord.st); + + #if (DEF_TEXTURE_FLAGS & 0x1) + material.Bright = texture2D(brighttexture, texCoord.st); + #endif + + #if (DEF_TEXTURE_FLAGS & 0x2) + { + vec4 Detail = texture2D(detailtexture, texCoord.st * uDetailParms.xy) * uDetailParms.z; + material.Base *= Detail; + } + #endif + + #if (DEF_TEXTURE_FLAGS & 0x4) + { + material.Glow = texture2D(glowtexture, texCoord.st); + } + #endif + +} + +//=========================================================================== +// +// Calculate light +// +// It is important to note that the light color is not desaturated +// due to ZDoom's implementation weirdness. Everything that's added +// on top of it, e.g. dynamic lights and glows are, though, because +// the objects emitting these lights are also. +// +// This is making this a bit more complicated than it needs to +// because we can't just desaturate the final fragment color. +// +//=========================================================================== + +vec4 getLightColor(Material material, float fogdist, float fogfactor) +{ + vec4 color = vColor; + +#if (DEF_USE_U_LIGHT_LEVEL == 1) + { + float newlightlevel = 1.0 - R_DoomLightingEquation(uLightLevel); + color.rgb *= newlightlevel; + } +#else + { + + #if (DEF_FOG_ENABLED == 1) && (DEF_FOG_COLOURED == 0) + { + // brightening around the player for light mode 2 + if (fogdist < uLightDist) + { + color.rgb *= uLightFactor - (fogdist / uLightDist) * (uLightFactor - 1.0); + } + + // + // apply light diminishing through fog equation + // + color.rgb = mix(vec3(0.0, 0.0, 0.0), color.rgb, fogfactor); + } + #endif + } +#endif + + + // + // handle glowing walls + // +#if (DEF_USE_GLOW_TOP_COLOR) + if (glowdist.x < uGlowTopColor.a) + { + color.rgb += desaturate(uGlowTopColor * (1.0 - glowdist.x / uGlowTopColor.a)).rgb; + } +#endif + + +#if (DEF_USE_GLOW_BOTTOM_COLOR) + if (glowdist.y < uGlowBottomColor.a) + { + color.rgb += desaturate(uGlowBottomColor * (1.0 - glowdist.y / uGlowBottomColor.a)).rgb; + } +#endif + + color = min(color, 1.0); + + // these cannot be safely applied by the legacy format where the implementation cannot guarantee that the values are set. +#ifndef LEGACY_USER_SHADER + // + // apply glow + // + color.rgb = mix(color.rgb, material.Glow.rgb, material.Glow.a); + + // + // apply brightmaps + // + color.rgb = min(color.rgb + material.Bright.rgb, 1.0); +#endif + + // + // apply other light manipulation by custom shaders, default is a NOP. + // + color = ProcessLight(material, color); + + // + // apply dynamic lights + // + return vec4(ProcessMaterialLight(material, color.rgb), material.Base.a * vColor.a); +} + +//=========================================================================== +// +// Applies colored fog +// +//=========================================================================== + +vec4 applyFog(vec4 frag, float fogfactor) +{ + return vec4(mix(uFogColor.rgb, frag.rgb, fogfactor), frag.a); +} + +//=========================================================================== +// +// Main shader routine +// +//=========================================================================== + +void main() +{ + + //if (ClipDistanceA.x < 0.0 || ClipDistanceA.y < 0.0 || ClipDistanceA.z < 0.0 || ClipDistanceA.w < 0.0 || ClipDistanceB.x < 0.0) discard; + +#ifndef LEGACY_USER_SHADER + Material material; + + material.Base = vec4(0.0); + material.Bright = vec4(0.0); + material.Glow = vec4(0.0); + material.Normal = vec3(0.0); + material.Specular = vec3(0.0); + material.Glossiness = 0.0; + material.SpecularLevel = 0.0; + SetupMaterial(material); +#else + Material material = ProcessMaterial(); +#endif + vec4 frag = material.Base; + +#ifndef NO_ALPHATEST + if (frag.a <= uAlphaThreshold) discard; +#endif + + #if (DEF_FOG_2D == 0) // check for special 2D 'fog' mode. + { + float fogdist = 0.0; + float fogfactor = 0.0; + + // + // calculate fog factor + // + #if (DEF_FOG_ENABLED == 1) + { + #if (DEF_FOG_RADIAL == 0) + fogdist = max(16.0, pixelpos.w); + #else + fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz)); + #endif + + fogfactor = exp2 (uFogDensity * fogdist); + } + #endif + + #if (DEF_TEXTURE_MODE != 7) + { + frag = getLightColor(material, fogdist, fogfactor); + + // + // colored fog + // + #if (DEF_FOG_ENABLED == 1) && (DEF_FOG_COLOURED == 1) + { + frag = applyFog(frag, fogfactor); + } + #endif + } + #else + { + frag = vec4(uFogColor.rgb, (1.0 - fogfactor) * frag.a * 0.75 * vColor.a); + } + #endif + } + #else + { + #if (DEF_TEXTURE_MODE == 7) + { + float gray = grayscale(frag); + vec4 cm = (uObjectColor + gray * (uAddColor - uObjectColor)) * 2; + frag = vec4(clamp(cm.rgb, 0.0, 1.0), frag.a); + } + #endif + + frag = frag * ProcessLight(material, vColor); + frag.rgb = frag.rgb + uFogColor.rgb; + } + #endif // (DEF_2D_FOG == 0) + +#if (DEF_USE_COLOR_MAP == 1) // This mostly works but doesn't look great because of the blending. + { + frag.rgb = clamp(pow(frag.rgb, vec3(uFixedColormapStart.a)), 0.0, 1.0); + if (uFixedColormapRange.a == 0.0) + { + float gray = (frag.r * 0.3 + frag.g * 0.56 + frag.b * 0.14); + vec4 cm = uFixedColormapStart + gray * uFixedColormapRange; + frag.rgb = clamp(cm.rgb, 0.0, 1.0); + } + } +#endif + + gl_FragColor = frag; + + //gl_FragColor = vec4(0.8, 0.2, 0.5, 1); + +} diff --git a/wadsrc/static/shaders_gles/glsl/main.vp b/wadsrc/static/shaders_gles/glsl/main.vp new file mode 100644 index 0000000000..1e87864c10 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/main.vp @@ -0,0 +1,134 @@ + +attribute vec4 aPosition; +attribute vec2 aTexCoord; +attribute vec4 aColor; + +varying vec4 vTexCoord; +varying vec4 vColor; + +#ifndef SIMPLE // we do not need these for simple shaders +attribute vec4 aVertex2; +attribute vec4 aNormal; +attribute vec4 aNormal2; + +varying vec4 pixelpos; +varying vec3 glowdist; +varying vec3 gradientdist; +varying vec4 vWorldNormal; +varying vec4 vEyeNormal; +#endif + +#ifdef NO_CLIPDISTANCE_SUPPORT +varying vec4 ClipDistanceA; +varying vec4 ClipDistanceB; +#endif + +void main() +{ + float ClipDistance0, ClipDistance1, ClipDistance2, ClipDistance3, ClipDistance4; + + vec2 parmTexCoord; + vec4 parmPosition; + + parmTexCoord = aTexCoord; + parmPosition = aPosition; + + #ifndef SIMPLE + vec4 worldcoord = ModelMatrix * mix(parmPosition, aVertex2, uInterpolationFactor); + #else + vec4 worldcoord = ModelMatrix * parmPosition; + #endif + + vec4 eyeCoordPos = ViewMatrix * worldcoord; + + #ifdef HAS_UNIFORM_VERTEX_DATA + if ((useVertexData & 1) == 0) + vColor = uVertexColor; + else + vColor = aColor; + #else + vColor = aColor; + #endif + + #ifndef SIMPLE + pixelpos.xyz = worldcoord.xyz; + pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w; + + if (uGlowTopColor.a > 0.0 || uGlowBottomColor.a > 0.0) + { + float topatpoint = (uGlowTopPlane.w + uGlowTopPlane.x * worldcoord.x + uGlowTopPlane.y * worldcoord.z) * uGlowTopPlane.z; + float bottomatpoint = (uGlowBottomPlane.w + uGlowBottomPlane.x * worldcoord.x + uGlowBottomPlane.y * worldcoord.z) * uGlowBottomPlane.z; + glowdist.x = topatpoint - worldcoord.y; + glowdist.y = worldcoord.y - bottomatpoint; + glowdist.z = clamp(glowdist.x / (topatpoint - bottomatpoint), 0.0, 1.0); + } + + if (uObjectColor2.a != 0.0) + { + float topatpoint = (uGradientTopPlane.w + uGradientTopPlane.x * worldcoord.x + uGradientTopPlane.y * worldcoord.z) * uGradientTopPlane.z; + float bottomatpoint = (uGradientBottomPlane.w + uGradientBottomPlane.x * worldcoord.x + uGradientBottomPlane.y * worldcoord.z) * uGradientBottomPlane.z; + gradientdist.x = topatpoint - worldcoord.y; + gradientdist.y = worldcoord.y - bottomatpoint; + gradientdist.z = clamp(gradientdist.x / (topatpoint - bottomatpoint), 0.0, 1.0); + } + + if (uSplitBottomPlane.z != 0.0) + { + ClipDistance3 = ((uSplitTopPlane.w + uSplitTopPlane.x * worldcoord.x + uSplitTopPlane.y * worldcoord.z) * uSplitTopPlane.z) - worldcoord.y; + ClipDistance4 = worldcoord.y - ((uSplitBottomPlane.w + uSplitBottomPlane.x * worldcoord.x + uSplitBottomPlane.y * worldcoord.z) * uSplitBottomPlane.z); + } + + #ifdef HAS_UNIFORM_VERTEX_DATA + if ((useVertexData & 2) == 0) + vWorldNormal = NormalModelMatrix * vec4(uVertexNormal.xyz, 1.0); + else + vWorldNormal = NormalModelMatrix * vec4(normalize(mix(aNormal.xyz, aNormal2.xyz, uInterpolationFactor)), 1.0); + #else + vWorldNormal = NormalModelMatrix * vec4(normalize(mix(aNormal.xyz, aNormal2.xyz, uInterpolationFactor)), 1.0); + #endif + vEyeNormal = NormalViewMatrix * vWorldNormal; + #endif + + #ifdef SPHEREMAP + vec3 u = normalize(eyeCoordPos.xyz); + vec4 n = normalize(NormalViewMatrix * vec4(parmTexCoord.x, 0.0, parmTexCoord.y, 0.0)); + vec3 r = reflect(u, n.xyz); + float m = 2.0 * sqrt( r.x*r.x + r.y*r.y + (r.z+1.0)*(r.z+1.0) ); + vec2 sst = vec2(r.x/m + 0.5, r.y/m + 0.5); + vTexCoord.xy = sst; + #else + vTexCoord = TextureMatrix * vec4(parmTexCoord, 0.0, 1.0); + #endif + + + if (uClipHeightDirection != 0.0) // clip planes used for reflective flats + { + ClipDistance0 = (worldcoord.y - uClipHeight) * uClipHeightDirection; + } + else if (uClipLine.x > -1000000.0) // and for line portals - this will never be active at the same time as the reflective planes clipping so it can use the same hardware clip plane. + { + ClipDistance0 = -( (worldcoord.z - uClipLine.y) * uClipLine.z + (uClipLine.x - worldcoord.x) * uClipLine.w ) + 1.0/32768.0; // allow a tiny bit of imprecisions for colinear linedefs. + } + else + { + ClipDistance0 = 1.0; + } + + // clip planes used for translucency splitting + ClipDistance1 = worldcoord.y - uClipSplit.x; + ClipDistance2 = uClipSplit.y - worldcoord.y; + + if (uSplitTopPlane == vec4(0.0)) + { + ClipDistance3 = 1.0; + ClipDistance4 = 1.0; + } + + ClipDistanceA = vec4(ClipDistance0, ClipDistance1, ClipDistance2, ClipDistance3); + ClipDistanceB = vec4(ClipDistance4, 0.0, 0.0, 0.0); + + + //gl_PointSize = 1.0; + + gl_Position = ProjectionMatrix * eyeCoordPos; +} diff --git a/wadsrc/static/shaders_gles/glsl/material_nolight.fp b/wadsrc/static/shaders_gles/glsl/material_nolight.fp new file mode 100644 index 0000000000..b714044232 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/material_nolight.fp @@ -0,0 +1,5 @@ + +vec3 ProcessMaterialLight(Material material, vec3 color) +{ + return material.Base.rgb * clamp(color + desaturate(uDynLightColor).rgb, 0.0, 1.4); +} diff --git a/wadsrc/static/shaders_gles/glsl/material_normal.fp b/wadsrc/static/shaders_gles/glsl/material_normal.fp new file mode 100644 index 0000000000..61d8abbee7 --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/material_normal.fp @@ -0,0 +1,130 @@ + +vec3 lightContribution(int i, vec3 normal) +{ + vec4 lightpos = lights[i]; + vec4 lightcolor = lights[i+1]; + vec4 lightspot1 = lights[i+2]; + vec4 lightspot2 = lights[i+3]; + + float lightdistance = distance(lightpos.xyz, pixelpos.xyz); + + //if (lightpos.w < lightdistance) + // return vec3(0.0); // Early out lights touching surface but not this fragment + + vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz); + float dotprod = dot(normal, lightdir); + + //if (dotprod < -0.0001) return vec3(0.0); // light hits from the backside. This can happen with full sector light lists and must be rejected for all cases. Note that this can cause precision issues. + + float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0); + + + // NOTE, all spot light stuff gone + return lightcolor.rgb * attenuation; + +/* + if (lightspot1.w == 1.0) + attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y); + + if (lightcolor.a < 0.0) // Sign bit is the attenuated light flag + { + attenuation *= clamp(dotprod, 0.0, 1.0); + } + + + + if (attenuation > 0.0) // Skip shadow map test if possible + { + attenuation *= shadowAttenuation(lightpos, lightcolor.a); + return lightcolor.rgb * attenuation; + } + else + { + return vec3(0.0); + } +*/ +} + + +vec3 ProcessMaterialLight(Material material, vec3 color) +{ + vec4 dynlight = uDynLightColor; + vec3 normal = material.Normal; + +#if (DEF_DYNAMIC_LIGHTS_MOD == 1) + // modulated lights + + // Some very old GLES2 hardward does not allow non-constants in a for-loop expression because it can not unroll it. + // However they do allow 'break' and use stupid hack + #if (USE_GLSL_V100 == 1) + + for(int i = 0; i < 8; i++) // Max 8 lights + { + if(i == ((uLightRange.y - uLightRange.x) / 4)) + break; + + dynlight.rgb += lightContribution(i * 4, normal); + } + + #else + + for(int i=uLightRange.x; i= 0) + { + ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1); + if (lightRange.z > lightRange.x) + { + // + // modulated lights + // + for(int i=lightRange.x; i 0.0) + { + attenuation *= shadowAttenuation(lightpos, lightcolor.a); + + vec3 radiance = lightcolor.rgb * attenuation; + + // cook-torrance brdf + float NDF = DistributionGGX(N, H, roughness); + float G = GeometrySmith(N, V, L, roughness); + vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0); + + vec3 kS = F; + vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic); + + vec3 nominator = NDF * G * F; + float denominator = 4.0 * clamp(dot(N, V), 0.0, 1.0) * clamp(dot(N, L), 0.0, 1.0); + vec3 specular = nominator / max(denominator, 0.001); + + Lo += (kD * albedo / PI + specular) * radiance; + } + } + // + // subtractive lights + // + for(int i=lightRange.y; i 0.0) + { + attenuation *= shadowAttenuation(lightpos, lightcolor.a); + + vec3 radiance = lightcolor.rgb * attenuation; + + // cook-torrance brdf + float NDF = DistributionGGX(N, H, roughness); + float G = GeometrySmith(N, V, L, roughness); + vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0); + + vec3 kS = F; + vec3 kD = (vec3(1.0) - kS) * (1.0 - metallic); + + vec3 nominator = NDF * G * F; + float denominator = 4.0 * clamp(dot(N, V), 0.0, 1.0) * clamp(dot(N, L), 0.0, 1.0); + vec3 specular = nominator / max(denominator, 0.001); + + Lo -= (kD * albedo / PI + specular) * radiance; + } + } + } + } + + // Pretend we sampled the sector light level from an irradiance map + + vec3 F = fresnelSchlickRoughness(clamp(dot(N, V), 0.0, 1.0), F0, roughness); + + vec3 kS = F; + vec3 kD = 1.0 - kS; + + vec3 irradiance = ambientLight; // texture(irradianceMap, N).rgb + vec3 diffuse = irradiance * albedo; + + //kD *= 1.0 - metallic; + //const float MAX_REFLECTION_LOD = 4.0; + //vec3 prefilteredColor = textureLod(prefilterMap, R, roughness * MAX_REFLECTION_LOD).rgb; + //vec2 envBRDF = texture(brdfLUT, vec2(clamp(dot(N, V), 0.0, 1.0), roughness)).rg; + //vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y); + + //vec3 ambient = (kD * diffuse + specular) * ao; + vec3 ambient = (kD * diffuse) * ao; + + vec3 color = max(ambient + Lo, vec3(0.0)); + + // Tonemap (reinhard) and apply sRGB gamma + //color = color / (color + vec3(1.0)); + return pow(color, vec3(1.0 / 2.2)); +} diff --git a/wadsrc/static/shaders_gles/glsl/material_specular.fp b/wadsrc/static/shaders_gles/glsl/material_specular.fp new file mode 100644 index 0000000000..f6c142308f --- /dev/null +++ b/wadsrc/static/shaders_gles/glsl/material_specular.fp @@ -0,0 +1,95 @@ + +vec2 lightAttenuation(int i, vec3 normal, vec3 viewdir, float lightcolorA) +{ + vec4 lightpos = lights[i]; + vec4 lightspot1 = lights[i+2]; + vec4 lightspot2 = lights[i+3]; + + float lightdistance = distance(lightpos.xyz, pixelpos.xyz); + if (lightpos.w < lightdistance) + return vec2(0.0); // Early out lights touching surface but not this fragment + + float attenuation = clamp((lightpos.w - lightdistance) / lightpos.w, 0.0, 1.0); + + if (lightspot1.w == 1.0) + attenuation *= spotLightAttenuation(lightpos, lightspot1.xyz, lightspot2.x, lightspot2.y); + + vec3 lightdir = normalize(lightpos.xyz - pixelpos.xyz); + + if (lightcolorA < 0.0) // Sign bit is the attenuated light flag + attenuation *= clamp(dot(normal, lightdir), 0.0, 1.0); + + if (attenuation > 0.0) // Skip shadow map test if possible + attenuation *= shadowAttenuation(lightpos, lightcolorA); + + if (attenuation <= 0.0) + return vec2(0.0); + + float glossiness = uSpecularMaterial.x; + float specularLevel = uSpecularMaterial.y; + + vec3 halfdir = normalize(viewdir + lightdir); + float specAngle = clamp(dot(halfdir, normal), 0.0, 1.0); + float phExp = glossiness * 4.0; + return vec2(attenuation, attenuation * specularLevel * pow(specAngle, phExp)); +} + +vec3 ProcessMaterialLight(Material material, vec3 color) +{ + vec4 dynlight = uDynLightColor; + vec4 specular = vec4(0.0, 0.0, 0.0, 1.0); + + vec3 normal = material.Normal; + vec3 viewdir = normalize(uCameraPos.xyz - pixelpos.xyz); + + if (uLightIndex >= 0) + { + ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1); + if (lightRange.z > lightRange.x) + { + // modulated lights + for(int i=lightRange.x; i= 0) + { + ivec4 lightRange = ivec4(lights[uLightIndex]) + ivec4(uLightIndex + 1); + if (lightRange.w > lightRange.z) + { + vec4 addlight = vec4(0.0,0.0,0.0,0.0); + + // additive lights + for(int i=lightRange.z; i= edgeVert; + FxaaFloat subpixA = subpixNSWE * 2.0 + subpixNWSWNESE; +/*--------------------------------------------------------------------------*/ + if(!horzSpan) lumaN = lumaW; + if(!horzSpan) lumaS = lumaE; + if(horzSpan) lengthSign = fxaaQualityRcpFrame.y; + FxaaFloat subpixB = (subpixA * (1.0/12.0)) - lumaM; +/*--------------------------------------------------------------------------*/ + FxaaFloat gradientN = lumaN - lumaM; + FxaaFloat gradientS = lumaS - lumaM; + FxaaFloat lumaNN = lumaN + lumaM; + FxaaFloat lumaSS = lumaS + lumaM; + FxaaBool pairN = abs(gradientN) >= abs(gradientS); + FxaaFloat gradient = max(abs(gradientN), abs(gradientS)); + if(pairN) lengthSign = -lengthSign; + FxaaFloat subpixC = FxaaSat(abs(subpixB) * subpixRcpRange); +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posB; + posB.x = posM.x; + posB.y = posM.y; + FxaaFloat2 offNP; + offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x; + offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y; + if(!horzSpan) posB.x += lengthSign * 0.5; + if( horzSpan) posB.y += lengthSign * 0.5; +/*--------------------------------------------------------------------------*/ + FxaaFloat2 posN; + posN.x = posB.x - offNP.x * FXAA_QUALITY__P0; + posN.y = posB.y - offNP.y * FXAA_QUALITY__P0; + FxaaFloat2 posP; + posP.x = posB.x + offNP.x * FXAA_QUALITY__P0; + posP.y = posB.y + offNP.y * FXAA_QUALITY__P0; + FxaaFloat subpixD = ((-2.0)*subpixC) + 3.0; + FxaaFloat lumaEndN = FxaaLuma(FxaaTexTop(tex, posN)); + FxaaFloat subpixE = subpixC * subpixC; + FxaaFloat lumaEndP = FxaaLuma(FxaaTexTop(tex, posP)); +/*--------------------------------------------------------------------------*/ + if(!pairN) lumaNN = lumaSS; + FxaaFloat gradientScaled = gradient * 1.0/4.0; + FxaaFloat lumaMM = lumaM - lumaNN * 0.5; + FxaaFloat subpixF = subpixD * subpixE; + FxaaBool lumaMLTZero = lumaMM < 0.0; +/*--------------------------------------------------------------------------*/ + lumaEndN -= lumaNN * 0.5; + lumaEndP -= lumaNN * 0.5; + FxaaBool doneN = abs(lumaEndN) >= gradientScaled; + FxaaBool doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P1; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P1; + FxaaBool doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P1; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P1; +/*--------------------------------------------------------------------------*/ + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P2; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P2; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P2; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P2; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 3) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P3; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P3; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P3; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P3; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 4) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P4; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P4; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P4; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P4; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 5) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P5; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P5; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P5; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P5; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 6) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P6; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P6; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P6; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P6; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 7) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P7; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P7; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P7; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P7; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 8) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P8; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P8; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P8; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P8; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 9) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P9; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P9; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P9; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P9; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 10) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P10; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P10; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P10; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P10; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 11) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P11; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P11; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P11; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P11; +/*--------------------------------------------------------------------------*/ + #if (FXAA_QUALITY__PS > 12) + if(doneNP) { + if(!doneN) lumaEndN = FxaaLuma(FxaaTexTop(tex, posN.xy)); + if(!doneP) lumaEndP = FxaaLuma(FxaaTexTop(tex, posP.xy)); + if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5; + if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5; + doneN = abs(lumaEndN) >= gradientScaled; + doneP = abs(lumaEndP) >= gradientScaled; + if(!doneN) posN.x -= offNP.x * FXAA_QUALITY__P12; + if(!doneN) posN.y -= offNP.y * FXAA_QUALITY__P12; + doneNP = (!doneN) || (!doneP); + if(!doneP) posP.x += offNP.x * FXAA_QUALITY__P12; + if(!doneP) posP.y += offNP.y * FXAA_QUALITY__P12; +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } + #endif +/*--------------------------------------------------------------------------*/ + } +/*--------------------------------------------------------------------------*/ + FxaaFloat dstN = posM.x - posN.x; + FxaaFloat dstP = posP.x - posM.x; + if(!horzSpan) dstN = posM.y - posN.y; + if(!horzSpan) dstP = posP.y - posM.y; +/*--------------------------------------------------------------------------*/ + FxaaBool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero; + FxaaFloat spanLength = (dstP + dstN); + FxaaBool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero; + FxaaFloat spanLengthRcp = 1.0/spanLength; +/*--------------------------------------------------------------------------*/ + FxaaBool directionN = dstN < dstP; + FxaaFloat dst = min(dstN, dstP); + FxaaBool goodSpan = directionN ? goodSpanN : goodSpanP; + FxaaFloat subpixG = subpixF * subpixF; + FxaaFloat pixelOffset = (dst * (-spanLengthRcp)) + 0.5; + FxaaFloat subpixH = subpixG * fxaaQualitySubpix; +/*--------------------------------------------------------------------------*/ + FxaaFloat pixelOffsetGood = goodSpan ? pixelOffset : 0.0; + FxaaFloat pixelOffsetSubpix = max(pixelOffsetGood, subpixH); + if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign; + if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign; + #if (FXAA_DISCARD == 1) + return FxaaTexTop(tex, posM); + #else + return FxaaFloat4(FxaaTexTop(tex, posM).xyz, lumaM); + #endif +} + +void main() +{ + FragColor = FxaaPixelShader(TexCoord, InputTexture, ReciprocalResolution, 0.75f, 0.166f, 0.0833f); +} + +#endif // FXAA_LUMA_PASS diff --git a/wadsrc/static/shaders_gles/pp/lensdistortion.fp b/wadsrc/static/shaders_gles/pp/lensdistortion.fp new file mode 100644 index 0000000000..1b0d47b4ff --- /dev/null +++ b/wadsrc/static/shaders_gles/pp/lensdistortion.fp @@ -0,0 +1,54 @@ +/* + Original Lens Distortion Algorithm from SSontech + http://www.ssontech.com/content/lensalg.htm + + If (u,v) are the coordinates of a feature in the undistorted perfect + image plane, then (u', v') are the coordinates of the feature on the + distorted image plate, ie the scanned or captured image from the + camera. The distortion occurs radially away from the image center, + with correction for the image aspect ratio (image_aspect = physical + image width/height), as follows: + + r2 = image_aspect*image_aspect*u*u + v*v + f = 1 + r2*(k + kcube*sqrt(r2)) + u' = f*u + v' = f*v + + The constant k is the distortion coefficient that appears on the lens + panel and through Sizzle. It is generally a small positive or negative + number under 1%. The constant kcube is the cubic distortion value found + on the image preprocessor's lens panel: it can be used to undistort or + redistort images, but it does not affect or get computed by the solver. + When no cubic distortion is needed, neither is the square root, saving + time. + + Chromatic Aberration example, + using red distord channel with green and blue undistord channel: + + k = vec3(-0.15, 0.0, 0.0); + kcube = vec3(0.15, 0.0, 0.0); +*/ + +layout(location=0) in vec2 TexCoord; +layout(location=0) out vec4 FragColor; + +layout(binding=0) uniform sampler2D InputTexture; + +void main() +{ + vec2 position = (TexCoord - vec2(0.5)); + + vec2 p = vec2(position.x * Aspect, position.y); + float r2 = dot(p, p); + vec3 f = vec3(1.0) + r2 * (k.rgb + kcube.rgb * sqrt(r2)); + + vec3 x = f * position.x * Scale + 0.5; + vec3 y = f * position.y * Scale + 0.5; + + vec3 c; + c.r = texture(InputTexture, vec2(x.r, y.r)).r; + c.g = texture(InputTexture, vec2(x.g, y.g)).g; + c.b = texture(InputTexture, vec2(x.b, y.b)).b; + + FragColor = vec4(c, 1.0); +} diff --git a/wadsrc/static/shaders_gles/pp/lineardepth.fp b/wadsrc/static/shaders_gles/pp/lineardepth.fp new file mode 100644 index 0000000000..7966e310a7 --- /dev/null +++ b/wadsrc/static/shaders_gles/pp/lineardepth.fp @@ -0,0 +1,38 @@ + +layout(location=0) in vec2 TexCoord; +layout(location=0) out vec4 FragColor; + +#if defined(MULTISAMPLE) +layout(binding=0) uniform sampler2DMS DepthTexture; +layout(binding=1) uniform sampler2DMS ColorTexture; +#else +layout(binding=0) uniform sampler2D DepthTexture; +layout(binding=1) uniform sampler2D ColorTexture; +#endif + +float normalizeDepth(float depth) +{ + float normalizedDepth = clamp(InverseDepthRangeA * depth + InverseDepthRangeB, 0.0, 1.0); + return 1.0 / (normalizedDepth * LinearizeDepthA + LinearizeDepthB); +} + +void main() +{ + vec2 uv = Offset + TexCoord * Scale; + +#if defined(MULTISAMPLE) + ivec2 texSize = textureSize(DepthTexture); +#else + ivec2 texSize = textureSize(DepthTexture, 0); +#endif + + ivec2 ipos = ivec2(max(uv * vec2(texSize), vec2(0.0))); + +#if defined(MULTISAMPLE) + float depth = normalizeDepth(texelFetch(ColorTexture, ipos, SampleIndex).a != 0.0 ? texelFetch(DepthTexture, ipos, SampleIndex).x : 1.0); +#else + float depth = normalizeDepth(texelFetch(ColorTexture, ipos, 0).a != 0.0 ? texelFetch(DepthTexture, ipos, 0).x : 1.0); +#endif + + FragColor = vec4(depth, 0.0, 0.0, 1.0); +} diff --git a/wadsrc/static/shaders_gles/pp/present.fp b/wadsrc/static/shaders_gles/pp/present.fp new file mode 100644 index 0000000000..a27b78f338 --- /dev/null +++ b/wadsrc/static/shaders_gles/pp/present.fp @@ -0,0 +1,32 @@ + +varying vec2 TexCoord; + +uniform sampler2D InputTexture; +uniform sampler2D DitherTexture; + +vec4 ApplyGamma(vec4 c) +{ + vec3 valgray; + + valgray = mix(vec3(dot(c.rgb, vec3(0.3,0.56,0.14))), c.rgb, Saturation); + + vec3 val = valgray * Contrast - (Contrast - 1.0) * 0.5; + val += Brightness * 0.5; + val = pow(max(val, vec3(0.0)), vec3(InvGamma)); + return vec4(val, c.a); +} + +//vec4 Dither(vec4 c) +//{ +// if (ColorScale == 0.0) +// return c; +// vec2 texSize = vec2(textureSize(DitherTexture, 0)); +// float threshold = texture2D(DitherTexture, gl_FragCoord.xy / texSize).r; +// return vec4(floor(c.rgb * ColorScale + threshold) / ColorScale, c.a); +//} + + +void main() +{ + gl_FragColor = ApplyGamma(texture2D(InputTexture, UVOffset + TexCoord * UVScale)); +} diff --git a/wadsrc/static/shaders_gles/pp/present_checker3d.fp b/wadsrc/static/shaders_gles/pp/present_checker3d.fp new file mode 100644 index 0000000000..36d77e2506 --- /dev/null +++ b/wadsrc/static/shaders_gles/pp/present_checker3d.fp @@ -0,0 +1,33 @@ + +layout(location=0) in vec2 TexCoord; +layout(location=0) out vec4 FragColor; + +layout(binding=0) uniform sampler2D LeftEyeTexture; +layout(binding=1) uniform sampler2D RightEyeTexture; + +vec4 ApplyGamma(vec4 c) +{ + vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5; + val += Brightness * 0.5; + val = pow(max(val, vec3(0.0)), vec3(InvGamma)); + return vec4(val, c.a); +} + +void main() +{ + int thisVerticalPixel = int(gl_FragCoord.y); // Bottom row is typically the right eye, when WindowHeight is even + int thisHorizontalPixel = int(gl_FragCoord.x); // column + bool isLeftEye = (thisVerticalPixel // because we want to alternate eye view on each row + + thisHorizontalPixel // and each column + + WindowPositionParity // because the window might not be aligned to the screen + ) % 2 == 0; + vec4 inputColor; + if (isLeftEye) { + inputColor = texture(LeftEyeTexture, UVOffset + TexCoord * UVScale); + } + else { + // inputColor = vec4(0, 1, 0, 1); + inputColor = texture(RightEyeTexture, UVOffset + TexCoord * UVScale); + } + FragColor = ApplyGamma(inputColor); +} diff --git a/wadsrc/static/shaders_gles/pp/present_column3d.fp b/wadsrc/static/shaders_gles/pp/present_column3d.fp new file mode 100644 index 0000000000..cf8758e3aa --- /dev/null +++ b/wadsrc/static/shaders_gles/pp/present_column3d.fp @@ -0,0 +1,31 @@ + +layout(location=0) in vec2 TexCoord; +layout(location=0) out vec4 FragColor; + +layout(binding=0) uniform sampler2D LeftEyeTexture; +layout(binding=1) uniform sampler2D RightEyeTexture; + +vec4 ApplyGamma(vec4 c) +{ + vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5; + val += Brightness * 0.5; + val = pow(max(val, vec3(0.0)), vec3(InvGamma)); + return vec4(val, c.a); +} + +void main() +{ + int thisHorizontalPixel = int(gl_FragCoord.x); // zero-based column index from left + bool isLeftEye = (thisHorizontalPixel // because we want to alternate eye view on each column + + WindowPositionParity // because the window might not be aligned to the screen + ) % 2 == 0; + vec4 inputColor; + if (isLeftEye) { + inputColor = texture(LeftEyeTexture, UVOffset + TexCoord * UVScale); + } + else { + // inputColor = vec4(0, 1, 0, 1); + inputColor = texture(RightEyeTexture, UVOffset + TexCoord * UVScale); + } + FragColor = ApplyGamma(inputColor); +} diff --git a/wadsrc/static/shaders_gles/pp/present_row3d.fp b/wadsrc/static/shaders_gles/pp/present_row3d.fp new file mode 100644 index 0000000000..a88be0ed0e --- /dev/null +++ b/wadsrc/static/shaders_gles/pp/present_row3d.fp @@ -0,0 +1,31 @@ + +layout(location=0) in vec2 TexCoord; +layout(location=0) out vec4 FragColor; + +layout(binding=0) uniform sampler2D LeftEyeTexture; +layout(binding=1) uniform sampler2D RightEyeTexture; + +vec4 ApplyGamma(vec4 c) +{ + vec3 val = c.rgb * Contrast - (Contrast - 1.0) * 0.5; + val += Brightness * 0.5; + val = pow(max(val, vec3(0.0)), vec3(InvGamma)); + return vec4(val, c.a); +} + +void main() +{ + int thisVerticalPixel = int(gl_FragCoord.y); // Bottom row is typically the right eye, when WindowHeight is even + bool isLeftEye = (thisVerticalPixel // because we want to alternate eye view on each row + + WindowPositionParity // because the window might not be aligned to the screen + ) % 2 == 0; + vec4 inputColor; + if (isLeftEye) { + inputColor = texture(LeftEyeTexture, UVOffset + TexCoord * UVScale); + } + else { + // inputColor = vec4(0, 1, 0, 1); + inputColor = texture(RightEyeTexture, UVOffset + TexCoord * UVScale); + } + FragColor = ApplyGamma(inputColor); +} diff --git a/wadsrc/static/shaders_gles/pp/screenquad.vp b/wadsrc/static/shaders_gles/pp/screenquad.vp new file mode 100644 index 0000000000..87378f6e95 --- /dev/null +++ b/wadsrc/static/shaders_gles/pp/screenquad.vp @@ -0,0 +1,11 @@ + +attribute vec4 PositionInProjection; +attribute vec2 UV; + +varying vec2 TexCoord; + +void main() +{ + gl_Position = PositionInProjection; + TexCoord = UV; +} diff --git a/wadsrc/static/shaders_gles/pp/shadowmap.fp b/wadsrc/static/shaders_gles/pp/shadowmap.fp new file mode 100644 index 0000000000..ec141f0fcd --- /dev/null +++ b/wadsrc/static/shaders_gles/pp/shadowmap.fp @@ -0,0 +1,190 @@ + +layout(location=0) in vec2 TexCoord; +layout(location=0) out vec4 FragColor; + +// A node in an AABB binary tree with lines stored in the leaf nodes +struct GPUNode +{ + vec2 aabb_min; // Min xy values for the axis-aligned box containing the node and its subtree + vec2 aabb_max; // Max xy values + int left; // Left subnode index + int right; // Right subnode index + int line_index; // Line index if it is a leaf node, otherwise -1 + int padding; // Unused - maintains 16 byte alignment +}; + +// 2D line segment, referenced by leaf nodes +struct GPULine +{ + vec2 pos; // Line start position + vec2 delta; // Line end position - line start position +}; + +layout(std430, binding = 4) buffer LightNodes +{ + GPUNode nodes[]; +}; + +layout(std430, binding = 5) buffer LightLines +{ + GPULine lines[]; +}; + +layout(std430, binding = 6) buffer LightList +{ + vec4 lights[]; +}; + +// Overlap test between line segment and axis-aligned bounding box. Returns true if they overlap. +bool overlapRayAABB(vec2 ray_start2d, vec2 ray_end2d, vec2 aabb_min2d, vec2 aabb_max2d) +{ + // To do: simplify test to use a 2D test + vec3 ray_start = vec3(ray_start2d, 0.0); + vec3 ray_end = vec3(ray_end2d, 0.0); + vec3 aabb_min = vec3(aabb_min2d, -1.0); + vec3 aabb_max = vec3(aabb_max2d, 1.0); + + vec3 c = (ray_start + ray_end) * 0.5f; + vec3 w = ray_end - c; + vec3 h = (aabb_max - aabb_min) * 0.5f; // aabb.extents(); + + c -= (aabb_max + aabb_min) * 0.5f; // aabb.center(); + + vec3 v = abs(w); + + if (abs(c.x) > v.x + h.x || abs(c.y) > v.y + h.y || abs(c.z) > v.z + h.z) + return false; // disjoint; + + if (abs(c.y * w.z - c.z * w.y) > h.y * v.z + h.z * v.y || + abs(c.x * w.z - c.z * w.x) > h.x * v.z + h.z * v.x || + abs(c.x * w.y - c.y * w.x) > h.x * v.y + h.y * v.x) + return false; // disjoint; + + return true; // overlap; +} + +// Intersection test between two line segments. +// Returns the intersection point as a value between 0-1 on the ray line segment. 1.0 if there was no hit. +float intersectRayLine(vec2 ray_start, vec2 ray_end, int line_index, vec2 raydelta, float rayd, float raydist2) +{ + const float epsilon = 0.0000001; + GPULine line = lines[line_index]; + + vec2 raynormal = vec2(raydelta.y, -raydelta.x); + + float den = dot(raynormal, line.delta); + if (abs(den) > epsilon) + { + float t_line = (rayd - dot(raynormal, line.pos)) / den; + if (t_line >= 0.0 && t_line <= 1.0) + { + vec2 linehitdelta = line.pos + line.delta * t_line - ray_start; + float t = dot(raydelta, linehitdelta) / raydist2; + return t > 0.0 ? t : 1.0; + } + } + + return 1.0; +} + +// Returns true if an AABB tree node is a leaf node. Leaf nodes contains a line. +bool isLeaf(int node_index) +{ + return nodes[node_index].line_index != -1; +} + +// Perform ray intersection test between the ray line segment and all the lines in the AABB binary tree. +// Returns the intersection point as a value between 0-1 on the ray line segment. 1.0 if there was no hit. +float rayTest(vec2 ray_start, vec2 ray_end) +{ + vec2 raydelta = ray_end - ray_start; + float raydist2 = dot(raydelta, raydelta); + vec2 raynormal = vec2(raydelta.y, -raydelta.x); + float rayd = dot(raynormal, ray_start); + if (raydist2 < 1.0) + return 1.0; + + float t = 1.0; + + // Walk the AABB binary tree searching for nodes touching the ray line segment's AABB box. + // When it reaches a leaf node, use a line segment intersection test to see if we got a hit. + + int stack[32]; + int stack_pos = 1; + stack[0] = NodesCount - 1; + while (stack_pos > 0) + { + int node_index = stack[stack_pos - 1]; + + if (!overlapRayAABB(ray_start, ray_end, nodes[node_index].aabb_min, nodes[node_index].aabb_max)) + { + stack_pos--; + } + else if (isLeaf(node_index)) + { + t = min(intersectRayLine(ray_start, ray_end, nodes[node_index].line_index, raydelta, rayd, raydist2), t); + stack_pos--; + } + else if (stack_pos == 32) + { + stack_pos--; // stack overflow + } + else + { + stack[stack_pos - 1] = nodes[node_index].left; + stack[stack_pos] = nodes[node_index].right; + stack_pos++; + } + } + + return t; +} + +void main() +{ + // Find the light that belongs to this texel in the shadowmap texture we output to: + + int lightIndex = int(gl_FragCoord.y); + + vec4 light = lights[lightIndex]; + float radius = light.w; + vec2 lightpos = light.xy; + + if (radius > 0.0) + { + // We found an active light. Calculate the ray direction for the texel. + // + // The texels are laid out so that there are four projections: + // + // * top-left to top-right + // * top-right to bottom-right + // * bottom-right to bottom-left + // * bottom-left to top-left + // + vec2 raydir; + float u = gl_FragCoord.x / ShadowmapQuality * 4.0; + switch (int(u)) + { + case 0: raydir = vec2(u * 2.0 - 1.0, 1.0); break; + case 1: raydir = vec2(1.0, 1.0 - (u - 1.0) * 2.0); break; + case 2: raydir = vec2(1.0 - (u - 2.0) * 2.0, -1.0); break; + case 3: raydir = vec2(-1.0, (u - 3.0) * 2.0 - 1.0); break; + } + + // Find the position for the ray starting at the light position and travelling until light contribution is zero: + vec2 pixelpos = lightpos + raydir * radius; + + // Check if we hit any line between the light and the end position: + float t = rayTest(lightpos, pixelpos); + + // Calculate the square distance for the hit, if any: + vec2 delta = (pixelpos - lightpos) * t; + float dist2 = dot(delta, delta); + + FragColor = vec4(dist2, 0.0, 0.0, 1.0); + } + else + { + FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } +} diff --git a/wadsrc/static/shaders_gles/pp/ssao.fp b/wadsrc/static/shaders_gles/pp/ssao.fp new file mode 100644 index 0000000000..b3ab1178cd --- /dev/null +++ b/wadsrc/static/shaders_gles/pp/ssao.fp @@ -0,0 +1,123 @@ + +layout(location=0) in vec2 TexCoord; +layout(location=0) out vec4 FragColor; + +layout(binding=0) uniform sampler2D DepthTexture; + +#if defined(MULTISAMPLE) +layout(binding=1) uniform sampler2DMS NormalTexture; +#else +layout(binding=1) uniform sampler2D NormalTexture; +#endif + +#if defined(USE_RANDOM_TEXTURE) +layout(binding=2) uniform sampler2D RandomTexture; +#endif + +#define PI 3.14159265358979323846 + +// Calculate eye space position for the specified texture coordinate +vec3 FetchViewPos(vec2 uv) +{ + float z = texture(DepthTexture, uv).x; + return vec3((UVToViewA * uv + UVToViewB) * z, z); +} + +#if defined(MULTISAMPLE) +vec3 SampleNormal(vec2 uv) +{ + ivec2 texSize = textureSize(NormalTexture); + ivec2 ipos = ivec2(uv * vec2(texSize)); + return texelFetch(NormalTexture, ipos, SampleIndex).xyz * 2.0 - 1.0; +} +#else +vec3 SampleNormal(vec2 uv) +{ + ivec2 texSize = textureSize(NormalTexture, 0); + ivec2 ipos = ivec2(uv * vec2(texSize)); + return texelFetch(NormalTexture, ipos, 0).xyz * 2.0 - 1.0; +} +#endif + +// Look up the eye space normal for the specified texture coordinate +vec3 FetchNormal(vec2 uv) +{ + vec3 normal = SampleNormal(Offset + uv * Scale); + if (length(normal) > 0.1) + { + normal = normalize(normal); + normal.z = -normal.z; + return normal; + } + else + { + return vec3(0.0); + } +} + +// Compute normalized 2D direction +vec2 RotateDirection(vec2 dir, vec2 cossin) +{ + return vec2(dir.x * cossin.x - dir.y * cossin.y, dir.x * cossin.y + dir.y * cossin.x); +} + +vec4 GetJitter() +{ +#if !defined(USE_RANDOM_TEXTURE) + return vec4(1,0,1,1); + //vec3 rand = noise3(TexCoord.x + TexCoord.y); + //float angle = 2.0 * PI * rand.x / NUM_DIRECTIONS; + //return vec4(cos(angle), sin(angle), rand.y, rand.z); +#else + return texture(RandomTexture, gl_FragCoord.xy / RANDOM_TEXTURE_WIDTH); +#endif +} + +// Calculates the ambient occlusion of a sample +float ComputeSampleAO(vec3 kernelPos, vec3 normal, vec3 samplePos) +{ + vec3 v = samplePos - kernelPos; + float distanceSquare = dot(v, v); + float nDotV = dot(normal, v) * inversesqrt(distanceSquare); + return clamp(nDotV - NDotVBias, 0.0, 1.0) * clamp(distanceSquare * NegInvR2 + 1.0, 0.0, 1.0); +} + +// Calculates the total ambient occlusion for the entire fragment +float ComputeAO(vec3 viewPosition, vec3 viewNormal) +{ + vec4 rand = GetJitter(); + + float radiusPixels = RadiusToScreen / viewPosition.z; + float stepSizePixels = radiusPixels / (NUM_STEPS + 1.0); + + const float directionAngleStep = 2.0 * PI / NUM_DIRECTIONS; + float ao = 0.0; + + for (float directionIndex = 0.0; directionIndex < NUM_DIRECTIONS; ++directionIndex) + { + float angle = directionAngleStep * directionIndex; + + vec2 direction = RotateDirection(vec2(cos(angle), sin(angle)), rand.xy); + float rayPixels = (rand.z * stepSizePixels + 1.0); + + for (float StepIndex = 0.0; StepIndex < NUM_STEPS; ++StepIndex) + { + vec2 sampleUV = round(rayPixels * direction) * InvFullResolution + TexCoord; + vec3 samplePos = FetchViewPos(sampleUV); + ao += ComputeSampleAO(viewPosition, viewNormal, samplePos); + rayPixels += stepSizePixels; + } + } + + ao *= AOMultiplier / (NUM_DIRECTIONS * NUM_STEPS); + return clamp(1.0 - ao * 2.0, 0.0, 1.0); +} + +void main() +{ + vec3 viewPosition = FetchViewPos(TexCoord); + vec3 viewNormal = FetchNormal(TexCoord); + float occlusion = viewNormal != vec3(0.0) ? ComputeAO(viewPosition, viewNormal) * AOStrength + (1.0 - AOStrength) : 1.0; + + FragColor = vec4(occlusion, viewPosition.z, 0.0, 1.0); +} diff --git a/wadsrc/static/shaders_gles/pp/ssaocombine.fp b/wadsrc/static/shaders_gles/pp/ssaocombine.fp new file mode 100644 index 0000000000..0d592549f3 --- /dev/null +++ b/wadsrc/static/shaders_gles/pp/ssaocombine.fp @@ -0,0 +1,41 @@ + +layout(location=0) in vec2 TexCoord; +layout(location=0) out vec4 FragColor; + +layout(binding=0) uniform sampler2D AODepthTexture; + +#if defined(MULTISAMPLE) +layout(binding=1) uniform sampler2DMS SceneFogTexture; +#else +layout(binding=1) uniform sampler2D SceneFogTexture; +#endif + +void main() +{ + vec2 uv = Offset + TexCoord * Scale; + +#if defined(MULTISAMPLE) + ivec2 texSize = textureSize(SceneFogTexture); +#else + ivec2 texSize = textureSize(SceneFogTexture, 0); +#endif + ivec2 ipos = ivec2(uv * vec2(texSize)); + +#if defined(MULTISAMPLE) + vec3 fogColor = texelFetch(SceneFogTexture, ipos, 0).rgb; +#else + vec3 fogColor = texelFetch(SceneFogTexture, ipos, 0).rgb; +#endif + + vec4 ssao = texture(AODepthTexture, TexCoord); + float attenutation = ssao.x; + + if (DebugMode == 0) + FragColor = vec4(fogColor, 1.0 - attenutation); + else if (DebugMode < 3) + FragColor = vec4(attenutation, attenutation, attenutation, 1.0); + else if (DebugMode == 3) + FragColor = vec4(ssao.yyy / 1000.0, 1.0); + else + FragColor = vec4(ssao.xyz, 1.0); +} diff --git a/wadsrc/static/shaders_gles/pp/tonemap.fp b/wadsrc/static/shaders_gles/pp/tonemap.fp new file mode 100644 index 0000000000..f18e9fc9e4 --- /dev/null +++ b/wadsrc/static/shaders_gles/pp/tonemap.fp @@ -0,0 +1,89 @@ + +layout(location=0) in vec2 TexCoord; +layout(location=0) out vec4 FragColor; + +layout(binding=0) uniform sampler2D InputTexture; + +vec3 Linear(vec3 c) +{ + //c = max(c, vec3(0.0)); + //return pow(c, 2.2); + return c * c; // cheaper, but assuming gamma of 2.0 instead of 2.2 +} + +vec3 sRGB(vec3 c) +{ + c = max(c, vec3(0.0)); + //return pow(c, vec3(1.0 / 2.2)); + return sqrt(c); // cheaper, but assuming gamma of 2.0 instead of 2.2 +} + +#if defined(LINEAR) + +vec3 Tonemap(vec3 color) +{ + return sRGB(color); +} + +#elif defined(REINHARD) + +vec3 Tonemap(vec3 color) +{ + color = color / (1.0 + color); + return sRGB(color); +} + +#elif defined(HEJLDAWSON) + +vec3 Tonemap(vec3 color) +{ + vec3 x = max(vec3(0.0), color - 0.004); + return (x * (6.2 * x + 0.5)) / (x * (6.2 * x + 1.7) + 0.06); // no sRGB needed +} + +#elif defined(UNCHARTED2) + +vec3 Uncharted2Tonemap(vec3 x) +{ + float A = 0.15; + float B = 0.50; + float C = 0.10; + float D = 0.20; + float E = 0.02; + float F = 0.30; + return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F; +} + +vec3 Tonemap(vec3 color) +{ + float W = 11.2; + vec3 curr = Uncharted2Tonemap(color); + vec3 whiteScale = vec3(1) / Uncharted2Tonemap(vec3(W)); + return sRGB(curr * whiteScale); +} + +#elif defined(PALETTE) + +layout(binding=1) uniform sampler2D PaletteLUT; + +vec3 Tonemap(vec3 color) +{ + ivec3 c = ivec3(clamp(color.rgb, vec3(0.0), vec3(1.0)) * 63.0 + 0.5); + int index = (c.r * 64 + c.g) * 64 + c.b; + int tx = index % 512; + int ty = index / 512; + return texelFetch(PaletteLUT, ivec2(tx, ty), 0).rgb; +} + +#else +#error Tonemap mode define is missing +#endif + +void main() +{ + vec3 color = texture(InputTexture, TexCoord).rgb; +#ifndef PALETTE + color = Linear(color); // needed because gzdoom's scene texture is not linear at the moment +#endif + FragColor = vec4(Tonemap(color), 1.0); +} diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index e9f617dfe5..a447a9b731 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -1,4 +1,4 @@ -version "4.5" +version "4.6" // Generic engine code #include "zscript/engine/base.zs"