[RFCv2 1/9] gl-renderer: Move shader functions into it's own file.

John Kåre Alsaker john.kare.alsaker at gmail.com
Fri Nov 16 18:23:52 PST 2012


This moves all shader functions into it's own file in preparation of a more
flexible shader generation. It adds gl-internal.h for shared definitions
between the files.
---
 src/Makefile.am   |   2 +
 src/gl-internal.h | 138 ++++++++++++++++++++
 src/gl-renderer.c | 376 ++----------------------------------------------------
 src/gl-shaders.c  | 284 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 437 insertions(+), 363 deletions(-)
 create mode 100644 src/gl-internal.h
 create mode 100644 src/gl-shaders.c

diff --git a/src/Makefile.am b/src/Makefile.am
index ef71d00..0c315cd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -34,6 +34,8 @@ weston_SOURCES =				\
 	util.c					\
 	matrix.c				\
 	matrix.h				\
+	gl-shaders.c				\
+	gl-internal.h				\
 	gl-renderer.h				\
 	gl-renderer.c				\
 	noop-renderer.c				\
diff --git a/src/gl-internal.h b/src/gl-internal.h
new file mode 100644
index 0000000..90912df
--- /dev/null
+++ b/src/gl-internal.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright © 2012 Intel Corporation
+ * Copyright © 2012 John Kåre Alsaker
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _GL_INTERNAL_H_
+#define _GL_INTERNAL_H_
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <float.h>
+#include <assert.h>
+#include <linux/input.h>
+
+#include "gl-renderer.h"
+
+#include <EGL/eglext.h>
+#include "weston-egl-ext.h"
+
+struct gl_shader {
+	GLuint program;
+	GLuint vertex_shader, fragment_shader;
+	GLint proj_uniform;
+	GLint tex_uniforms[3];
+	GLint alpha_uniform;
+	GLint color_uniform;
+};
+
+struct gl_output_state {
+	EGLSurface egl_surface;
+};
+
+struct gl_surface_state {
+	GLfloat color[4];
+	struct gl_shader *shader;
+
+	GLuint textures[3];
+	int num_textures;
+
+	EGLImageKHR images[3];
+	GLenum target;
+	int num_images;
+};
+
+struct gl_renderer {
+	struct weston_renderer base;
+	int fragment_shader_debug;
+
+	EGLDisplay egl_display;
+	EGLContext egl_context;
+	EGLConfig egl_config;
+
+	struct {
+		int32_t top, bottom, left, right;
+		GLuint texture;
+		int32_t width, height;
+	} border;
+
+	PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
+	PFNEGLCREATEIMAGEKHRPROC create_image;
+	PFNEGLDESTROYIMAGEKHRPROC destroy_image;
+
+	int has_unpack_subimage;
+
+	PFNEGLBINDWAYLANDDISPLAYWL bind_display;
+	PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
+	PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
+	int has_bind_display;
+
+	int has_egl_image_external;
+
+	struct gl_shader texture_shader_rgba;
+	struct gl_shader texture_shader_rgbx;
+	struct gl_shader texture_shader_egl_external;
+	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 *current_shader;
+};
+
+static inline struct gl_output_state *
+get_output_state(struct weston_output *output)
+{
+	return (struct gl_output_state *)output->renderer_state;
+}
+
+static inline struct gl_surface_state *
+get_surface_state(struct weston_surface *surface)
+{
+	return (struct gl_surface_state *)surface->renderer_state;
+}
+
+static inline struct gl_renderer *
+get_renderer(struct weston_compositor *ec)
+{
+	return (struct gl_renderer *)ec->renderer;
+}
+
+int
+gl_init_shaders(struct gl_renderer *gr);
+
+void
+gl_destroy_shaders(struct gl_renderer *gr);
+
+void
+gl_use_shader(struct gl_renderer *gr,
+			     struct gl_shader *shader);
+
+void
+gl_shader_uniforms(struct gl_shader *shader,
+		       struct weston_surface *surface,
+		       struct weston_output *output);
+
+#endif
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 45b60dd..a14fe2f 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2012 Intel Corporation
+ * Copyright © 2012 John Kåre Alsaker
  *
  * Permission to use, copy, modify, distribute, and sell this software and
  * its documentation for any purpose is hereby granted without fee, provided
@@ -22,101 +23,7 @@
 
 #define _GNU_SOURCE
 
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <float.h>
-#include <assert.h>
-#include <linux/input.h>
-
-#include "gl-renderer.h"
-
-#include <EGL/eglext.h>
-#include "weston-egl-ext.h"
-
-struct gl_shader {
-	GLuint program;
-	GLuint vertex_shader, fragment_shader;
-	GLint proj_uniform;
-	GLint tex_uniforms[3];
-	GLint alpha_uniform;
-	GLint color_uniform;
-};
-
-struct gl_output_state {
-	EGLSurface egl_surface;
-};
-
-struct gl_surface_state {
-	GLfloat color[4];
-	struct gl_shader *shader;
-
-	GLuint textures[3];
-	int num_textures;
-
-	EGLImageKHR images[3];
-	GLenum target;
-	int num_images;
-};
-
-struct gl_renderer {
-	struct weston_renderer base;
-	int fragment_shader_debug;
-
-	EGLDisplay egl_display;
-	EGLContext egl_context;
-	EGLConfig egl_config;
-
-	struct {
-		int32_t top, bottom, left, right;
-		GLuint texture;
-		int32_t width, height;
-	} border;
-
-	PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
-	PFNEGLCREATEIMAGEKHRPROC create_image;
-	PFNEGLDESTROYIMAGEKHRPROC destroy_image;
-
-	int has_unpack_subimage;
-
-	PFNEGLBINDWAYLANDDISPLAYWL bind_display;
-	PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
-	PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
-	int has_bind_display;
-
-	int has_egl_image_external;
-
-	struct gl_shader texture_shader_rgba;
-	struct gl_shader texture_shader_rgbx;
-	struct gl_shader texture_shader_egl_external;
-	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 *current_shader;
-};
-
-static inline struct gl_output_state *
-get_output_state(struct weston_output *output)
-{
-	return (struct gl_output_state *)output->renderer_state;
-}
-
-static inline struct gl_surface_state *
-get_surface_state(struct weston_surface *surface)
-{
-	return (struct gl_surface_state *)surface->renderer_state;
-}
-
-static inline struct gl_renderer *
-get_renderer(struct weston_compositor *ec)
-{
-	return (struct gl_renderer *)ec->renderer;
-}
+#include "gl-internal.h"
 
 static const char *
 egl_error_string(EGLint code)
@@ -689,34 +596,6 @@ use_output(struct weston_output *output)
 }
 
 static void
-use_shader(struct gl_renderer *gr,
-			     struct gl_shader *shader)
-{
-	if (gr->current_shader == shader)
-		return;
-
-	glUseProgram(shader->program);
-	gr->current_shader = shader;
-}
-
-static void
-shader_uniforms(struct gl_shader *shader,
-		       struct weston_surface *surface,
-		       struct weston_output *output)
-{
-	int i;
-	struct gl_surface_state *gs = get_surface_state(surface);
-
-	glUniformMatrix4fv(shader->proj_uniform,
-			   1, GL_FALSE, output->matrix.d);
-	glUniform4fv(shader->color_uniform, 1, gs->color);
-	glUniform1f(shader->alpha_uniform, surface->alpha);
-
-	for (i = 0; i < gs->num_textures; i++)
-		glUniform1i(shader->tex_uniforms[i], i);
-}
-
-static void
 draw_surface(struct weston_surface *es, struct weston_output *output,
 	     pixman_region32_t *damage) /* in global coordinates */
 {
@@ -745,12 +624,12 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
 	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
 	if (ec->fan_debug) {
-		use_shader(gr, &gr->solid_shader);
-		shader_uniforms(&gr->solid_shader, es, output);
+		gl_use_shader(gr, &gr->solid_shader);
+		gl_shader_uniforms(&gr->solid_shader, es, output);
 	}
 
-	use_shader(gr, gs->shader);
-	shader_uniforms(gs->shader, es, output);
+	gl_use_shader(gr, gs->shader);
+	gl_shader_uniforms(gs->shader, es, output);
 
 	if (es->transform.enabled || output->zoom.active)
 		filter = GL_LINEAR;
@@ -776,8 +655,8 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
 			 * that forces texture alpha = 1.0.
 			 * Xwayland surfaces need this.
 			 */
-			use_shader(gr, &gr->texture_shader_rgbx);
-			shader_uniforms(&gr->texture_shader_rgbx, es, output);
+			gl_use_shader(gr, &gr->texture_shader_rgbx);
+			gl_shader_uniforms(&gr->texture_shader_rgbx, es, output);
 		}
 
 		if (es->alpha < 1.0)
@@ -789,7 +668,7 @@ draw_surface(struct weston_surface *es, struct weston_output *output,
 	}
 
 	if (pixman_region32_not_empty(&surface_blend)) {
-		use_shader(gr, gs->shader);
+		gl_use_shader(gr, gs->shader);
 		glEnable(GL_BLEND);
 		repaint_region(es, &repaint, &surface_blend);
 	}
@@ -898,7 +777,7 @@ draw_border(struct weston_output *output)
 	int n;
 
 	glDisable(GL_BLEND);
-	use_shader(gr, shader);
+	gl_use_shader(gr, shader);
 
 	glUniformMatrix4fv(shader->proj_uniform,
 			   1, GL_FALSE, output->matrix.d);
@@ -1230,197 +1109,6 @@ gl_renderer_destroy_surface(struct weston_surface *surface)
 	free(gs);
 }
 
-static const char vertex_shader[] =
-	"uniform mat4 proj;\n"
-	"attribute vec2 position;\n"
-	"attribute vec2 texcoord;\n"
-	"varying vec2 v_texcoord;\n"
-	"void main()\n"
-	"{\n"
-	"   gl_Position = proj * vec4(position, 0.0, 1.0);\n"
-	"   v_texcoord = texcoord;\n"
-	"}\n";
-
-/* Declare common fragment shader uniforms */
-#define FRAGMENT_CONVERT_YUV						\
-	"  y *= alpha;\n"						\
-	"  u *= alpha;\n"						\
-	"  v *= alpha;\n"						\
-	"  gl_FragColor.r = y + 1.59602678 * v;\n"			\
-	"  gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n"	\
-	"  gl_FragColor.b = y + 2.01723214 * u;\n"			\
-	"  gl_FragColor.a = alpha;\n"
-
-static const char fragment_debug[] =
-	"  gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
-
-static const char fragment_brace[] =
-	"}\n";
-
-static const char texture_fragment_shader_rgba[] =
-	"precision mediump float;\n"
-	"varying vec2 v_texcoord;\n"
-	"uniform sampler2D tex;\n"
-	"uniform float alpha;\n"
-	"void main()\n"
-	"{\n"
-	"   gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
-	;
-
-static const char texture_fragment_shader_rgbx[] =
-	"precision mediump float;\n"
-	"varying vec2 v_texcoord;\n"
-	"uniform sampler2D tex;\n"
-	"uniform float alpha;\n"
-	"void main()\n"
-	"{\n"
-	"   gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
-	"   gl_FragColor.a = alpha;\n"
-	;
-
-static const char texture_fragment_shader_egl_external[] =
-	"#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"
-	"void main()\n"
-	"{\n"
-	"   gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
-	;
-
-static const char texture_fragment_shader_y_uv[] =
-	"precision mediump float;\n"
-	"uniform sampler2D tex;\n"
-	"uniform sampler2D tex1;\n"
-	"varying vec2 v_texcoord;\n"
-	"uniform float alpha;\n"
-	"void main() {\n"
-	"  float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
-	"  float u = texture2D(tex1, v_texcoord).r - 0.5;\n"
-	"  float v = texture2D(tex1, v_texcoord).g - 0.5;\n"
-	FRAGMENT_CONVERT_YUV
-	;
-
-static const char texture_fragment_shader_y_u_v[] =
-	"precision mediump float;\n"
-	"uniform sampler2D tex;\n"
-	"uniform sampler2D tex1;\n"
-	"uniform sampler2D tex2;\n"
-	"varying vec2 v_texcoord;\n"
-	"uniform float alpha;\n"
-	"void main() {\n"
-	"  float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
-	"  float u = texture2D(tex1, v_texcoord).x - 0.5;\n"
-	"  float v = texture2D(tex2, v_texcoord).x - 0.5;\n"
-	FRAGMENT_CONVERT_YUV
-	;
-
-static const char texture_fragment_shader_y_xuxv[] =
-	"precision mediump float;\n"
-	"uniform sampler2D tex;\n"
-	"uniform sampler2D tex1;\n"
-	"varying vec2 v_texcoord;\n"
-	"uniform float alpha;\n"
-	"void main() {\n"
-	"  float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
-	"  float u = texture2D(tex1, v_texcoord).g - 0.5;\n"
-	"  float v = texture2D(tex1, v_texcoord).a - 0.5;\n"
-	FRAGMENT_CONVERT_YUV
-	;
-
-static const char solid_fragment_shader[] =
-	"precision mediump float;\n"
-	"uniform vec4 color;\n"
-	"uniform float alpha;\n"
-	"void main()\n"
-	"{\n"
-	"   gl_FragColor = alpha * color\n;"
-	;
-
-static int
-compile_shader(GLenum type, int count, const char **sources)
-{
-	GLuint s;
-	char msg[512];
-	GLint status;
-
-	s = glCreateShader(type);
-	glShaderSource(s, count, sources, NULL);
-	glCompileShader(s);
-	glGetShaderiv(s, GL_COMPILE_STATUS, &status);
-	if (!status) {
-		glGetShaderInfoLog(s, sizeof msg, NULL, msg);
-		weston_log("shader info: %s\n", msg);
-		return GL_NONE;
-	}
-
-	return s;
-}
-
-static int
-shader_init(struct gl_shader *shader, struct weston_compositor *ec,
-		   const char *vertex_source, const char *fragment_source)
-{
-	char msg[512];
-	GLint status;
-	int count;
-	const char *sources[3];
-	struct gl_renderer *renderer = get_renderer(ec);
-
-	shader->vertex_shader =
-		compile_shader(GL_VERTEX_SHADER, 1, &vertex_source);
-
-	if (renderer->fragment_shader_debug) {
-		sources[0] = fragment_source;
-		sources[1] = fragment_debug;
-		sources[2] = fragment_brace;
-		count = 3;
-	} else {
-		sources[0] = fragment_source;
-		sources[1] = fragment_brace;
-		count = 2;
-	}
-
-	shader->fragment_shader =
-		compile_shader(GL_FRAGMENT_SHADER, count, sources);
-
-	shader->program = glCreateProgram();
-	glAttachShader(shader->program, shader->vertex_shader);
-	glAttachShader(shader->program, shader->fragment_shader);
-	glBindAttribLocation(shader->program, 0, "position");
-	glBindAttribLocation(shader->program, 1, "texcoord");
-
-	glLinkProgram(shader->program);
-	glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
-	if (!status) {
-		glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
-		weston_log("link info: %s\n", msg);
-		return -1;
-	}
-
-	shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
-	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->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
-	shader->color_uniform = glGetUniformLocation(shader->program, "color");
-
-	return 0;
-}
-
-static void
-shader_release(struct gl_shader *shader)
-{
-	glDeleteShader(shader->vertex_shader);
-	glDeleteShader(shader->fragment_shader);
-	glDeleteProgram(shader->program);
-
-	shader->vertex_shader = 0;
-	shader->fragment_shader = 0;
-	shader->program = 0;
-}
-
 static void
 log_extensions(const char *name, const char *extensions)
 {
@@ -1730,37 +1418,6 @@ gl_renderer_display(struct weston_compositor *ec)
 	return get_renderer(ec)->egl_display;
 }
 
-static int
-compile_shaders(struct weston_compositor *ec)
-{
-	struct gl_renderer *gr = get_renderer(ec);
-
-	if (shader_init(&gr->texture_shader_rgba, ec,
-			     vertex_shader, texture_fragment_shader_rgba) < 0)
-		return -1;
-	if (shader_init(&gr->texture_shader_rgbx, ec,
-			     vertex_shader, texture_fragment_shader_rgbx) < 0)
-		return -1;
-	if (gr->has_egl_image_external &&
-			shader_init(&gr->texture_shader_egl_external, ec,
-				vertex_shader, texture_fragment_shader_egl_external) < 0)
-		return -1;
-	if (shader_init(&gr->texture_shader_y_uv, ec,
-			       vertex_shader, texture_fragment_shader_y_uv) < 0)
-		return -1;
-	if (shader_init(&gr->texture_shader_y_u_v, ec,
-			       vertex_shader, texture_fragment_shader_y_u_v) < 0)
-		return -1;
-	if (shader_init(&gr->texture_shader_y_xuxv, ec,
-			       vertex_shader, texture_fragment_shader_y_xuxv) < 0)
-		return -1;
-	if (shader_init(&gr->solid_shader, ec,
-			     vertex_shader, solid_fragment_shader) < 0)
-		return -1;
-
-	return 0;
-}
-
 static void
 fragment_debug_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
 		       void *data)
@@ -1771,15 +1428,8 @@ fragment_debug_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
 
 	gr->fragment_shader_debug ^= 1;
 
-	shader_release(&gr->texture_shader_rgba);
-	shader_release(&gr->texture_shader_rgbx);
-	shader_release(&gr->texture_shader_egl_external);
-	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);
-
-	compile_shaders(ec);
+	gl_destroy_shaders(gr);
+	gl_init_shaders(gr);
 
 	wl_list_for_each(output, &ec->output_list, link)
 		weston_output_damage(output);
@@ -1873,7 +1523,7 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
 
 	glActiveTexture(GL_TEXTURE0);
 
-	if (compile_shaders(ec))
+	if (gl_init_shaders(gr) < 0)
 		return -1;
 
 	weston_compositor_add_debug_binding(ec, KEY_S,
diff --git a/src/gl-shaders.c b/src/gl-shaders.c
new file mode 100644
index 0000000..35275ca
--- /dev/null
+++ b/src/gl-shaders.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright © 2012 John Kåre Alsaker
+ * Copyright © 2012 Intel Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the copyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission.  The copyright holders make
+ * no representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gl-internal.h"
+
+void
+gl_use_shader(struct gl_renderer *gr,
+			     struct gl_shader *shader)
+{
+	if (gr->current_shader == shader)
+		return;
+
+	glUseProgram(shader->program);
+	gr->current_shader = shader;
+}
+
+void
+gl_shader_uniforms(struct gl_shader *shader,
+		       struct weston_surface *surface,
+		       struct weston_output *output)
+{
+	int i;
+	struct gl_surface_state *gs = get_surface_state(surface);
+
+	glUniformMatrix4fv(shader->proj_uniform,
+			   1, GL_FALSE, output->matrix.d);
+	glUniform4fv(shader->color_uniform, 1, gs->color);
+	glUniform1f(shader->alpha_uniform, surface->alpha);
+
+	for (i = 0; i < gs->num_textures; i++)
+		glUniform1i(shader->tex_uniforms[i], i);
+}
+
+static const char vertex_shader[] =
+	"uniform mat4 proj;\n"
+	"attribute vec2 position;\n"
+	"attribute vec2 texcoord;\n"
+	"varying vec2 v_texcoord;\n"
+	"void main()\n"
+	"{\n"
+	"   gl_Position = proj * vec4(position, 0.0, 1.0);\n"
+	"   v_texcoord = texcoord;\n"
+	"}\n";
+
+/* Declare common fragment shader uniforms */
+#define FRAGMENT_CONVERT_YUV						\
+	"  y *= alpha;\n"						\
+	"  u *= alpha;\n"						\
+	"  v *= alpha;\n"						\
+	"  gl_FragColor.r = y + 1.59602678 * v;\n"			\
+	"  gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n"	\
+	"  gl_FragColor.b = y + 2.01723214 * u;\n"			\
+	"  gl_FragColor.a = alpha;\n"
+
+static const char fragment_debug[] =
+	"  gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8;\n";
+
+static const char fragment_brace[] =
+	"}\n";
+
+static const char texture_fragment_shader_rgba[] =
+	"precision mediump float;\n"
+	"varying vec2 v_texcoord;\n"
+	"uniform sampler2D tex;\n"
+	"uniform float alpha;\n"
+	"void main()\n"
+	"{\n"
+	"   gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
+	;
+
+static const char texture_fragment_shader_rgbx[] =
+	"precision mediump float;\n"
+	"varying vec2 v_texcoord;\n"
+	"uniform sampler2D tex;\n"
+	"uniform float alpha;\n"
+	"void main()\n"
+	"{\n"
+	"   gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb\n;"
+	"   gl_FragColor.a = alpha;\n"
+	;
+
+static const char texture_fragment_shader_egl_external[] =
+	"#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"
+	"void main()\n"
+	"{\n"
+	"   gl_FragColor = alpha * texture2D(tex, v_texcoord)\n;"
+	;
+
+static const char texture_fragment_shader_y_uv[] =
+	"precision mediump float;\n"
+	"uniform sampler2D tex;\n"
+	"uniform sampler2D tex1;\n"
+	"varying vec2 v_texcoord;\n"
+	"uniform float alpha;\n"
+	"void main() {\n"
+	"  float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
+	"  float u = texture2D(tex1, v_texcoord).r - 0.5;\n"
+	"  float v = texture2D(tex1, v_texcoord).g - 0.5;\n"
+	FRAGMENT_CONVERT_YUV
+	;
+
+static const char texture_fragment_shader_y_u_v[] =
+	"precision mediump float;\n"
+	"uniform sampler2D tex;\n"
+	"uniform sampler2D tex1;\n"
+	"uniform sampler2D tex2;\n"
+	"varying vec2 v_texcoord;\n"
+	"uniform float alpha;\n"
+	"void main() {\n"
+	"  float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
+	"  float u = texture2D(tex1, v_texcoord).x - 0.5;\n"
+	"  float v = texture2D(tex2, v_texcoord).x - 0.5;\n"
+	FRAGMENT_CONVERT_YUV
+	;
+
+static const char texture_fragment_shader_y_xuxv[] =
+	"precision mediump float;\n"
+	"uniform sampler2D tex;\n"
+	"uniform sampler2D tex1;\n"
+	"varying vec2 v_texcoord;\n"
+	"uniform float alpha;\n"
+	"void main() {\n"
+	"  float y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625);\n"
+	"  float u = texture2D(tex1, v_texcoord).g - 0.5;\n"
+	"  float v = texture2D(tex1, v_texcoord).a - 0.5;\n"
+	FRAGMENT_CONVERT_YUV
+	;
+
+static const char solid_fragment_shader[] =
+	"precision mediump float;\n"
+	"uniform vec4 color;\n"
+	"uniform float alpha;\n"
+	"void main()\n"
+	"{\n"
+	"   gl_FragColor = alpha * color\n;"
+	;
+
+static int
+compile_shader(GLenum type, int count, const char **sources)
+{
+	GLuint s;
+	char msg[512];
+	GLint status;
+
+	s = glCreateShader(type);
+	glShaderSource(s, count, sources, NULL);
+	glCompileShader(s);
+	glGetShaderiv(s, GL_COMPILE_STATUS, &status);
+	if (!status) {
+		glGetShaderInfoLog(s, sizeof msg, NULL, msg);
+		weston_log("shader info: %s\n", msg);
+		return GL_NONE;
+	}
+
+	return s;
+}
+
+static int
+shader_init(struct gl_renderer *renderer, struct gl_shader *shader,
+		   const char *vertex_source, const char *fragment_source)
+{
+	char msg[512];
+	GLint status;
+	int count;
+	const char *sources[3];
+
+	shader->vertex_shader =
+		compile_shader(GL_VERTEX_SHADER, 1, &vertex_source);
+
+	if (renderer->fragment_shader_debug) {
+		sources[0] = fragment_source;
+		sources[1] = fragment_debug;
+		sources[2] = fragment_brace;
+		count = 3;
+	} else {
+		sources[0] = fragment_source;
+		sources[1] = fragment_brace;
+		count = 2;
+	}
+
+	shader->fragment_shader =
+		compile_shader(GL_FRAGMENT_SHADER, count, sources);
+
+	shader->program = glCreateProgram();
+	glAttachShader(shader->program, shader->vertex_shader);
+	glAttachShader(shader->program, shader->fragment_shader);
+	glBindAttribLocation(shader->program, 0, "position");
+	glBindAttribLocation(shader->program, 1, "texcoord");
+
+	glLinkProgram(shader->program);
+	glGetProgramiv(shader->program, GL_LINK_STATUS, &status);
+	if (!status) {
+		glGetProgramInfoLog(shader->program, sizeof msg, NULL, msg);
+		weston_log("link info: %s\n", msg);
+		return -1;
+	}
+
+	shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
+	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->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
+	shader->color_uniform = glGetUniformLocation(shader->program, "color");
+
+	return 0;
+}
+
+static void
+shader_release(struct gl_shader *shader)
+{
+	glDeleteShader(shader->vertex_shader);
+	glDeleteShader(shader->fragment_shader);
+	glDeleteProgram(shader->program);
+
+	shader->vertex_shader = 0;
+	shader->fragment_shader = 0;
+	shader->program = 0;
+}
+
+int
+gl_init_shaders(struct gl_renderer *gr)
+{
+	if (shader_init(gr, &gr->texture_shader_rgba,
+			     vertex_shader, texture_fragment_shader_rgba) < 0)
+		return -1;
+	if (shader_init(gr, &gr->texture_shader_rgbx,
+			     vertex_shader, texture_fragment_shader_rgbx) < 0)
+		return -1;
+	if (gr->has_egl_image_external &&
+			shader_init(gr, &gr->texture_shader_egl_external,
+				vertex_shader, texture_fragment_shader_egl_external) < 0)
+		return -1;
+	if (shader_init(gr, &gr->texture_shader_y_uv,
+			       vertex_shader, texture_fragment_shader_y_uv) < 0)
+		return -1;
+	if (shader_init(gr, &gr->texture_shader_y_u_v,
+			       vertex_shader, texture_fragment_shader_y_u_v) < 0)
+		return -1;
+	if (shader_init(gr, &gr->texture_shader_y_xuxv,
+			       vertex_shader, texture_fragment_shader_y_xuxv) < 0)
+		return -1;
+	if (shader_init(gr, &gr->solid_shader,
+			     vertex_shader, solid_fragment_shader) < 0)
+		return -1;
+
+	return 0;
+}
+
+void
+gl_destroy_shaders(struct gl_renderer *gr)
+{
+	shader_release(&gr->texture_shader_rgba);
+	shader_release(&gr->texture_shader_rgbx);
+	shader_release(&gr->texture_shader_egl_external);
+	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);
+
+}
-- 
1.8.0



More information about the wayland-devel mailing list