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

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

  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 	shader->compress_ceil = glGetUniformLocation(prog, "compress_ceil");
298 	shader->compress_knee = glGetUniformLocation(prog, "compress_knee");
299 	shader->compress_invert = glGetUniformLocation(prog, "compress_invert");
300 
301 	if (!effects) {
302 		return true;
303 	}
304 	shader->effects.size = glGetUniformLocation(prog, "size");
305 	shader->effects.position = glGetUniformLocation(prog, "position");
306 	shader->effects.radius.top_left = glGetUniformLocation(prog, "radius_top_left");
307 	shader->effects.radius.top_right = glGetUniformLocation(prog, "radius_top_right");
308 	shader->effects.radius.bottom_left = glGetUniformLocation(prog, "radius_bottom_left");
309 	shader->effects.radius.bottom_right = glGetUniformLocation(prog, "radius_bottom_right");
310 	shader->effects.radius.shape = glGetUniformLocation(prog, "corner_shape");
311 
312 	shader->effects.clip_size = glGetUniformLocation(prog, "clip_size");
313 	shader->effects.clip_position = glGetUniformLocation(prog, "clip_position");
314 	shader->effects.clip_radius.top_left = glGetUniformLocation(prog, "clip_radius_top_left");
315 	shader->effects.clip_radius.top_right = glGetUniformLocation(prog, "clip_radius_top_right");
316 	shader->effects.clip_radius.bottom_left = glGetUniformLocation(prog, "clip_radius_bottom_left");
317 	shader->effects.clip_radius.bottom_right = glGetUniformLocation(prog, "clip_radius_bottom_right");
318 	shader->effects.clip_radius.shape = glGetUniformLocation(prog, "corner_shape");
319 
320 	return true;
321 }
322 
323 bool link_box_shadow_program(struct box_shadow_shader *shader) {
324 	GLchar shadow_src[8192];
325 	snprintf(shadow_src, sizeof(shadow_src), "%s\n%s", box_shadow_frag_src,
326 		corner_alpha_frag_src);
327 
328 	GLuint prog;
329 	shader->program = prog = link_program(shadow_src);
330 	if (!shader->program) {
331 		return false;
332 	}
333 	shader->proj = glGetUniformLocation(prog, "proj");
334 	shader->color = glGetUniformLocation(prog, "color");
335 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
336 	shader->position = glGetUniformLocation(prog, "position");
337 	shader->size = glGetUniformLocation(prog, "size");
338 	shader->blur_sigma = glGetUniformLocation(prog, "blur_sigma");
339 	shader->corner_radius = glGetUniformLocation(prog, "corner_radius");
340 	shader->clip_position = glGetUniformLocation(prog, "clip_position");
341 	shader->clip_size = glGetUniformLocation(prog, "clip_size");
342 	shader->clip_radius.top_left = glGetUniformLocation(prog, "clip_radius_top_left");
343 	shader->clip_radius.top_right = glGetUniformLocation(prog, "clip_radius_top_right");
344 	shader->clip_radius.bottom_left = glGetUniformLocation(prog, "clip_radius_bottom_left");
345 	shader->clip_radius.bottom_right = glGetUniformLocation(prog, "clip_radius_bottom_right");
346 	shader->clip_radius.shape = glGetUniformLocation(prog, "corner_shape");
347 
348 	return true;
349 }
350 
351 bool link_bevel_program(struct bevel_shader *shader) {
352 	// Same pairing as link_box_shadow_program: the rim's SDF is the shared
353 	// corner routine, so the shape follows corner_shape like every other cut.
354 	GLchar bevel_src[16384];
355 	snprintf(bevel_src, sizeof(bevel_src), "%s\n%s", bevel_frag_src,
356 		corner_alpha_frag_src);
357 
358 	GLuint prog;
359 	shader->program = prog = link_program(bevel_src);
360 	if (!shader->program) {
361 		return false;
362 	}
363 	shader->proj = glGetUniformLocation(prog, "proj");
364 	shader->color = glGetUniformLocation(prog, "color");
365 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
366 	shader->position = glGetUniformLocation(prog, "position");
367 	shader->size = glGetUniformLocation(prog, "size");
368 	shader->corner_radius = glGetUniformLocation(prog, "corner_radius");
369 	shader->corner_shape = glGetUniformLocation(prog, "corner_shape");
370 	shader->thickness = glGetUniformLocation(prog, "thickness");
371 	shader->light_dir = glGetUniformLocation(prog, "light_dir");
372 	shader->light_intensity = glGetUniformLocation(prog, "light_intensity");
373 	shader->shade_intensity = glGetUniformLocation(prog, "shade_intensity");
374 	shader->focus = glGetUniformLocation(prog, "focus");
375 	shader->focus_color = glGetUniformLocation(prog, "focus_color");
376 	shader->focus_sharpness = glGetUniformLocation(prog, "focus_sharpness");
377 	shader->shoulder = glGetUniformLocation(prog, "shoulder");
378 
379 	return true;
380 }
381 
382 bool link_frame_program(struct frame_shader *shader) {
383 	// Paired with the shared corner routine, like bevel: the ring traces the
384 	// same superellipse every other corner cut does.
385 	GLchar frame_src[16384];
386 	snprintf(frame_src, sizeof(frame_src), "%s\n%s", frame_frag_src,
387 		corner_alpha_frag_src);
388 
389 	GLuint prog;
390 	shader->program = prog = link_program(frame_src);
391 	if (!shader->program) {
392 		return false;
393 	}
394 	shader->proj = glGetUniformLocation(prog, "proj");
395 	shader->color = glGetUniformLocation(prog, "color");
396 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
397 	shader->position = glGetUniformLocation(prog, "position");
398 	shader->size = glGetUniformLocation(prog, "size");
399 	shader->corner_radius = glGetUniformLocation(prog, "corner_radius");
400 	shader->corner_shape = glGetUniformLocation(prog, "corner_shape");
401 	shader->band = glGetUniformLocation(prog, "band");
402 	shader->band_min = glGetUniformLocation(prog, "band_min");
403 	shader->corner_len = glGetUniformLocation(prog, "corner_len");
404 	shader->gap = glGetUniformLocation(prog, "gap");
405 	shader->hovered = glGetUniformLocation(prog, "hovered");
406 	shader->hover_color = glGetUniformLocation(prog, "hover_color");
407 	shader->swell_curve = glGetUniformLocation(prog, "swell_curve");
408 	shader->bulge = glGetUniformLocation(prog, "bulge");
409 	shader->exclusion = glGetUniformLocation(prog, "exclusion");
410 	shader->buttons = glGetUniformLocation(prog, "buttons");
411 
412 	return true;
413 }
414 
415 bool link_droplet_program(struct droplet_shader *shader) {
416 	GLuint prog;
417 	shader->program = prog = link_program(droplet_frag_src);
418 	if (!shader->program) {
419 		return false;
420 	}
421 	shader->proj = glGetUniformLocation(prog, "proj");
422 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
423 	shader->tex = glGetUniformLocation(prog, "tex");
424 	shader->tex_size = glGetUniformLocation(prog, "tex_size");
425 	shader->position = glGetUniformLocation(prog, "position");
426 	shader->size = glGetUniformLocation(prog, "size");
427 	shader->attach_r = glGetUniformLocation(prog, "attach_r");
428 	shader->sheet_r = glGetUniformLocation(prog, "sheet_r");
429 	shader->bow_rise = glGetUniformLocation(prog, "bow_rise");
430 	shader->blend_k = glGetUniformLocation(prog, "blend_k");
431 	shader->curve = glGetUniformLocation(prog, "curve");
432 	shader->band_px = glGetUniformLocation(prog, "band_px");
433 	shader->refr = glGetUniformLocation(prog, "refr");
434 	shader->ghost = glGetUniformLocation(prog, "ghost");
435 	shader->compress_ceil = glGetUniformLocation(prog, "compress_ceil");
436 	shader->compress_knee = glGetUniformLocation(prog, "compress_knee");
437 	shader->compress_invert = glGetUniformLocation(prog, "compress_invert");
438 
439 	return true;
440 }
441 
442 bool link_blur1_program(struct blur_shader *shader) {
443 	GLuint prog;
444 	shader->program = prog = link_program(blur1_frag_src);
445 	if (!shader->program) {
446 		return false;
447 	}
448 	shader->proj = glGetUniformLocation(prog, "proj");
449 	shader->tex = glGetUniformLocation(prog, "tex");
450 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
451 	shader->tex_proj = glGetUniformLocation(prog, "tex_proj");
452 	shader->radius = glGetUniformLocation(prog, "radius");
453 	shader->halfpixel = glGetUniformLocation(prog, "halfpixel");
454 
455 	return true;
456 }
457 
458 bool link_blur2_program(struct blur_shader *shader) {
459 	GLuint prog;
460 	shader->program = prog = link_program(blur2_frag_src);
461 	if (!shader->program) {
462 		return false;
463 	}
464 	shader->proj = glGetUniformLocation(prog, "proj");
465 	shader->tex = glGetUniformLocation(prog, "tex");
466 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
467 	shader->tex_proj = glGetUniformLocation(prog, "tex_proj");
468 	shader->radius = glGetUniformLocation(prog, "radius");
469 	shader->halfpixel = glGetUniformLocation(prog, "halfpixel");
470 
471 	return true;
472 }
473 
474 bool link_blur_effects_program(struct blur_effects_shader *shader) {
475 	GLuint prog;
476 	shader->program = prog = link_program(blur_effects_frag_src);
477 	if (!shader->program) {
478 		return false;
479 	}
480 	shader->proj = glGetUniformLocation(prog, "proj");
481 	shader->tex = glGetUniformLocation(prog, "tex");
482 	shader->pos_attrib = glGetAttribLocation(prog, "pos");
483 	shader->tex_proj = glGetUniformLocation(prog, "tex_proj");
484 	shader->noise = glGetUniformLocation(prog, "noise");
485 	shader->brightness = glGetUniformLocation(prog, "brightness");
486 	shader->contrast = glGetUniformLocation(prog, "contrast");
487 	shader->saturation = glGetUniformLocation(prog, "saturation");
488 
489 	return true;
490 }