[4/6] gl-renderer: Add necessary shaders for color correction

Submitted by Niels Ole Salscheider on Oct. 13, 2014, 5:40 p.m.

Details

Message ID 1413222051-4637-5-git-send-email-niels_ole@salscheider-online.de
State Changes Requested
Headers show

Not browsing as part of any series.

Commit Message

Niels Ole Salscheider Oct. 13, 2014, 5:40 p.m.
This patch ignores the YUV variants for now.

Signed-off-by: Niels Ole Salscheider <niels_ole@salscheider-online.de>
---
 src/gl-renderer.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 102 insertions(+)

Patch hide | download patch | download mbox

diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index f7f29b3..470f98a 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -43,6 +43,7 @@  struct gl_shader {
 	GLuint vertex_shader, fragment_shader;
 	GLint proj_uniform;
 	GLint tex_uniforms[3];
+	GLint lut_uniform;
 	GLint alpha_uniform;
 	GLint color_uniform;
 	const char *vertex_source, *fragment_source;
@@ -127,6 +128,7 @@  struct gl_renderer {
 	struct wl_array vtxcnt;
 
 	PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
+	PFNGLTEXIMAGE3DOESPROC teximage3d;
 	PFNEGLCREATEIMAGEKHRPROC create_image;
 	PFNEGLDESTROYIMAGEKHRPROC destroy_image;
 
@@ -145,16 +147,22 @@  struct gl_renderer {
 
 	int has_egl_buffer_age;
 
+	int has_texture_3d;
+
 	int has_configless_context;
 
 	struct gl_shader texture_shader_rgba;
+	struct gl_shader texture_shader_rgba_lut;
 	struct gl_shader texture_shader_rgbx;
+	struct gl_shader texture_shader_rgbx_lut;
 	struct gl_shader texture_shader_egl_external;
+	struct gl_shader texture_shader_egl_external_lut;
 	struct gl_shader texture_shader_y_uv;
 	struct gl_shader texture_shader_y_u_v;
 	struct gl_shader texture_shader_y_xuxv;
 	struct gl_shader invert_color_shader;
 	struct gl_shader solid_shader;
+	struct gl_shader fb_shader;
 	struct gl_shader *current_shader;
 
 	struct wl_signal destroy_signal;
@@ -518,6 +526,8 @@  shader_uniforms(struct gl_shader *shader,
 
 	for (i = 0; i < gs->num_textures; i++)
 		glUniform1i(shader->tex_uniforms[i], i);
+
+	glUniform1i(shader->lut_uniform, i);
 }
 
 static void
@@ -1410,6 +1420,16 @@  static const char vertex_shader[] =
 	"  gl_FragColor.b = y + 2.01723214 * u;\n"			\
 	"  gl_FragColor.a = alpha;\n"
 
+#define FRAGMENT_LUT_ENABLE						\
+	"#extension GL_OES_texture_3D : enable\n"
+
+#define FRAGMENT_LUT_VARS						\
+	"uniform sampler3D lut;\n"
+
+#define FRAGMENT_LUT_APPLY						\
+	"  gl_FragColor.rgb = texture3D(lut,\n"				\
+	"    gl_FragColor.rgb / gl_FragColor.a).rgb * gl_FragColor.a;\n"
+
 static const char fragment_debug[] =
 	"  gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
 
@@ -1426,6 +1446,19 @@  static const char texture_fragment_shader_rgba[] =
 	"   gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
 	;
 
+static const char texture_fragment_shader_rgba_lut[] =
+	FRAGMENT_LUT_ENABLE
+	"precision mediump float;\n"
+	"varying vec2 v_texcoord;\n"
+	"uniform sampler2D tex;\n"
+	"uniform float alpha;\n"
+	FRAGMENT_LUT_VARS
+	"void main()\n"
+	"{\n"
+	"   gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
+	FRAGMENT_LUT_APPLY
+	;
+
 static const char texture_fragment_shader_rgbx[] =
 	"precision mediump float;\n"
 	"varying vec2 v_texcoord;\n"
@@ -1437,6 +1470,20 @@  static const char texture_fragment_shader_rgbx[] =
 	"   gl_FragColor.a = alpha;\n"
 	;
 
+static const char texture_fragment_shader_rgbx_lut[] =
+	FRAGMENT_LUT_ENABLE
+	"precision mediump float;\n"
+	"varying vec2 v_texcoord;\n"
+	"uniform sampler2D tex;\n"
+	"uniform float alpha;\n"
+	FRAGMENT_LUT_VARS
+	"void main()\n"
+	"{\n"
+	"   gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
+	"   gl_FragColor.a = alpha;\n"
+	FRAGMENT_LUT_APPLY
+	;
+
 static const char texture_fragment_shader_egl_external[] =
 	"#extension GL_OES_EGL_image_external : require\n"
 	"precision mediump float;\n"
@@ -1448,6 +1495,20 @@  static const char texture_fragment_shader_egl_external[] =
 	"   gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
 	;
 
+static const char texture_fragment_shader_egl_external_lut[] =
+	FRAGMENT_LUT_ENABLE
+	"#extension GL_OES_EGL_image_external : require\n"
+	"precision mediump float;\n"
+	"varying vec2 v_texcoord;\n"
+	"uniform samplerExternalOES tex;\n"
+	"uniform float alpha;\n"
+	FRAGMENT_LUT_VARS
+	"void main()\n"
+	"{\n"
+	"   gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
+	FRAGMENT_LUT_APPLY
+	;
+
 static const char texture_fragment_shader_y_uv[] =
 	"precision mediump float;\n"
 	"uniform sampler2D tex;\n"
@@ -1497,6 +1558,18 @@  static const char solid_fragment_shader[] =
 	"   gl_FragColor = alpha * color\n;"
 	;
 
+static const char fb_fragment_shader[] =
+	FRAGMENT_LUT_ENABLE
+	"precision mediump float;\n"
+	"uniform sampler2D tex;\n"
+	"varying vec2 v_texcoord;\n"
+	FRAGMENT_LUT_VARS
+	"void main()\n"
+	"{\n"
+	"   gl_FragColor = texture2D(tex, v_texcoord);\n"
+	FRAGMENT_LUT_APPLY
+	;
+
 static int
 compile_shader(GLenum type, int count, const char **sources)
 {
@@ -1561,6 +1634,7 @@  shader_init(struct gl_shader *shader, struct gl_renderer *renderer,
 	shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex");
 	shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1");
 	shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2");
+	shader->lut_uniform = glGetUniformLocation(shader->program, "lut");
 	shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
 	shader->color_uniform = glGetUniformLocation(shader->program, "color");
 
@@ -1982,13 +2056,25 @@  compile_shaders(struct weston_compositor *ec)
 	gr->texture_shader_rgba.vertex_source = vertex_shader;
 	gr->texture_shader_rgba.fragment_source = texture_fragment_shader_rgba;
 
+	gr->texture_shader_rgba_lut.vertex_source = vertex_shader;
+	gr->texture_shader_rgba_lut.fragment_source =
+		texture_fragment_shader_rgba_lut;
+
 	gr->texture_shader_rgbx.vertex_source = vertex_shader;
 	gr->texture_shader_rgbx.fragment_source = texture_fragment_shader_rgbx;
 
+	gr->texture_shader_rgbx_lut.vertex_source = vertex_shader;
+	gr->texture_shader_rgbx_lut.fragment_source =
+		texture_fragment_shader_rgbx_lut;
+
 	gr->texture_shader_egl_external.vertex_source = vertex_shader;
 	gr->texture_shader_egl_external.fragment_source =
 		texture_fragment_shader_egl_external;
 
+	gr->texture_shader_egl_external_lut.vertex_source = vertex_shader;
+	gr->texture_shader_egl_external_lut.fragment_source =
+		texture_fragment_shader_egl_external_lut;
+
 	gr->texture_shader_y_uv.vertex_source = vertex_shader;
 	gr->texture_shader_y_uv.fragment_source = texture_fragment_shader_y_uv;
 
@@ -2003,6 +2089,9 @@  compile_shaders(struct weston_compositor *ec)
 	gr->solid_shader.vertex_source = vertex_shader;
 	gr->solid_shader.fragment_source = solid_fragment_shader;
 
+	gr->fb_shader.vertex_source = vertex_shader;
+	gr->fb_shader.fragment_source = fb_fragment_shader;
+
 	return 0;
 }
 
@@ -2017,12 +2106,16 @@  fragment_debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
 	gr->fragment_shader_debug ^= 1;
 
 	shader_release(&gr->texture_shader_rgba);
+	shader_release(&gr->texture_shader_rgba_lut);
 	shader_release(&gr->texture_shader_rgbx);
+	shader_release(&gr->texture_shader_rgbx_lut);
 	shader_release(&gr->texture_shader_egl_external);
+	shader_release(&gr->texture_shader_egl_external_lut);
 	shader_release(&gr->texture_shader_y_uv);
 	shader_release(&gr->texture_shader_y_u_v);
 	shader_release(&gr->texture_shader_y_xuxv);
 	shader_release(&gr->solid_shader);
+	shader_release(&gr->fb_shader);
 
 	/* Force use_shader() to call glUseProgram(), since we need to use
 	 * the recompiled version of the shader. */
@@ -2090,6 +2183,9 @@  gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
 	gr->image_target_texture_2d =
 		(void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
 
+	gr->teximage3d =
+		(void *) eglGetProcAddress("glTexImage3DOES");
+
 	extensions = (const char *) glGetString(GL_EXTENSIONS);
 	if (!extensions) {
 		weston_log("Retrieving GL extension string failed.\n");
@@ -2114,6 +2210,12 @@  gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
 	if (strstr(extensions, "GL_OES_EGL_image_external"))
 		gr->has_egl_image_external = 1;
 
+	if (strstr(extensions, "GL_OES_texture_3D"))
+		gr->has_texture_3d = 1;
+	else
+		weston_log("warning: GL_OES_texture_3D not supported. "
+			   "Color correction will be disabled.\n");
+
 	glActiveTexture(GL_TEXTURE0);
 
 	if (compile_shaders(ec))