diff --git a/client/renderers/EGL/CMakeLists.txt b/client/renderers/EGL/CMakeLists.txt index 56df4c46..7ad1e9ee 100644 --- a/client/renderers/EGL/CMakeLists.txt +++ b/client/renderers/EGL/CMakeLists.txt @@ -56,7 +56,7 @@ build_shaders( shader/damage.vert shader/damage.frag shader/basic.vert - shader/convert_bgr_bgra.frag + shader/convert_24bit.frag shader/ffx_cas.frag shader/ffx_fsr1_easu.frag shader/ffx_fsr1_rcas.frag @@ -88,7 +88,7 @@ add_library(renderer_EGL STATIC postprocess.c ffx.c filter.c - filter_bgr_bgra.c + filter_24bit.c filter_ffx_cas.c filter_ffx_fsr1.c filter_downscale.c diff --git a/client/renderers/EGL/cursor.c b/client/renderers/EGL/cursor.c index 90bbda39..0c1d1e89 100644 --- a/client/renderers/EGL/cursor.c +++ b/client/renderers/EGL/cursor.c @@ -100,7 +100,7 @@ static bool cursorTexInit(struct CursorTex * t, } if (!egl_shaderCompile(t->shader, - vertex_code, vertex_size, fragment_code, fragment_size, false)) + vertex_code, vertex_size, fragment_code, fragment_size, false, NULL)) { DEBUG_ERROR("Failed to compile the cursor shader"); return false; diff --git a/client/renderers/EGL/damage.c b/client/renderers/EGL/damage.c index 45d3e118..e90ea821 100644 --- a/client/renderers/EGL/damage.c +++ b/client/renderers/EGL/damage.c @@ -77,7 +77,7 @@ bool egl_damageInit(EGL_Damage ** damage) if (!egl_shaderCompile((*damage)->shader, b_shader_damage_vert, b_shader_damage_vert_size, b_shader_damage_frag, b_shader_damage_frag_size, - false)) + false, NULL)) { DEBUG_ERROR("Failed to compile the damage shader"); return false; diff --git a/client/renderers/EGL/desktop.c b/client/renderers/EGL/desktop.c index efb3acfa..a8cca3f2 100644 --- a/client/renderers/EGL/desktop.c +++ b/client/renderers/EGL/desktop.c @@ -114,7 +114,7 @@ static bool egl_initDesktopShader( if (!egl_shaderCompile(shader->shader, vertex_code , vertex_size, fragment_code, fragment_size, - useDMA)) + useDMA, NULL)) { return false; } @@ -207,7 +207,7 @@ bool egl_desktopInit(EGL * egl, EGL_Desktop ** desktop_, EGLDisplay * display, } // this MUST be first - egl_postProcessAdd(desktop->pp, &egl_filterBGRtoBGRAOps); + egl_postProcessAdd(desktop->pp, &egl_filter24bitOps); egl_postProcessAdd(desktop->pp, &egl_filterDownscaleOps); egl_postProcessAdd(desktop->pp, &egl_filterFFXCASOps ); diff --git a/client/renderers/EGL/filter_bgr_bgra.c b/client/renderers/EGL/filter_24bit.c similarity index 74% rename from client/renderers/EGL/filter_bgr_bgra.c rename to client/renderers/EGL/filter_24bit.c index 85519ea3..b7a5e246 100644 --- a/client/renderers/EGL/filter_bgr_bgra.c +++ b/client/renderers/EGL/filter_24bit.c @@ -29,14 +29,15 @@ #include "cimgui.h" #include "basic.vert.h" -#include "convert_bgr_bgra.frag.h" +#include "convert_24bit.frag.h" -typedef struct EGL_FilterBGRtoBGRA +typedef struct EGL_Filter24bit { EGL_Filter base; bool enable; + EGL_PixelFormat format; int useDMA; unsigned int width, height; unsigned int desktopWidth, desktopHeight; @@ -48,11 +49,11 @@ typedef struct EGL_FilterBGRtoBGRA EGL_Framebuffer * fb; GLuint sampler[2]; } -EGL_FilterBGRtoBGRA; +EGL_Filter24bit; -static bool egl_filterBGRtoBGRAInit(EGL_Filter ** filter) +static bool egl_filter24bitInit(EGL_Filter ** filter) { - EGL_FilterBGRtoBGRA * this = calloc(1, sizeof(*this)); + EGL_Filter24bit * this = calloc(1, sizeof(*this)); if (!this) { DEBUG_ERROR("Failed to allocate ram"); @@ -94,9 +95,9 @@ error_this: return false; } -static void egl_filterBGRtoBGRAFree(EGL_Filter * filter) +static void egl_filter24bitFree(EGL_Filter * filter) { - EGL_FilterBGRtoBGRA * this = UPCAST(EGL_FilterBGRtoBGRA, filter); + EGL_Filter24bit * this = UPCAST(EGL_Filter24bit, filter); egl_shaderFree(&this->shader); egl_framebufferFree(&this->fb); @@ -104,22 +105,28 @@ static void egl_filterBGRtoBGRAFree(EGL_Filter * filter) free(this); } -static bool egl_filterBGRtoBGRASetup(EGL_Filter * filter, +static bool egl_filter24bitSetup(EGL_Filter * filter, enum EGL_PixelFormat pixFmt, unsigned int width, unsigned int height, unsigned int desktopWidth, unsigned int desktopHeight, bool useDMA) { - EGL_FilterBGRtoBGRA * this = UPCAST(EGL_FilterBGRtoBGRA, filter); + EGL_Filter24bit * this = UPCAST(EGL_Filter24bit, filter); if (pixFmt != EGL_PF_BGR_32 && pixFmt != EGL_PF_RGB_24) return false; - if (this->useDMA != useDMA) + if (this->useDMA != useDMA || this->format != pixFmt) { + EGL_ShaderDefine defines[] = + { + {"OUTPUT", pixFmt == EGL_PF_BGR_32 ? "fragColor.bgra" : "fragColor.rgba" }, + {0} + }; + if (!egl_shaderCompile(this->shader, - b_shader_basic_vert , b_shader_basic_vert_size, - b_shader_convert_bgr_bgra_frag, b_shader_convert_bgr_bgra_frag_size, - useDMA) + b_shader_basic_vert , b_shader_basic_vert_size, + b_shader_convert_24bit_frag, b_shader_convert_24bit_frag_size, + useDMA, defines) ) { DEBUG_ERROR("Failed to compile the shader"); @@ -144,6 +151,7 @@ static bool egl_filterBGRtoBGRASetup(EGL_Filter * filter, if (!egl_framebufferSetup(this->fb, pixFmt, desktopWidth, desktopHeight)) return false; + this->format = pixFmt; this->width = width; this->height = height; this->desktopWidth = desktopWidth; @@ -153,17 +161,17 @@ static bool egl_filterBGRtoBGRASetup(EGL_Filter * filter, return true; } -static void egl_filterBGRtoBGRAGetOutputRes(EGL_Filter * filter, +static void egl_filter24bitGetOutputRes(EGL_Filter * filter, unsigned int *width, unsigned int *height) { - EGL_FilterBGRtoBGRA * this = UPCAST(EGL_FilterBGRtoBGRA, filter); + EGL_Filter24bit * this = UPCAST(EGL_Filter24bit, filter); *width = this->desktopWidth; *height = this->desktopHeight; } -static bool egl_filterBGRtoBGRAPrepare(EGL_Filter * filter) +static bool egl_filter24bitPrepare(EGL_Filter * filter) { - EGL_FilterBGRtoBGRA * this = UPCAST(EGL_FilterBGRtoBGRA, filter); + EGL_Filter24bit * this = UPCAST(EGL_Filter24bit, filter); if (this->prepared) return true; @@ -176,10 +184,10 @@ static bool egl_filterBGRtoBGRAPrepare(EGL_Filter * filter) return true; } -static EGL_Texture * egl_filterBGRtoBGRARun(EGL_Filter * filter, +static EGL_Texture * egl_filter24bitRun(EGL_Filter * filter, EGL_FilterRects * rects, EGL_Texture * texture) { - EGL_FilterBGRtoBGRA * this = UPCAST(EGL_FilterBGRtoBGRA, filter); + EGL_Filter24bit * this = UPCAST(EGL_Filter24bit, filter); egl_framebufferBind(this->fb); @@ -194,19 +202,19 @@ static EGL_Texture * egl_filterBGRtoBGRARun(EGL_Filter * filter, return egl_framebufferGetTexture(this->fb); } -EGL_FilterOps egl_filterBGRtoBGRAOps = +EGL_FilterOps egl_filter24bitOps = { - .id = "bgrtobgra", - .name = "BGRtoBGRA", + .id = "24bit", + .name = "24bit", .type = EGL_FILTER_TYPE_INTERNAL, .earlyInit = NULL, - .init = egl_filterBGRtoBGRAInit, - .free = egl_filterBGRtoBGRAFree, + .init = egl_filter24bitInit, + .free = egl_filter24bitFree, .imguiConfig = NULL, .saveState = NULL, .loadState = NULL, - .setup = egl_filterBGRtoBGRASetup, - .getOutputRes = egl_filterBGRtoBGRAGetOutputRes, - .prepare = egl_filterBGRtoBGRAPrepare, - .run = egl_filterBGRtoBGRARun + .setup = egl_filter24bitSetup, + .getOutputRes = egl_filter24bitGetOutputRes, + .prepare = egl_filter24bitPrepare, + .run = egl_filter24bitRun }; diff --git a/client/renderers/EGL/filter_downscale.c b/client/renderers/EGL/filter_downscale.c index 10def0ac..57f68b14 100644 --- a/client/renderers/EGL/filter_downscale.c +++ b/client/renderers/EGL/filter_downscale.c @@ -316,7 +316,7 @@ static bool egl_filterDownscaleSetup(EGL_Filter * filter, b_shader_basic_vert , b_shader_basic_vert_size, b_shader_downscale_frag, b_shader_downscale_frag_size, - useDMA) + useDMA, NULL) ) { DEBUG_ERROR("Failed to compile the shader"); @@ -327,7 +327,7 @@ static bool egl_filterDownscaleSetup(EGL_Filter * filter, b_shader_basic_vert, b_shader_basic_vert_size, b_shader_downscale_linear_frag, b_shader_downscale_linear_frag_size, - useDMA) + useDMA, NULL) ) { DEBUG_ERROR("Failed to compile the shader"); @@ -338,7 +338,7 @@ static bool egl_filterDownscaleSetup(EGL_Filter * filter, b_shader_basic_vert, b_shader_basic_vert_size, b_shader_downscale_lanczos2_frag, b_shader_downscale_lanczos2_frag_size, - useDMA) + useDMA, NULL) ) { DEBUG_ERROR("Failed to compile the shader"); diff --git a/client/renderers/EGL/filter_ffx_cas.c b/client/renderers/EGL/filter_ffx_cas.c index 29d1a511..86580aef 100644 --- a/client/renderers/EGL/filter_ffx_cas.c +++ b/client/renderers/EGL/filter_ffx_cas.c @@ -222,7 +222,7 @@ static bool egl_filterFFXCASSetup(EGL_Filter * filter, if (!egl_shaderCompile(this->shader, b_shader_basic_vert , b_shader_basic_vert_size, b_shader_ffx_cas_frag, b_shader_ffx_cas_frag_size, - useDMA) + useDMA, NULL) ) { DEBUG_ERROR("Failed to compile the shader"); diff --git a/client/renderers/EGL/filter_ffx_fsr1.c b/client/renderers/EGL/filter_ffx_fsr1.c index bd5bc953..8f0758ca 100644 --- a/client/renderers/EGL/filter_ffx_fsr1.c +++ b/client/renderers/EGL/filter_ffx_fsr1.c @@ -127,7 +127,7 @@ static bool egl_filterFFXFSR1Init(EGL_Filter ** filter) if (!egl_shaderCompile(this->rcas, b_shader_basic_vert , b_shader_basic_vert_size, b_shader_ffx_fsr1_rcas_frag, b_shader_ffx_fsr1_rcas_frag_size, - false) + false, NULL) ) { DEBUG_ERROR("Failed to compile the Rcas shader"); @@ -336,7 +336,7 @@ static bool egl_filterFFXFSR1Setup(EGL_Filter * filter, if (!egl_shaderCompile(this->easu, b_shader_basic_vert , b_shader_basic_vert_size, b_shader_ffx_fsr1_easu_frag, b_shader_ffx_fsr1_easu_frag_size, - useDMA) + useDMA, NULL) ) { DEBUG_ERROR("Failed to compile the Easu shader"); diff --git a/client/renderers/EGL/filters.h b/client/renderers/EGL/filters.h index f662aa4c..aa424bd0 100644 --- a/client/renderers/EGL/filters.h +++ b/client/renderers/EGL/filters.h @@ -20,7 +20,7 @@ #pragma once -extern EGL_FilterOps egl_filterBGRtoBGRAOps; +extern EGL_FilterOps egl_filter24bitOps; extern EGL_FilterOps egl_filterDownscaleOps; extern EGL_FilterOps egl_filterFFXCASOps; extern EGL_FilterOps egl_filterFFXFSR1Ops; diff --git a/client/renderers/EGL/shader.c b/client/renderers/EGL/shader.c index 5ec4d565..9ca712a8 100644 --- a/client/renderers/EGL/shader.c +++ b/client/renderers/EGL/shader.c @@ -65,7 +65,8 @@ void egl_shaderFree(EGL_Shader ** shader) } bool egl_shaderLoad(EGL_Shader * this, - const char * vertex_file, const char * fragment_file, bool useDMA) + const char * vertex_file, const char * fragment_file, bool useDMA, + const EGL_ShaderDefine * defines) { char * vertex_code, * fragment_code; size_t vertex_size, fragment_size; @@ -89,7 +90,7 @@ bool egl_shaderLoad(EGL_Shader * this, bool ret = egl_shaderCompile(this, vertex_code, vertex_size, fragment_code, fragment_size, - useDMA); + useDMA, defines); free(vertex_code); free(fragment_code); @@ -210,8 +211,12 @@ static bool shaderCompile(EGL_Shader * this, const char * vertex_code, bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code, size_t vertex_size, const char * fragment_code, size_t fragment_size, - bool useDMA) + bool useDMA, const EGL_ShaderDefine * defines) { + bool result = false; + char * processed = NULL; + char * newCode = NULL; + if (useDMA) { const char * search = "sampler2D"; @@ -225,12 +230,13 @@ bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code, src += strlen(search); } - const int diff = (strlen(replace) - strlen(search)) * instances; - char * newCode = malloc(fragment_size + diff + 1); + const int diff = (strlen(replace) - strlen(search)) * instances; + const int newLen = fragment_size + diff; + newCode = malloc(newLen + 1); if (!newCode) { DEBUG_ERROR("Out of memory"); - return false; + goto exit; } src = fragment_code; @@ -250,20 +256,94 @@ bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code, const int final = fragment_size - (src - fragment_code); memcpy(dst, src, final); - dst[final] = 0; + dst[final] = '\0'; - bool result = shaderCompile( - this, - vertex_code, vertex_size, - newCode , fragment_size + diff); - - free(newCode); - return result; + fragment_code = newCode; + fragment_size = newLen; } - return shaderCompile(this, + if (defines) + { + // find the end of any existing lines starting with # + bool newLine = true; + bool skip = false; + int insertPos = 0; + for(int i = 0; i < fragment_size; ++i) + { + if (skip) + { + if (fragment_code[i] == '\n') + skip = false; + continue; + } + + switch(fragment_code[i]) + { + case '\n': + newLine = true; + continue; + + case ' ': + case '\t': + case '\r': + continue; + + case '#': + if (newLine) + { + skip = true; + continue; + } + //fallthrough + + default: + newLine = false; + break; + } + + if (!newLine) + { + insertPos = i - 1; + break; + } + } + + int processedLen = fragment_size; + const char * defineFormat = "#define %s %s\n"; + for(const EGL_ShaderDefine * define = defines; define->name; ++define) + processedLen += snprintf(NULL, 0, defineFormat, define->name, define->value); + + processed = malloc(processedLen); + if (!processed) + { + DEBUG_ERROR("Out of memory"); + goto exit; + } + + memcpy(processed, fragment_code, insertPos); + + int offset = insertPos; + for(const EGL_ShaderDefine * define = defines; define->name; ++define) + offset += sprintf(processed + offset, defineFormat, + define->name, define->value); + + memcpy( + processed + offset, + fragment_code + insertPos, + fragment_size - insertPos); + + fragment_code = processed; + fragment_size = processedLen; + } + + result = shaderCompile(this, vertex_code , vertex_size, fragment_code, fragment_size); + +exit: + free(processed); + free(newCode); + return result; } void egl_shaderSetUniforms(EGL_Shader * this, EGL_Uniform * uniforms, int count) diff --git a/client/renderers/EGL/shader.h b/client/renderers/EGL/shader.h index e4423aa3..cbf8e723 100644 --- a/client/renderers/EGL/shader.h +++ b/client/renderers/EGL/shader.h @@ -93,15 +93,22 @@ typedef struct EGL_Uniform } EGL_Uniform; +typedef struct EGL_ShaderDefine +{ + const char * name; + const char * value; +} +EGL_ShaderDefine; + bool egl_shaderInit(EGL_Shader ** shader); void egl_shaderFree(EGL_Shader ** shader); bool egl_shaderLoad(EGL_Shader * model, const char * vertex_file, - const char * fragment_file, bool useDMA); + const char * fragment_file, bool useDMA, const EGL_ShaderDefine * defines); bool egl_shaderCompile(EGL_Shader * model, const char * vertex_code, size_t vertex_size, const char * fragment_code, size_t fragment_size, - bool useDMA); + bool useDMA, const EGL_ShaderDefine * defines); void egl_shaderSetUniforms(EGL_Shader * shader, EGL_Uniform * uniforms, int count); diff --git a/client/renderers/EGL/shader/convert_bgr_bgra.frag b/client/renderers/EGL/shader/convert_24bit.frag similarity index 96% rename from client/renderers/EGL/shader/convert_bgr_bgra.frag rename to client/renderers/EGL/shader/convert_24bit.frag index d1bf7e3e..19ff0906 100644 --- a/client/renderers/EGL/shader/convert_bgr_bgra.frag +++ b/client/renderers/EGL/shader/convert_24bit.frag @@ -23,7 +23,7 @@ void main() uint trd = (outputPos.x * 3u + 2u) / 4u; vec4 color_2 = texelFetch(sampler1, ivec2(trd, outputPos.y), 0); - fragColor.bgra = vec4( + OUTPUT = vec4( color_0.barg[outputPos.x % 4u], color_1.gbar[outputPos.x % 4u], color_2.rgba[outputPos.x % 4u],