diff --git a/libweston/renderer-gl/fragment.glsl b/libweston/renderer-gl/fragment.glsl new file mode 100644 index 000000000..45e4e9543 --- /dev/null +++ b/libweston/renderer-gl/fragment.glsl @@ -0,0 +1,130 @@ +/* + * Copyright 2012 Intel Corporation + * Copyright 2015,2019 Collabora, Ltd. + * Copyright 2016 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* GLSL version 1.00 ES, defined in gl-shaders.c */ + +/* + * Enumeration of shader variants. + */ +#define SHADER_VARIANT_RGBX 1 +#define SHADER_VARIANT_RGBA 2 +#define SHADER_VARIANT_Y_U_V 3 +#define SHADER_VARIANT_Y_UV 4 +#define SHADER_VARIANT_Y_XUXV 5 +#define SHADER_VARIANT_XYUV 6 +#define SHADER_VARIANT_SOLID 7 +#define SHADER_VARIANT_EXTERNAL 8 + +#if DEF_VARIANT == SHADER_VARIANT_EXTERNAL +#extension GL_OES_EGL_image_external : require +#endif + +precision mediump float; + +/* + * These undeclared identifiers will be #defined by a runtime generated code + * snippet. + */ +const int c_variant = DEF_VARIANT; +const bool c_debug = DEF_DEBUG; + +vec4 +yuva2rgba(float y, float u, float v, float a) +{ + vec4 color_out; + + y *= a; + u *= a; + v *= a; + color_out.r = y + 1.59602678 * v; + color_out.g = y - 0.39176229 * u - 0.81296764 * v; + color_out.b = y + 2.01723214 * u; + color_out.a = a; + + return color_out; +} + +#if DEF_VARIANT == SHADER_VARIANT_EXTERNAL +uniform samplerExternalOES tex; +#else +uniform sampler2D tex; +#endif + +varying vec2 v_texcoord; +uniform sampler2D tex1; +uniform sampler2D tex2; +uniform float alpha; +uniform vec4 color; + +void +main() +{ + float y, u, v; + + if (c_variant == SHADER_VARIANT_RGBA || + c_variant == SHADER_VARIANT_EXTERNAL) { + gl_FragColor = alpha * texture2D(tex, v_texcoord); + + } else if (c_variant == SHADER_VARIANT_RGBX) { + gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb; + gl_FragColor.a = alpha; + + } else if (c_variant == SHADER_VARIANT_Y_U_V) { + y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625); + u = texture2D(tex1, v_texcoord).x - 0.5; + v = texture2D(tex2, v_texcoord).x - 0.5; + gl_FragColor = yuva2rgba(y, u, v, alpha); + + } else if (c_variant == SHADER_VARIANT_Y_UV) { + y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625); + u = texture2D(tex1, v_texcoord).r - 0.5; + v = texture2D(tex1, v_texcoord).g - 0.5; + gl_FragColor = yuva2rgba(y, u, v, alpha); + + } else if (c_variant == SHADER_VARIANT_Y_XUXV) { + y = 1.16438356 * (texture2D(tex, v_texcoord).x - 0.0625); + u = texture2D(tex1, v_texcoord).g - 0.5; + v = texture2D(tex1, v_texcoord).a - 0.5; + gl_FragColor = yuva2rgba(y, u, v, alpha); + + } else if (c_variant == SHADER_VARIANT_XYUV) { + y = 1.16438356 * (texture2D(tex, v_texcoord).b - 0.0625); + u = texture2D(tex, v_texcoord).g - 0.5; + v = texture2D(tex, v_texcoord).r - 0.5; + gl_FragColor = yuva2rgba(y, u, v, alpha); + + } else if (c_variant == SHADER_VARIANT_SOLID) { + gl_FragColor = alpha * color; + + } else { + /* Never reached, bad variant value. */ + gl_FragColor = vec4(1.0, 0.3, 1.0, 1.0); + } + + if (c_debug) + gl_FragColor = vec4(0.0, 0.3, 0.0, 0.2) + gl_FragColor * 0.8; +} diff --git a/libweston/renderer-gl/gl-shaders.c b/libweston/renderer-gl/gl-shaders.c index 9199ababd..320f78df0 100644 --- a/libweston/renderer-gl/gl-shaders.c +++ b/libweston/renderer-gl/gl-shaders.c @@ -35,114 +35,8 @@ /* static const char vertex_shader[]; vertex.glsl */ #include "vertex-shader.h" -/* 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 texture_fragment_shader_xyuv[] = - "precision mediump float;\n" - "uniform sampler2D tex;\n" - "varying vec2 v_texcoord;\n" - "uniform float alpha;\n" - "void main() {\n" - " float y = 1.16438356 * (texture2D(tex, v_texcoord).b - 0.0625);\n" - " float u = texture2D(tex, v_texcoord).g - 0.5;\n" - " float v = texture2D(tex, v_texcoord).r - 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 const char fragment_shader[]; fragment.glsl */ +#include "fragment-shader.h" static int compile_shader(GLenum type, int count, const char **sources) @@ -166,31 +60,40 @@ compile_shader(GLenum type, int count, const char **sources) int shader_init(struct gl_shader *shader, struct gl_renderer *renderer, - const char *vertex_source, const char *fragment_source) + const char *vertex_source, const char *fragment_variant) { + static const char fragment_shader_attrs_fmt[] = + "#define DEF_DEBUG %s\n" + "#define DEF_VARIANT %s\n" + ; char msg[512]; GLint status; - int count; + int ret; const char *sources[3]; + char *attrs; + const char *def_debug; shader->vertex_shader = compile_shader(GL_VERTEX_SHADER, 1, &vertex_source); if (shader->vertex_shader == GL_NONE) return -1; - 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; - } + if (renderer->fragment_shader_debug) + def_debug = "true"; + else + def_debug = "false"; - shader->fragment_shader = - compile_shader(GL_FRAGMENT_SHADER, count, sources); + ret = asprintf(&attrs, fragment_shader_attrs_fmt, + def_debug, fragment_variant); + if (ret < 0) + return -1; + + sources[0] = "#version 100\n"; + sources[1] = attrs; + sources[2] = fragment_shader; + shader->fragment_shader = compile_shader(GL_FRAGMENT_SHADER, + 3, sources); + free(attrs); if (shader->fragment_shader == GL_NONE) return -1; @@ -236,31 +139,28 @@ compile_shaders(struct weston_compositor *ec) struct gl_renderer *gr = get_renderer(ec); gr->texture_shader_rgba.vertex_source = vertex_shader; - gr->texture_shader_rgba.fragment_source = texture_fragment_shader_rgba; + gr->texture_shader_rgba.fragment_source = "SHADER_VARIANT_RGBA"; gr->texture_shader_rgbx.vertex_source = vertex_shader; - gr->texture_shader_rgbx.fragment_source = texture_fragment_shader_rgbx; + gr->texture_shader_rgbx.fragment_source = "SHADER_VARIANT_RGBX"; 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.fragment_source = "SHADER_VARIANT_EXTERNAL"; gr->texture_shader_y_uv.vertex_source = vertex_shader; - gr->texture_shader_y_uv.fragment_source = texture_fragment_shader_y_uv; + gr->texture_shader_y_uv.fragment_source = "SHADER_VARIANT_Y_UV"; gr->texture_shader_y_u_v.vertex_source = vertex_shader; - gr->texture_shader_y_u_v.fragment_source = - texture_fragment_shader_y_u_v; + gr->texture_shader_y_u_v.fragment_source = "SHADER_VARIANT_Y_U_V"; gr->texture_shader_y_xuxv.vertex_source = vertex_shader; - gr->texture_shader_y_xuxv.fragment_source = - texture_fragment_shader_y_xuxv; + gr->texture_shader_y_xuxv.fragment_source = "SHADER_VARIANT_Y_XUXV"; gr->texture_shader_xyuv.vertex_source = vertex_shader; - gr->texture_shader_xyuv.fragment_source = texture_fragment_shader_xyuv; + gr->texture_shader_xyuv.fragment_source = "SHADER_VARIANT_XYUV"; gr->solid_shader.vertex_source = vertex_shader; - gr->solid_shader.fragment_source = solid_fragment_shader; + gr->solid_shader.fragment_source = "SHADER_VARIANT_SOLID"; return 0; } diff --git a/libweston/renderer-gl/meson.build b/libweston/renderer-gl/meson.build index 4687b5b06..476e26ce5 100644 --- a/libweston/renderer-gl/meson.build +++ b/libweston/renderer-gl/meson.build @@ -11,8 +11,16 @@ vertex_glsl = custom_target( output: 'vertex-shader.h', ) +fragment_glsl = custom_target( + 'fragment-shader.h', + command: cmd_xxd + [ '-n', 'fragment_shader' ], + input: 'fragment.glsl', + output: 'fragment-shader.h', +) + srcs_renderer_gl = [ 'egl-glue.c', + fragment_glsl, 'gl-renderer.c', 'gl-shaders.c', linux_dmabuf_unstable_v1_protocol_c,