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;
+}