compositor: Move gles2 initialization to gles2-renderer.h
diff --git a/src/gles2-renderer.c b/src/gles2-renderer.c
index 14dcf64..fb70375 100644
--- a/src/gles2-renderer.c
+++ b/src/gles2-renderer.c
@@ -20,7 +20,11 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
+#define _GNU_SOURCE
+
 #include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
 
 #include "compositor.h"
 
@@ -669,3 +673,300 @@
 	}
 
 }
+
+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 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;"
+	"}\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"
+	"}\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;"
+	"}\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
+	"}\n";
+
+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
+	"}\n";
+
+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
+	"}\n";
+
+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;"
+	"}\n";
+
+static int
+compile_shader(GLenum type, const char *source)
+{
+	GLuint s;
+	char msg[512];
+	GLint status;
+
+	s = glCreateShader(type);
+	glShaderSource(s, 1, &source, 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
+weston_shader_init(struct weston_shader *shader,
+		   const char *vertex_source, const char *fragment_source)
+{
+	char msg[512];
+	GLint status;
+
+	shader->vertex_shader =
+		compile_shader(GL_VERTEX_SHADER, vertex_source);
+	shader->fragment_shader =
+		compile_shader(GL_FRAGMENT_SHADER, fragment_source);
+
+	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
+log_extensions(const char *name, const char *extensions)
+{
+	const char *p, *end;
+	int l;
+	int len;
+
+	l = weston_log("%s:", name);
+	p = extensions;
+	while (*p) {
+		end = strchrnul(p, ' ');
+		len = end - p;
+		if (l + len > 78)
+			l = weston_log_continue("\n" STAMP_SPACE "%.*s",
+						len, p);
+		else
+			l += weston_log_continue(" %.*s", len, p);
+		for (p = end; isspace(*p); p++)
+			;
+	}
+	weston_log_continue("\n");
+}
+
+static void
+log_egl_gl_info(EGLDisplay egldpy)
+{
+	const char *str;
+
+	str = eglQueryString(egldpy, EGL_VERSION);
+	weston_log("EGL version: %s\n", str ? str : "(null)");
+
+	str = eglQueryString(egldpy, EGL_VENDOR);
+	weston_log("EGL vendor: %s\n", str ? str : "(null)");
+
+	str = eglQueryString(egldpy, EGL_CLIENT_APIS);
+	weston_log("EGL client APIs: %s\n", str ? str : "(null)");
+
+	str = eglQueryString(egldpy, EGL_EXTENSIONS);
+	log_extensions("EGL extensions", str ? str : "(null)");
+
+	str = (char *)glGetString(GL_VERSION);
+	weston_log("GL version: %s\n", str ? str : "(null)");
+
+	str = (char *)glGetString(GL_SHADING_LANGUAGE_VERSION);
+	weston_log("GLSL version: %s\n", str ? str : "(null)");
+
+	str = (char *)glGetString(GL_VENDOR);
+	weston_log("GL vendor: %s\n", str ? str : "(null)");
+
+	str = (char *)glGetString(GL_RENDERER);
+	weston_log("GL renderer: %s\n", str ? str : "(null)");
+
+	str = (char *)glGetString(GL_EXTENSIONS);
+	log_extensions("GL extensions", str ? str : "(null)");
+}
+
+WL_EXPORT int
+gles2_renderer_init(struct weston_compositor *ec)
+{
+	const char *extensions;
+	int has_egl_image_external = 0;
+
+	log_egl_gl_info(ec->egl_display);
+
+	ec->image_target_texture_2d =
+		(void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
+	ec->image_target_renderbuffer_storage = (void *)
+		eglGetProcAddress("glEGLImageTargetRenderbufferStorageOES");
+	ec->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
+	ec->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
+	ec->bind_display =
+		(void *) eglGetProcAddress("eglBindWaylandDisplayWL");
+	ec->unbind_display =
+		(void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
+	ec->query_buffer =
+		(void *) eglGetProcAddress("eglQueryWaylandBufferWL");
+
+	extensions = (const char *) glGetString(GL_EXTENSIONS);
+	if (!extensions) {
+		weston_log("Retrieving GL extension string failed.\n");
+		return -1;
+	}
+
+	if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
+		weston_log("GL_EXT_texture_format_BGRA8888 not available\n");
+		return -1;
+	}
+
+	if (strstr(extensions, "GL_EXT_read_format_bgra"))
+		ec->read_format = GL_BGRA_EXT;
+	else
+		ec->read_format = GL_RGBA;
+
+	if (strstr(extensions, "GL_EXT_unpack_subimage"))
+		ec->has_unpack_subimage = 1;
+
+	if (strstr(extensions, "GL_OES_EGL_image_external"))
+		has_egl_image_external = 1;
+
+	extensions =
+		(const char *) eglQueryString(ec->egl_display, EGL_EXTENSIONS);
+	if (!extensions) {
+		weston_log("Retrieving EGL extension string failed.\n");
+		return -1;
+	}
+
+	if (strstr(extensions, "EGL_WL_bind_wayland_display"))
+		ec->has_bind_display = 1;
+	if (ec->has_bind_display)
+		ec->bind_display(ec->egl_display, ec->wl_display);
+
+	glActiveTexture(GL_TEXTURE0);
+
+	if (weston_shader_init(&ec->texture_shader_rgba,
+			     vertex_shader, texture_fragment_shader_rgba) < 0)
+		return -1;
+	if (weston_shader_init(&ec->texture_shader_rgbx,
+			     vertex_shader, texture_fragment_shader_rgbx) < 0)
+		return -1;
+	if (has_egl_image_external &&
+			weston_shader_init(&ec->texture_shader_egl_external,
+				vertex_shader, texture_fragment_shader_egl_external) < 0)
+		return -1;
+	if (weston_shader_init(&ec->texture_shader_y_uv,
+			       vertex_shader, texture_fragment_shader_y_uv) < 0)
+		return -1;
+	if (weston_shader_init(&ec->texture_shader_y_u_v,
+			       vertex_shader, texture_fragment_shader_y_u_v) < 0)
+		return -1;
+	if (weston_shader_init(&ec->texture_shader_y_xuxv,
+			       vertex_shader, texture_fragment_shader_y_xuxv) < 0)
+		return -1;
+	if (weston_shader_init(&ec->solid_shader,
+			     vertex_shader, solid_fragment_shader) < 0)
+		return -1;
+
+	return 0;
+}