[client] egl: make the bgr_bgra filter generic for 24-bit formats

This commit is contained in:
Geoffrey McRae 2023-11-08 20:29:42 +11:00
parent 3843afa927
commit c0e09e13a5
12 changed files with 154 additions and 59 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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 );

View File

@ -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_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
};

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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;

View File

@ -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";
@ -226,11 +231,12 @@ bool egl_shaderCompile(EGL_Shader * this, const char * vertex_code,
}
const int diff = (strlen(replace) - strlen(search)) * instances;
char * newCode = malloc(fragment_size + diff + 1);
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)

View File

@ -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);

View File

@ -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],