git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

scenefx/render/fx_renderer/shaders.c (17.5K)

  1 #include <EGL/egl.h>
  2 #include <stdio.h>
  3 #include <stdlib.h>
  4 #include <wlr/util/log.h>
  5 #include <scenefx/types/fx/clipped_region.h>
  6 #include <scenefx/render/fx_renderer/fx_renderer.h>
  7 
  8 #include "render/fx_renderer/shaders.h"
  9 
 10 // shaders
 11 #include "GLES2/gl2.h"
 12 #include "common_vert_src.h"
 13 #include "gradient_frag_src.h"
 14 #include "corner_alpha_frag_src.h"
 15 #include "quad_frag_src.h"
 16 #include "quad_grad_frag_src.h"
 17 #include "quad_round_frag_src.h"
 18 #include "quad_grad_round_frag_src.h"
 19 #include "tex_frag_src.h"
 20 #include "box_shadow_frag_src.h"
 21 #include "bevel_frag_src.h"
 22 #include "frame_frag_src.h"
 23 #include "droplet_frag_src.h"
 24 #include "blur1_frag_src.h"
 25 #include "blur2_frag_src.h"
 26 #include "blur_effects_frag_src.h"
 27 
 28 GLuint compile_shader(GLuint type, const GLchar *src) {
 29 	GLuint shader = glCreateShader(type);
 30 	glShaderSource(shader, 1, &src, NULL);
 31 	glCompileShader(shader);
 32 
 33 	GLint ok;
 34 	glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
 35 	if (ok == GL_FALSE) {
 36 		wlr_log(WLR_ERROR, "Failed to compile shader");
 37 		glDeleteShader(shader);
 38 		shader = 0;
 39 	}
 40 
 41 	return shader;
 42 }
 43 
 44 GLuint link_program(const GLchar *frag_src) {
 45 	GLuint vert = compile_shader(GL_VERTEX_SHADER, common_vert_src);
 46 	if (!vert) {
 47 		goto error;
 48 	}
 49 
 50 	GLuint frag = compile_shader(GL_FRAGMENT_SHADER, frag_src);
 51 	if (!frag) {
 52 		glDeleteShader(vert);
 53 		goto error;
 54 	}
 55 
 56 	GLuint prog = glCreateProgram();
 57 	glAttachShader(prog, vert);
 58 	glAttachShader(prog, frag);
 59 	glLinkProgram(prog);
 60 
 61 	glDetachShader(prog, vert);
 62 	glDetachShader(prog, frag);
 63 	glDeleteShader(vert);
 64 	glDeleteShader(frag);
 65 
 66 	GLint ok;
 67 	glGetProgramiv(prog, GL_LINK_STATUS, &ok);
 68 	if (ok == GL_FALSE) {
 69 		wlr_log(WLR_ERROR, "Failed to link shader");
 70 		glDeleteProgram(prog);
 71 		goto error;
 72 	}
 73 
 74 	return prog;
 75 
 76 error:
 77 	return 0;
 78 }
 79 
 80 
 81 bool check_gl_ext(const char *exts, const char *ext) {
 82 	size_t extlen = strlen(ext);
 83 	const char *end = exts + strlen(exts);
 84 
 85 	while (exts < end) {
 86 		if (exts[0] == ' ') {
 87 			exts++;
 88 			continue;
 89 		}
 90 		size_t n = strcspn(exts, " ");
 91 		if (n == extlen && strncmp(ext, exts, n) == 0) {
 92 			return true;
 93 		}
 94 		exts += n;
 95 	}
 96 	return false;
 97 }
 98 
 99 void load_gl_proc(void *proc_ptr, const char *name) {
100 	void *proc = (void *)eglGetProcAddress(name);
101 	if (proc == NULL) {
102 		wlr_log(WLR_ERROR, "FX RENDERER: eglGetProcAddress(%s) failed", name);
103 		abort();
104 	}
105 	*(void **)proc_ptr = proc;
106 }
107 
108 // Renderer-global corner-shape exponent (circular arcs by default); set once
109 // from the compositor's config via fx_renderer_set_corner_shape.
110 static float global_corner_shape = 2.0f;
111 
112 void fx_renderer_set_corner_shape(float shape) {
113 	global_corner_shape = shape;
114 }
115 
116 float fx_corner_shape(void) {
117 	return global_corner_shape;
118 }
119 
120 void uniform_corner_radii_set(const struct shader_corner_radii *uniform,
121 		const struct fx_corner_fradii *corners) {
122 	/* The corner-SDF shaders flip Y (relative_pos.y = size.y - y) on top of
123 	 * an already top-down gl_FragCoord in this renderer's FBO setup, so a
124 	 * radius bound to the shader's "top" slots renders at the SCREEN bottom
125 	 * and vice versa. Every symmetric consumer (grid cells, window
126 	 * backgrounds — equal radii on all four corners) masked this for years;
127 	 * the border corner pieces are the first per-corner-asymmetric rects
128 	 * and rendered vertically mirrored (arc at the wrong end of the L, the
129 	 * clip hole's rounding on the wrong corner). Swap the vertical pairs at
130 	 * upload so scene-space corners land where they say. */
131 	glUniform1f(uniform->top_left, corners->bottom_left);
132 	glUniform1f(uniform->top_right, corners->bottom_right);
133 	glUniform1f(uniform->bottom_left, corners->top_left);
134 	glUniform1f(uniform->bottom_right, corners->top_right);
135 	glUniform1f(uniform->shape, global_corner_shape);
136 }
137 // Shaders
138 
139 bool link_quad_program(struct quad_shader *shader, bool clip) {
140 	GLchar quad_src_part[2048];
141 	GLchar quad_src[8192];
142 	snprintf(quad_src_part, sizeof(quad_src_part),
143 		quad_frag_src, clip);
144 	snprintf(quad_src, sizeof(quad_src),
145 		"%s\n%s\n", quad_src_part, clip ? corner_alpha_frag_src : "");
146 
147 	GLuint prog;
148 	shader->program = prog = link_program(quad_src);
149 	if (!shader->program) {
150 		return false;
151 	}
152 
153 	shader->proj = glGetUniformLocation(prog, "proj");
154 	shader->color = glGetUniformLocation(prog, "color");
155 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
156 
157 	if (!clip) {
158 		return true;
159 	}
160 	shader->effects.clip_size = glGetUniformLocation(prog, "clip_size");
161 	shader->effects.clip_position = glGetUniformLocation(prog, "clip_position");
162 	shader->effects.clip_radius.top_left = glGetUniformLocation(prog, "clip_radius_top_left");
163 	shader->effects.clip_radius.top_right = glGetUniformLocation(prog, "clip_radius_top_right");
164 	shader->effects.clip_radius.bottom_left = glGetUniformLocation(prog, "clip_radius_bottom_left");
165 	shader->effects.clip_radius.bottom_right = glGetUniformLocation(prog, "clip_radius_bottom_right");
166 	shader->effects.clip_radius.shape = glGetUniformLocation(prog, "corner_shape");
167 
168 	return true;
169 }
170 
171 bool link_quad_grad_program(struct quad_grad_shader *shader, int max_len) {
172 	GLchar quad_src_part[2048];
173 	GLchar quad_src[4096];
174 	snprintf(quad_src_part, sizeof(quad_src_part),
175 		quad_grad_frag_src, max_len);
176 	snprintf(quad_src, sizeof(quad_src),
177 		"%s\n%s", quad_src_part, gradient_frag_src);
178 
179 	GLuint prog;
180 	shader->program = prog = link_program(quad_src);
181 	if (!shader->program) {
182 		return false;
183 	}
184 
185 	shader->proj = glGetUniformLocation(prog, "proj");
186 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
187 	shader->size = glGetUniformLocation(prog, "size");
188 	shader->colors = glGetUniformLocation(prog, "colors");
189 	shader->degree = glGetUniformLocation(prog, "degree");
190 	shader->grad_box = glGetUniformLocation(prog, "grad_box");
191 	shader->linear = glGetUniformLocation(prog, "linear");
192 	shader->origin = glGetUniformLocation(prog, "origin");
193 	shader->count = glGetUniformLocation(prog, "count");
194 	shader->blend = glGetUniformLocation(prog, "blend");
195 
196 	shader->max_len = max_len;
197 
198 	return true;
199 }
200 
201 bool link_quad_round_program(struct quad_round_shader *shader) {
202 	GLchar quad_src[8192];
203 	snprintf(quad_src, sizeof(quad_src), "%s\n%s", quad_round_frag_src,
204 		corner_alpha_frag_src);
205 
206 	GLuint prog;
207 	shader->program = prog = link_program(quad_src);
208 	if (!shader->program) {
209 		return false;
210 	}
211 
212 	shader->proj = glGetUniformLocation(prog, "proj");
213 	shader->color = glGetUniformLocation(prog, "color");
214 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
215 	shader->size = glGetUniformLocation(prog, "size");
216 	shader->position = glGetUniformLocation(prog, "position");
217 	shader->radius.top_left = glGetUniformLocation(prog, "radius_top_left");
218 	shader->radius.top_right = glGetUniformLocation(prog, "radius_top_right");
219 	shader->radius.bottom_left = glGetUniformLocation(prog, "radius_bottom_left");
220 	shader->radius.bottom_right = glGetUniformLocation(prog, "radius_bottom_right");
221 	shader->radius.shape = glGetUniformLocation(prog, "corner_shape");
222 
223 	shader->clip_size = glGetUniformLocation(prog, "clip_size");
224 	shader->clip_position = glGetUniformLocation(prog, "clip_position");
225 	shader->clip_radius.top_left = glGetUniformLocation(prog, "clip_radius_top_left");
226 	shader->clip_radius.top_right = glGetUniformLocation(prog, "clip_radius_top_right");
227 	shader->clip_radius.bottom_left = glGetUniformLocation(prog, "clip_radius_bottom_left");
228 	shader->clip_radius.bottom_right = glGetUniformLocation(prog, "clip_radius_bottom_right");
229 	shader->clip_radius.shape = glGetUniformLocation(prog, "corner_shape");
230 	shader->fade_inset = glGetUniformLocation(prog, "fade_inset");
231 	shader->fade_mode = glGetUniformLocation(prog, "fade_mode");
232 
233 	return true;
234 }
235 
236 bool link_quad_grad_round_program(struct quad_grad_round_shader *shader, int max_len) {
237 	GLchar quad_src_part[2048];
238 	GLchar quad_src[8192];
239 	snprintf(quad_src_part, sizeof(quad_src_part),
240 		quad_grad_round_frag_src, max_len);
241 	snprintf(quad_src, sizeof(quad_src),
242 		"%s\n%s\n%s", quad_src_part, gradient_frag_src, corner_alpha_frag_src);
243 
244 	GLuint prog;
245 	shader->program = prog = link_program(quad_src);
246 	if (!shader->program) {
247 		return false;
248 	}
249 
250 	shader->proj = glGetUniformLocation(prog, "proj");
251 	shader->color = glGetUniformLocation(prog, "color");
252 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
253 	shader->size = glGetUniformLocation(prog, "size");
254 	shader->position = glGetUniformLocation(prog, "position");
255 	shader->radius.top_left = glGetUniformLocation(prog, "radius_top_left");
256 	shader->radius.top_right = glGetUniformLocation(prog, "radius_top_right");
257 	shader->radius.bottom_left = glGetUniformLocation(prog, "radius_bottom_left");
258 	shader->radius.bottom_right = glGetUniformLocation(prog, "radius_bottom_right");
259 	shader->radius.shape = glGetUniformLocation(prog, "corner_shape");
260 
261 	shader->grad_size = glGetUniformLocation(prog, "grad_size");
262 	shader->colors = glGetUniformLocation(prog, "colors");
263 	shader->degree = glGetUniformLocation(prog, "degree");
264 	shader->grad_box = glGetUniformLocation(prog, "grad_box");
265 	shader->linear = glGetUniformLocation(prog, "linear");
266 	shader->origin = glGetUniformLocation(prog, "origin");
267 	shader->count = glGetUniformLocation(prog, "count");
268 	shader->blend = glGetUniformLocation(prog, "blend");
269 
270 	shader->max_len = max_len;
271 
272 	return true;
273 }
274 
275 bool link_tex_program(struct tex_shader *shader, enum fx_tex_shader_source source,
276 		bool effects) {
277 	GLchar frag_src_part[4096];
278 	GLchar frag_src[8192];
279 	snprintf(frag_src_part, sizeof(frag_src_part),
280 		tex_frag_src, source, effects);
281 	snprintf(frag_src, sizeof(frag_src),
282 		"%s\n%s\n", frag_src_part, effects ? corner_alpha_frag_src : "");
283 
284 	GLuint prog;
285 	shader->program = prog = link_program(frag_src);
286 	if (!shader->program) {
287 		return false;
288 	}
289 
290 	shader->proj = glGetUniformLocation(prog, "proj");
291 	shader->tex = glGetUniformLocation(prog, "tex");
292 	shader->alpha = glGetUniformLocation(prog, "alpha");
293 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
294 	shader->tex_proj = glGetUniformLocation(prog, "tex_proj");
295 
296 	shader->discard_transparent = glGetUniformLocation(prog, "discard_transparent");
297 
298 	if (!effects) {
299 		return true;
300 	}
301 	shader->effects.size = glGetUniformLocation(prog, "size");
302 	shader->effects.position = glGetUniformLocation(prog, "position");
303 	shader->effects.radius.top_left = glGetUniformLocation(prog, "radius_top_left");
304 	shader->effects.radius.top_right = glGetUniformLocation(prog, "radius_top_right");
305 	shader->effects.radius.bottom_left = glGetUniformLocation(prog, "radius_bottom_left");
306 	shader->effects.radius.bottom_right = glGetUniformLocation(prog, "radius_bottom_right");
307 	shader->effects.radius.shape = glGetUniformLocation(prog, "corner_shape");
308 
309 	shader->effects.clip_size = glGetUniformLocation(prog, "clip_size");
310 	shader->effects.clip_position = glGetUniformLocation(prog, "clip_position");
311 	shader->effects.clip_radius.top_left = glGetUniformLocation(prog, "clip_radius_top_left");
312 	shader->effects.clip_radius.top_right = glGetUniformLocation(prog, "clip_radius_top_right");
313 	shader->effects.clip_radius.bottom_left = glGetUniformLocation(prog, "clip_radius_bottom_left");
314 	shader->effects.clip_radius.bottom_right = glGetUniformLocation(prog, "clip_radius_bottom_right");
315 	shader->effects.clip_radius.shape = glGetUniformLocation(prog, "corner_shape");
316 
317 	return true;
318 }
319 
320 bool link_box_shadow_program(struct box_shadow_shader *shader) {
321 	GLchar shadow_src[8192];
322 	snprintf(shadow_src, sizeof(shadow_src), "%s\n%s", box_shadow_frag_src,
323 		corner_alpha_frag_src);
324 
325 	GLuint prog;
326 	shader->program = prog = link_program(shadow_src);
327 	if (!shader->program) {
328 		return false;
329 	}
330 	shader->proj = glGetUniformLocation(prog, "proj");
331 	shader->color = glGetUniformLocation(prog, "color");
332 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
333 	shader->position = glGetUniformLocation(prog, "position");
334 	shader->size = glGetUniformLocation(prog, "size");
335 	shader->blur_sigma = glGetUniformLocation(prog, "blur_sigma");
336 	shader->corner_radius = glGetUniformLocation(prog, "corner_radius");
337 	shader->clip_position = glGetUniformLocation(prog, "clip_position");
338 	shader->clip_size = glGetUniformLocation(prog, "clip_size");
339 	shader->clip_radius.top_left = glGetUniformLocation(prog, "clip_radius_top_left");
340 	shader->clip_radius.top_right = glGetUniformLocation(prog, "clip_radius_top_right");
341 	shader->clip_radius.bottom_left = glGetUniformLocation(prog, "clip_radius_bottom_left");
342 	shader->clip_radius.bottom_right = glGetUniformLocation(prog, "clip_radius_bottom_right");
343 	shader->clip_radius.shape = glGetUniformLocation(prog, "corner_shape");
344 
345 	return true;
346 }
347 
348 bool link_bevel_program(struct bevel_shader *shader) {
349 	// Same pairing as link_box_shadow_program: the rim's SDF is the shared
350 	// corner routine, so the shape follows corner_shape like every other cut.
351 	GLchar bevel_src[16384];
352 	snprintf(bevel_src, sizeof(bevel_src), "%s\n%s", bevel_frag_src,
353 		corner_alpha_frag_src);
354 
355 	GLuint prog;
356 	shader->program = prog = link_program(bevel_src);
357 	if (!shader->program) {
358 		return false;
359 	}
360 	shader->proj = glGetUniformLocation(prog, "proj");
361 	shader->color = glGetUniformLocation(prog, "color");
362 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
363 	shader->position = glGetUniformLocation(prog, "position");
364 	shader->size = glGetUniformLocation(prog, "size");
365 	shader->corner_radius = glGetUniformLocation(prog, "corner_radius");
366 	shader->corner_shape = glGetUniformLocation(prog, "corner_shape");
367 	shader->thickness = glGetUniformLocation(prog, "thickness");
368 	shader->light_dir = glGetUniformLocation(prog, "light_dir");
369 	shader->light_intensity = glGetUniformLocation(prog, "light_intensity");
370 	shader->shade_intensity = glGetUniformLocation(prog, "shade_intensity");
371 	shader->focus = glGetUniformLocation(prog, "focus");
372 	shader->focus_color = glGetUniformLocation(prog, "focus_color");
373 	shader->focus_sharpness = glGetUniformLocation(prog, "focus_sharpness");
374 	shader->shoulder = glGetUniformLocation(prog, "shoulder");
375 
376 	return true;
377 }
378 
379 bool link_frame_program(struct frame_shader *shader) {
380 	// Paired with the shared corner routine, like bevel: the ring traces the
381 	// same superellipse every other corner cut does.
382 	GLchar frame_src[16384];
383 	snprintf(frame_src, sizeof(frame_src), "%s\n%s", frame_frag_src,
384 		corner_alpha_frag_src);
385 
386 	GLuint prog;
387 	shader->program = prog = link_program(frame_src);
388 	if (!shader->program) {
389 		return false;
390 	}
391 	shader->proj = glGetUniformLocation(prog, "proj");
392 	shader->color = glGetUniformLocation(prog, "color");
393 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
394 	shader->position = glGetUniformLocation(prog, "position");
395 	shader->size = glGetUniformLocation(prog, "size");
396 	shader->corner_radius = glGetUniformLocation(prog, "corner_radius");
397 	shader->corner_shape = glGetUniformLocation(prog, "corner_shape");
398 	shader->band = glGetUniformLocation(prog, "band");
399 	shader->band_min = glGetUniformLocation(prog, "band_min");
400 	shader->corner_len = glGetUniformLocation(prog, "corner_len");
401 	shader->gap = glGetUniformLocation(prog, "gap");
402 	shader->hovered = glGetUniformLocation(prog, "hovered");
403 	shader->hover_color = glGetUniformLocation(prog, "hover_color");
404 	shader->swell_curve = glGetUniformLocation(prog, "swell_curve");
405 	shader->bulge = glGetUniformLocation(prog, "bulge");
406 	shader->exclusion = glGetUniformLocation(prog, "exclusion");
407 
408 	return true;
409 }
410 
411 bool link_droplet_program(struct droplet_shader *shader) {
412 	GLuint prog;
413 	shader->program = prog = link_program(droplet_frag_src);
414 	if (!shader->program) {
415 		return false;
416 	}
417 	shader->proj = glGetUniformLocation(prog, "proj");
418 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
419 	shader->tex = glGetUniformLocation(prog, "tex");
420 	shader->tex_size = glGetUniformLocation(prog, "tex_size");
421 	shader->position = glGetUniformLocation(prog, "position");
422 	shader->size = glGetUniformLocation(prog, "size");
423 	shader->attach_r = glGetUniformLocation(prog, "attach_r");
424 	shader->sheet_r = glGetUniformLocation(prog, "sheet_r");
425 	shader->bow_rise = glGetUniformLocation(prog, "bow_rise");
426 	shader->blend_k = glGetUniformLocation(prog, "blend_k");
427 	shader->curve = glGetUniformLocation(prog, "curve");
428 	shader->band_px = glGetUniformLocation(prog, "band_px");
429 	shader->refr = glGetUniformLocation(prog, "refr");
430 	shader->ghost = glGetUniformLocation(prog, "ghost");
431 
432 	return true;
433 }
434 
435 bool link_blur1_program(struct blur_shader *shader) {
436 	GLuint prog;
437 	shader->program = prog = link_program(blur1_frag_src);
438 	if (!shader->program) {
439 		return false;
440 	}
441 	shader->proj = glGetUniformLocation(prog, "proj");
442 	shader->tex = glGetUniformLocation(prog, "tex");
443 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
444 	shader->tex_proj = glGetUniformLocation(prog, "tex_proj");
445 	shader->radius = glGetUniformLocation(prog, "radius");
446 	shader->halfpixel = glGetUniformLocation(prog, "halfpixel");
447 
448 	return true;
449 }
450 
451 bool link_blur2_program(struct blur_shader *shader) {
452 	GLuint prog;
453 	shader->program = prog = link_program(blur2_frag_src);
454 	if (!shader->program) {
455 		return false;
456 	}
457 	shader->proj = glGetUniformLocation(prog, "proj");
458 	shader->tex = glGetUniformLocation(prog, "tex");
459 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
460 	shader->tex_proj = glGetUniformLocation(prog, "tex_proj");
461 	shader->radius = glGetUniformLocation(prog, "radius");
462 	shader->halfpixel = glGetUniformLocation(prog, "halfpixel");
463 
464 	return true;
465 }
466 
467 bool link_blur_effects_program(struct blur_effects_shader *shader) {
468 	GLuint prog;
469 	shader->program = prog = link_program(blur_effects_frag_src);
470 	if (!shader->program) {
471 		return false;
472 	}
473 	shader->proj = glGetUniformLocation(prog, "proj");
474 	shader->tex = glGetUniformLocation(prog, "tex");
475 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
476 	shader->tex_proj = glGetUniformLocation(prog, "tex_proj");
477 	shader->noise = glGetUniformLocation(prog, "noise");
478 	shader->brightness = glGetUniformLocation(prog, "brightness");
479 	shader->contrast = glGetUniformLocation(prog, "contrast");
480 	shader->saturation = glGetUniformLocation(prog, "saturation");
481 
482 	return true;
483 }