refactor: merged tex shaders

This commit is contained in:
Will McKinnon 2023-03-18 01:03:02 -04:00
parent f1e3fe92ce
commit 1a10c61165
7 changed files with 113 additions and 99 deletions

View file

@ -7,6 +7,13 @@
enum corner_location { ALL, TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, NONE };
enum fx_gles2_shader_source {
WLR_GLES2_SHADER_SOURCE_TEXTURE_RGBA = 1,
WLR_GLES2_SHADER_SOURCE_TEXTURE_RGBX = 2,
WLR_GLES2_SHADER_SOURCE_TEXTURE_EXTERNAL = 3,
WLR_GLES2_SHADER_SOURCE_NOT_TEXTURE = 4,
};
struct decoration_data {
float alpha;
float saturation;

View file

@ -25,9 +25,8 @@
#include "quad_round_tr_frag_src.h"
#include "corner_frag_src.h"
#include "box_shadow_frag_src.h"
#include "tex_rgba_frag_src.h"
#include "tex_rgbx_frag_src.h"
#include "tex_external_frag_src.h"
//#include "tex_frag_src.h"
#include "tex_decorated_frag_src.h"
static const GLfloat verts[] = {
1, 0, // top right
@ -101,9 +100,9 @@ static void matrix_projection(float mat[static 9], int width, int height,
mat[8] = 1.0f;
}
static GLuint compile_shader(GLuint type, const GLchar *src) {
static GLuint compile_shader(GLuint type, const GLchar **srcs, size_t srcs_len) {
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &src, NULL);
glShaderSource(shader, srcs_len, srcs, NULL);
glCompileShader(shader);
GLint ok;
@ -117,13 +116,24 @@ static GLuint compile_shader(GLuint type, const GLchar *src) {
return shader;
}
static GLuint link_program(const GLchar *vert_src, const GLchar *frag_src) {
GLuint vert = compile_shader(GL_VERTEX_SHADER, vert_src);
static GLuint link_program(const GLchar *frag_src, enum fx_gles2_shader_source source) {
const GLchar *vert_src = common_vert_src;
GLuint vert = compile_shader(GL_VERTEX_SHADER, &vert_src, 1);
if (!vert) {
goto error;
}
GLuint frag = compile_shader(GL_FRAGMENT_SHADER, frag_src);
GLuint frag;
if (source != WLR_GLES2_SHADER_SOURCE_NOT_TEXTURE) {
static char frag_preamble[1024];
snprintf(frag_preamble, sizeof(frag_preamble),
"#define SOURCE %d\n", source);
const GLchar *frag_srcs[2] = { frag_preamble, frag_src };
frag = compile_shader(GL_FRAGMENT_SHADER, frag_srcs, 2);
} else {
frag = compile_shader(GL_FRAGMENT_SHADER, &frag_src, 1);
}
if (!frag) {
glDeleteShader(vert);
goto error;
@ -153,12 +163,16 @@ error:
return 0;
}
// initializes a provided fragment shader and returns false if unsuccessful
bool init_frag_shader(struct gles2_tex_shader *shader, GLuint prog) {
shader->program = prog;
static bool link_tex_program(struct fx_renderer *renderer,
struct gles2_tex_shader *shader, enum fx_gles2_shader_source source) {
GLuint prog;
const GLchar *frag_src = tex_decorated_frag_src;
shader->program = prog = link_program(frag_src, source);
if (!shader->program) {
return false;
}
shader->proj = glGetUniformLocation(prog, "proj");
shader->tex = glGetUniformLocation(prog, "tex");
shader->alpha = glGetUniformLocation(prog, "alpha");
@ -171,6 +185,7 @@ bool init_frag_shader(struct gles2_tex_shader *shader, GLuint prog) {
shader->radius = glGetUniformLocation(prog, "radius");
shader->saturation = glGetUniformLocation(prog, "saturation");
shader->has_titlebar = glGetUniformLocation(prog, "has_titlebar");
return true;
}
@ -256,7 +271,7 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) {
GLuint prog;
// quad fragment shader
prog = link_program(common_vert_src, quad_frag_src);
prog = link_program(quad_frag_src, WLR_GLES2_SHADER_SOURCE_NOT_TEXTURE);
renderer->shaders.quad.program = prog;
if (!renderer->shaders.quad.program) {
goto error;
@ -266,21 +281,21 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) {
renderer->shaders.quad.pos_attrib = glGetAttribLocation(prog, "pos");
// rounded quad fragment shaders
prog = link_program(common_vert_src, quad_round_frag_src);
prog = link_program(quad_round_frag_src, WLR_GLES2_SHADER_SOURCE_NOT_TEXTURE);
if (!init_rounded_quad_shader(&renderer->shaders.rounded_quad, prog)) {
goto error;
}
prog = link_program(common_vert_src, quad_round_tl_frag_src);
prog = link_program(quad_round_tl_frag_src, WLR_GLES2_SHADER_SOURCE_NOT_TEXTURE);
if (!init_rounded_quad_shader(&renderer->shaders.rounded_tl_quad, prog)) {
goto error;
}
prog = link_program(common_vert_src, quad_round_tr_frag_src);
prog = link_program(quad_round_tr_frag_src, WLR_GLES2_SHADER_SOURCE_NOT_TEXTURE);
if (!init_rounded_quad_shader(&renderer->shaders.rounded_tr_quad, prog)) {
goto error;
}
// Border corner shader
prog = link_program(common_vert_src, corner_frag_src);
prog = link_program(corner_frag_src, WLR_GLES2_SHADER_SOURCE_NOT_TEXTURE);
renderer->shaders.corner.program = prog;
if (!renderer->shaders.corner.program) {
goto error;
@ -298,7 +313,7 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) {
renderer->shaders.corner.half_thickness = glGetUniformLocation(prog, "half_thickness");
// box shadow shader
prog = link_program(common_vert_src, box_shadow_frag_src);
prog = link_program(box_shadow_frag_src, WLR_GLES2_SHADER_SOURCE_NOT_TEXTURE);
renderer->shaders.box_shadow.program = prog;
if (!renderer->shaders.box_shadow.program) {
goto error;
@ -312,19 +327,20 @@ struct fx_renderer *fx_renderer_create(struct wlr_egl *egl) {
renderer->shaders.box_shadow.corner_radius = glGetUniformLocation(prog, "corner_radius");
// fragment shaders
prog = link_program(common_vert_src, tex_rgba_frag_src);
if (!init_frag_shader(&renderer->shaders.tex_rgba, prog)) {
if (!link_tex_program(renderer, &renderer->shaders.tex_rgba,
WLR_GLES2_SHADER_SOURCE_TEXTURE_RGBA)) {
goto error;
}
prog = link_program(common_vert_src, tex_rgbx_frag_src);
if (!init_frag_shader(&renderer->shaders.tex_rgbx, prog)) {
if (!link_tex_program(renderer, &renderer->shaders.tex_rgbx,
WLR_GLES2_SHADER_SOURCE_TEXTURE_RGBX)) {
goto error;
}
prog = link_program(common_vert_src, tex_external_frag_src);
if (!init_frag_shader(&renderer->shaders.tex_ext, prog)) {
if (!link_tex_program(renderer, &renderer->shaders.tex_ext,
WLR_GLES2_SHADER_SOURCE_TEXTURE_EXTERNAL)) {
goto error;
}
if (!eglMakeCurrent(wlr_egl_get_display(renderer->egl),
EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
sway_log(SWAY_ERROR, "GLES2 RENDERER: Could not unset current EGL");

View file

@ -8,9 +8,7 @@ shaders = [
'quad_round_tr.frag',
'corner.frag',
'box_shadow.frag',
'tex_rgba.frag',
'tex_rgbx.frag',
'tex_external.frag',
'tex_decorated.frag',
]
foreach name : shaders

View file

@ -0,0 +1,36 @@
/* enum wlr_gles2_shader_source */
#define SOURCE_TEXTURE_RGBA 1
#define SOURCE_TEXTURE_RGBX 2
#define SOURCE_TEXTURE_EXTERNAL 3
#if !defined(SOURCE)
#error "Missing shader preamble"
#endif
#if SOURCE == SOURCE_TEXTURE_EXTERNAL
#extension GL_OES_EGL_image_external : require
#endif
precision mediump float;
varying vec2 v_texcoord;
#if SOURCE == SOURCE_TEXTURE_EXTERNAL
uniform samplerExternalOES tex;
#elif SOURCE == SOURCE_TEXTURE_RGBA || SOURCE == SOURCE_TEXTURE_RGBX
uniform sampler2D tex;
#endif
uniform float alpha;
vec4 sample_texture() {
#if SOURCE == SOURCE_TEXTURE_RGBA || SOURCE == SOURCE_TEXTURE_EXTERNAL
return texture2D(tex, v_texcoord);
#elif SOURCE == SOURCE_TEXTURE_RGBX
return vec4(texture2D(tex, v_texcoord).rgb, 1.0);
#endif
}
void main() {
gl_FragColor = sample_texture() * alpha;
}

View file

@ -1,19 +1,47 @@
/* enum wlr_gles2_shader_source */
#define SOURCE_TEXTURE_RGBA 1
#define SOURCE_TEXTURE_RGBX 2
#define SOURCE_TEXTURE_EXTERNAL 3
#if !defined(SOURCE)
#error "Missing shader preamble"
#endif
#if SOURCE == SOURCE_TEXTURE_EXTERNAL
#extension GL_OES_EGL_image_external : require
#endif
precision mediump float;
varying vec2 v_texcoord;
#if SOURCE == SOURCE_TEXTURE_EXTERNAL
uniform samplerExternalOES tex;
#elif SOURCE == SOURCE_TEXTURE_RGBA || SOURCE == SOURCE_TEXTURE_RGBX
uniform sampler2D tex;
#endif
uniform float alpha;
uniform float dim;
uniform vec4 dim_color;
uniform vec2 size;
uniform vec2 position;
uniform float radius;
uniform bool has_titlebar;
uniform float saturation;
const vec3 saturation_weight = vec3(0.2125, 0.7154, 0.0721);
vec4 sample_texture() {
#if SOURCE == SOURCE_TEXTURE_RGBA || SOURCE == SOURCE_TEXTURE_EXTERNAL
return texture2D(tex, v_texcoord);
#elif SOURCE == SOURCE_TEXTURE_RGBX
return vec4(texture2D(tex, v_texcoord).rgb, 1.0);
#endif
}
void main() {
vec4 color = texture2D(tex, v_texcoord);
vec4 color = sample_texture();
// Saturation
if (saturation != 1.0) {
vec4 pixColor = texture2D(tex, v_texcoord);

View file

@ -1,37 +0,0 @@
#extension GL_OES_EGL_image_external : require
precision mediump float;
varying vec2 v_texcoord;
uniform samplerExternalOES texture0;
uniform float alpha;
uniform float dim;
uniform vec4 dim_color;
uniform vec2 size;
uniform vec2 position;
uniform float radius;
uniform bool has_titlebar;
uniform float saturation;
const vec3 saturation_weight = vec3(0.2125, 0.7154, 0.0721);
void main() {
vec4 color = texture2D(texture0, v_texcoord);
// Saturation
if (saturation != 1.0) {
vec4 pixColor = texture2D(texture0, v_texcoord);
vec3 irgb = pixColor.rgb;
vec3 target = vec3(dot(irgb, saturation_weight));
color = vec4(mix(target, irgb, saturation), pixColor.a);
}
// Dimming
gl_FragColor = mix(color, dim_color, dim) * alpha;
if (!has_titlebar || gl_FragCoord.y - position.y > radius) {
vec2 corner_distance = min(gl_FragCoord.xy - position, size + position - gl_FragCoord.xy);
if (max(corner_distance.x, corner_distance.y) < radius) {
float d = radius - distance(corner_distance, vec2(radius));
float smooth = smoothstep(-1.0f, 0.5f, d);
gl_FragColor = mix(vec4(0), gl_FragColor, smooth);
}
}
}

View file

@ -1,34 +0,0 @@
precision mediump float;
varying vec2 v_texcoord;
uniform sampler2D tex;
uniform float alpha;
uniform float dim;
uniform vec4 dim_color;
uniform vec2 size;
uniform vec2 position;
uniform float radius;
uniform bool has_titlebar;
uniform float saturation;
const vec3 saturation_weight = vec3(0.2125, 0.7154, 0.0721);
void main() {
vec4 color = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
// Saturation
if (saturation != 1.0) {
vec3 irgb = texture2D(tex, v_texcoord).rgb;
vec3 target = vec3(dot(irgb, saturation_weight));
color = vec4(mix(target, irgb, saturation), 1.0);
}
// Dimming
gl_FragColor = mix(color, dim_color, dim) * alpha;
if (!has_titlebar || gl_FragCoord.y - position.y > radius) {
vec2 corner_distance = min(gl_FragCoord.xy - position, size + position - gl_FragCoord.xy);
if (max(corner_distance.x, corner_distance.y) < radius) {
float d = radius - distance(corner_distance, vec2(radius));
float smooth = smoothstep(-1.0f, 0.5f, d);
gl_FragColor = mix(vec4(0), gl_FragColor, smooth);
}
}
}