From ddd47368f3fb7a385e4b46abf4409fa569ac9efd Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 26 Oct 2022 14:45:22 +0200 Subject: [PATCH] wip: render/gles2: add support for 3D LUT transforms --- include/render/gles2.h | 11 ++++++++ render/gles2/renderer.c | 40 +++++++++++++++++++++++------ render/gles2/shaders/common.frag | 44 +++++++++++++++++++++++++++++--- 3 files changed, 84 insertions(+), 11 deletions(-) diff --git a/include/render/gles2.h b/include/render/gles2.h index 438bee352..7978f124d 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -64,6 +64,7 @@ struct wlr_gles2_renderer { PFNGLPUSHDEBUGGROUPKHRPROC glPushDebugGroupKHR; PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glEGLImageTargetRenderbufferStorageOES; PFNGLGETGRAPHICSRESETSTATUSKHRPROC glGetGraphicsResetStatusKHR; + PFNGLTEXIMAGE3DOESPROC glTexImage3DOES; } procs; struct { @@ -121,6 +122,16 @@ enum wlr_gles2_shader_source { WLR_GLES2_SHADER_SOURCE_TEXTURE_EXTERNAL = 4, }; +enum wlr_gles2_shader_color_transform { + WLR_GLES2_SHADER_COLOR_TRANSFORM_IDENTITY = 0, + WLR_GLES2_SHADER_COLOR_TRANSFORM_LUT_3D = 1, +}; + +struct wlr_gles2_shader_params { + enum wlr_gles2_shader_source source; + enum wlr_gles2_shader_color_transform color_transform; +}; + bool is_gles2_pixel_format_supported(const struct wlr_gles2_renderer *renderer, const struct wlr_gles2_pixel_format *format); const struct wlr_gles2_pixel_format *get_gles2_format_from_drm(uint32_t fmt); diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 6dcbac53e..7f47816b2 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -627,10 +627,12 @@ static GLuint compile_shader(struct wlr_gles2_renderer *renderer, } static GLuint link_program(struct wlr_gles2_renderer *renderer, - enum wlr_gles2_shader_source source) { + const struct wlr_gles2_shader_params *params) { static char frag_preamble[1024]; snprintf(frag_preamble, sizeof(frag_preamble), - "#define SOURCE %d\n", source); + "#define SOURCE %d\n" + "#define COLOR_TRANSFORM %d\n", + params->source, params->color_transform); push_gles2_debug(renderer); @@ -676,8 +678,8 @@ error: static bool link_tex_program(struct wlr_gles2_renderer *renderer, struct wlr_gles2_tex_shader *shader, - enum wlr_gles2_shader_source source) { - shader->program = link_program(renderer, source); + const struct wlr_gles2_shader_params *params) { + shader->program = link_program(renderer, params); if (!shader->program) { return false; } @@ -829,6 +831,10 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { } } + if (check_gl_ext(exts_str, "GL_OES_texture_3D")) { + load_gl_proc(&renderer->procs.glTexImage3DOES, "glTexImage3DOES"); + } + if (renderer->exts.KHR_debug) { glEnable(GL_DEBUG_OUTPUT_KHR); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR); @@ -843,9 +849,18 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { push_gles2_debug(renderer); + enum wlr_gles2_shader_color_transform color_transform = + WLR_GLES2_SHADER_COLOR_TRANSFORM_IDENTITY; + if (renderer->procs.glTexImage3DOES != NULL) { + color_transform = WLR_GLES2_SHADER_COLOR_TRANSFORM_LUT_3D; + } + GLuint prog; renderer->shaders.quad.program = prog = - link_program(renderer, WLR_GLES2_SHADER_SOURCE_SINGLE_COLOR); + link_program(renderer, &(struct wlr_gles2_shader_params){ + .source = WLR_GLES2_SHADER_SOURCE_SINGLE_COLOR, + .color_transform = color_transform, + }); if (!renderer->shaders.quad.program) { goto error; } @@ -854,16 +869,25 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { renderer->shaders.quad.pos_attrib = glGetAttribLocation(prog, "pos"); if (!link_tex_program(renderer, &renderer->shaders.tex_rgba, - WLR_GLES2_SHADER_SOURCE_TEXTURE_RGBA)) { + &(struct wlr_gles2_shader_params){ + .source = WLR_GLES2_SHADER_SOURCE_TEXTURE_RGBA, + .color_transform = color_transform, + })) { goto error; } if (!link_tex_program(renderer, &renderer->shaders.tex_rgbx, - WLR_GLES2_SHADER_SOURCE_TEXTURE_RGBX)) { + &(struct wlr_gles2_shader_params){ + .source = WLR_GLES2_SHADER_SOURCE_TEXTURE_RGBX, + .color_transform = color_transform, + })) { goto error; } if (renderer->exts.OES_egl_image_external && !link_tex_program(renderer, &renderer->shaders.tex_ext, - WLR_GLES2_SHADER_SOURCE_TEXTURE_EXTERNAL)) { + &(struct wlr_gles2_shader_params){ + .source = WLR_GLES2_SHADER_SOURCE_TEXTURE_EXTERNAL, + .color_transform = color_transform, + })) { goto error; } diff --git a/render/gles2/shaders/common.frag b/render/gles2/shaders/common.frag index bd178a722..989c530a6 100644 --- a/render/gles2/shaders/common.frag +++ b/render/gles2/shaders/common.frag @@ -4,7 +4,11 @@ #define SOURCE_TEXTURE_RGBX 3 #define SOURCE_TEXTURE_EXTERNAL 4 -#if !defined(SOURCE) +/* enum wlr_gles2_color_transform */ +#define COLOR_TRANSFORM_IDENTITY 0 +#define COLOR_TRANSFORM_LUT_3D 1 + +#if !defined(SOURCE) || !defined(COLOR_TRANSFORM) #error "Missing shader preamble" #endif @@ -12,6 +16,10 @@ #extension GL_OES_EGL_image_external : require #endif +#if COLOR_TRANSFORM == COLOR_TRANSFORM_3DLUT +#extension GL_OES_texture_3D : require +#endif + precision mediump float; varying vec2 v_texcoord; @@ -30,6 +38,12 @@ uniform float alpha; const float alpha = 1.0; #endif +#if COLOR_TRANSFORM == COLOR_TRANSFORM_LUT_3D +uniform mediump sampler3D lut_3d; +uniform float lut_3d_offset; +uniform float lut_3d_scale; +#endif + vec4 sample_texture() { #if SOURCE == SOURCE_TEXTURE_RGBA || SOURCE == SOURCE_TEXTURE_EXTERNAL return texture2D(tex, v_texcoord); @@ -40,6 +54,30 @@ vec4 sample_texture() { #endif } -void main() { - gl_FragColor = sample_texture() * alpha; +vec4 transform_color(vec4 color) { +#if COLOR_TRANSFORM == COLOR_TRANSFORM_IDENTITY + return color; +#elif COLOR_TRANSFORM == COLOR_TRANSFORM_LUT_3D + vec3 pos = lut_3d_offset + color * lut_3d_scale; + return texture3D(lut_3d, pos).rgb; +#endif +} + +void main() { + vec4 color = sample_texture() * alpha; + +#if COLOR_TRANSFORM != COLOR_TRANSFORM_IDENTITY + // Convert from pre-multiplied alpha to straight alpha + if (color.a == 0.0) + color.rgb = vec3(0.0, 0.0, 0.0); + else + color.rgb /= color.a; + + color = transform_color(color); + + // Convert from straight alpha to pre-multiplied alpha + color.rgb *= color.a; +#endif + + gl_FragColor = color; }