From 116fe3c65cd541b85623820605e237c4076024f2 Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Thu, 12 Nov 2015 15:52:21 -0800 Subject: [PATCH] ector: initial implementation of our own Ector GL backend. --- configure.ac | 2 + src/Makefile_Ector.am | 42 +- src/lib/ector/gl/Ector_GL.h | 24 ++ src/lib/ector/gl/ector_gl_buffer.c | 60 +++ src/lib/ector/gl/ector_gl_buffer.eo | 9 + src/lib/ector/gl/ector_gl_buffer_base.eo | 14 + src/lib/ector/gl/ector_gl_private.h | 69 ++++ src/lib/ector/gl/ector_gl_shader.c | 168 ++++++++ src/lib/ector/gl/ector_gl_surface.c | 383 ++++++++++++++++++ src/lib/ector/gl/ector_gl_surface.eo | 35 ++ src/lib/ector/gl/ector_renderer_gl_base.c | 56 +++ src/lib/ector/gl/ector_renderer_gl_base.eo | 22 + .../gl/ector_renderer_gl_gradient_linear.c | 115 ++++++ .../gl/ector_renderer_gl_gradient_linear.eo | 15 + .../gl/ector_renderer_gl_gradient_radial.c | 113 ++++++ .../gl/ector_renderer_gl_gradient_radial.eo | 15 + src/lib/ector/gl/ector_renderer_gl_shape.c | 170 ++++++++ src/lib/ector/gl/ector_renderer_gl_shape.eo | 14 + src/lib/ector/gl/shader/.gitignore | 1 + src/lib/ector/gl/shader/ector_gl_shaders.x | 285 +++++++++++++ src/lib/ector/gl/shader/fragment.glsl | 168 ++++++++ src/lib/ector/gl/shader/gen_shaders.sh | 38 ++ src/lib/ector/gl/shader/include.glsl | 22 + src/lib/ector/gl/shader/vertex.glsl | 137 +++++++ src/lib/eina/eina_util.c | 2 +- .../evas/engines/gl_common/evas_gl_shader.c | 3 - 26 files changed, 1975 insertions(+), 7 deletions(-) create mode 100644 src/lib/ector/gl/Ector_GL.h create mode 100644 src/lib/ector/gl/ector_gl_buffer.c create mode 100644 src/lib/ector/gl/ector_gl_buffer.eo create mode 100644 src/lib/ector/gl/ector_gl_buffer_base.eo create mode 100644 src/lib/ector/gl/ector_gl_private.h create mode 100644 src/lib/ector/gl/ector_gl_shader.c create mode 100644 src/lib/ector/gl/ector_gl_surface.c create mode 100644 src/lib/ector/gl/ector_gl_surface.eo create mode 100644 src/lib/ector/gl/ector_renderer_gl_base.c create mode 100644 src/lib/ector/gl/ector_renderer_gl_base.eo create mode 100644 src/lib/ector/gl/ector_renderer_gl_gradient_linear.c create mode 100644 src/lib/ector/gl/ector_renderer_gl_gradient_linear.eo create mode 100644 src/lib/ector/gl/ector_renderer_gl_gradient_radial.c create mode 100644 src/lib/ector/gl/ector_renderer_gl_gradient_radial.eo create mode 100644 src/lib/ector/gl/ector_renderer_gl_shape.c create mode 100644 src/lib/ector/gl/ector_renderer_gl_shape.eo create mode 100644 src/lib/ector/gl/shader/.gitignore create mode 100644 src/lib/ector/gl/shader/ector_gl_shaders.x create mode 100644 src/lib/ector/gl/shader/fragment.glsl create mode 100755 src/lib/ector/gl/shader/gen_shaders.sh create mode 100644 src/lib/ector/gl/shader/include.glsl create mode 100644 src/lib/ector/gl/shader/vertex.glsl diff --git a/configure.ac b/configure.ac index a7f97c94a8..9efb77bede 100644 --- a/configure.ac +++ b/configure.ac @@ -1489,6 +1489,8 @@ EFL_LIB_START([Ector]) EFL_PLATFORM_DEPEND([ECTOR], [evil]) EFL_INTERNAL_DEPEND_PKG([ECTOR], [eina]) +EFL_INTERNAL_DEPEND_PKG([ECTOR], [emile]) +EFL_INTERNAL_DEPEND_PKG([ECTOR], [eet]) EFL_INTERNAL_DEPEND_PKG([ECTOR], [eo]) EFL_INTERNAL_DEPEND_PKG([ECTOR], [efl]) diff --git a/src/Makefile_Ector.am b/src/Makefile_Ector.am index 83d765fcd0..e404df3402 100644 --- a/src/Makefile_Ector.am +++ b/src/Makefile_Ector.am @@ -33,10 +33,21 @@ ector_eolian_files_software = \ lib/ector/software/ector_renderer_software_gradient_linear.eo ector_eolian_software_h = $(ector_eolian_files_software:%.eo=%.eo.h) +# Handle gl backend +ector_eolian_files_gl = \ + lib/ector/gl/ector_gl_surface.eo \ + lib/ector/gl/ector_gl_buffer.eo \ + lib/ector/gl/ector_gl_buffer_base.eo \ + lib/ector/gl/ector_renderer_gl_base.eo \ + lib/ector/gl/ector_renderer_gl_shape.eo \ + lib/ector/gl/ector_renderer_gl_gradient_radial.eo \ + lib/ector/gl/ector_renderer_gl_gradient_linear.eo + ector_eolian_files = \ $(ector_eolian_files_generic) \ $(ector_eolian_files_cairo) \ - $(ector_eolian_files_software) + $(ector_eolian_files_software) \ + $(ector_eolian_files_gl) ector_eolian_c = $(ector_eolian_files:%.eo=%.eo.c) ector_eolian_h = $(ector_eolian_files:%.eo=%.eo.h) @@ -63,7 +74,8 @@ lib/ector/ector_util.h \ lib/ector/ector_surface.h \ lib/ector/ector_renderer.h \ lib/ector/cairo/Ector_Cairo.h \ -lib/ector/software/Ector_Software.h +lib/ector/software/Ector_Software.h \ +lib/ector/gl/Ector_GL.h # And the generic implementation @@ -115,6 +127,28 @@ static_libs/freetype/sw_ft_raster.c \ static_libs/freetype/sw_ft_stroker.c \ $(draw_sources) +# And now the gl backend +lib_ector_libector_la_SOURCES += \ +lib/ector/gl/ector_renderer_gl_gradient_linear.c \ +lib/ector/gl/ector_renderer_gl_gradient_radial.c \ +lib/ector/gl/ector_renderer_gl_shape.c \ +lib/ector/gl/ector_renderer_gl_base.c \ +lib/ector/gl/ector_gl_buffer.c \ +lib/ector/gl/ector_gl_surface.c \ +lib/ector/gl/ector_gl_private.h \ +lib/ector/gl/shader/ector_gl_shaders.x \ +lib/ector/gl/ector_gl_shader.c + +GL_SHADERS_GEN = \ +lib/ector/gl/shader/gen_shaders.sh \ +lib/ector/gl/shader/fragment.glsl \ +lib/ector/gl/shader/vertex.glsl \ +lib/ector/gl/shader/include.glsl + +lib/ector/gl/shader/ector_gl_shaders.x: $(GL_SHADERS_GEN) + @echo " SHADERS $@" + @bash $(srcdir)/lib/ector/gl/shader/gen_shaders.sh + installed_ectorsoftwareheadersdir = $(includedir)/ector-@VMAJ@/software nodist_installed_ectorsoftwareheaders_DATA = $(ector_eolian_software_h) @@ -122,6 +156,7 @@ lib_ector_libector_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ -I$(top_builddir)/src/lib/ector \ -I$(top_builddir)/src/lib/ector/cairo \ -I$(top_builddir)/src/lib/ector/software \ +-I$(top_builddir)/src/lib/ector/gl \ -I$(top_srcdir)/src/static_libs/freetype \ -I$(top_srcdir)/src/static_libs/draw \ @ECTOR_CFLAGS@ \ @@ -175,4 +210,5 @@ static_libs/freetype/sw_ft_raster.h \ static_libs/freetype/sw_ft_stroker.h \ static_libs/freetype/sw_ft_types.h \ static_libs/draw/draw.h \ -static_libs/draw/draw_private.h +static_libs/draw/draw_private.h \ +$(GL_SHADERS_GEN) diff --git a/src/lib/ector/gl/Ector_GL.h b/src/lib/ector/gl/Ector_GL.h new file mode 100644 index 0000000000..df49421813 --- /dev/null +++ b/src/lib/ector/gl/Ector_GL.h @@ -0,0 +1,24 @@ +#ifndef ECTOR_GL_H_ +# define ECTOR_GL_H_ + +#include "Ector.h" + +#ifndef _ECTOR_GL_SURFACE_EO_CLASS_TYPE +#define _ECTOR_GL_SURFACE_EO_CLASS_TYPE + +typedef Eo Ector_Cairo_Surface; + +#endif + +typedef unsigned int GLuint; +typedef short GLshort; + +#include "gl/ector_gl_buffer.eo.h" +#include "gl/ector_gl_buffer_base.eo.h" +#include "gl/ector_gl_surface.eo.h" +#include "gl/ector_renderer_gl_base.eo.h" +#include "gl/ector_renderer_gl_shape.eo.h" +#include "gl/ector_renderer_gl_gradient_linear.eo.h" +#include "gl/ector_renderer_gl_gradient_radial.eo.h" + +#endif diff --git a/src/lib/ector/gl/ector_gl_buffer.c b/src/lib/ector/gl/ector_gl_buffer.c new file mode 100644 index 0000000000..e3732b9c74 --- /dev/null +++ b/src/lib/ector/gl/ector_gl_buffer.c @@ -0,0 +1,60 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# define EFL_BETA_API_SUPPORT +#endif + +#include +#include "Ector_GL.h" +#include "ector_private.h" +#include "ector_gl_private.h" +#include "ector_generic_buffer.eo.h" +#include "ector_gl_buffer_base.eo.h" + +typedef struct _Ector_GL_Buffer_Base_Data Ector_GL_Buffer_Base_Data; +struct _Ector_GL_Buffer_Base_Data +{ +}; + +static Ector_Buffer_Flag +_ector_gl_buffer_base_ector_generic_buffer_flags_get(Eo *obj, Ector_GL_Buffer_Base_Data *pd) +{ +} + +static Eina_Bool +_ector_gl_buffer_base_ector_generic_buffer_pixels_set(Eo *obj, Ector_GL_Buffer_Base_Data *pd, void *pixels, int width, int height, int stride, Efl_Gfx_Colorspace cspace, Eina_Bool writable, unsigned char l, unsigned char r, unsigned char t, unsigned char b) +{ +} + +static uint8_t * +_ector_gl_buffer_base_ector_generic_buffer_span_get(Eo *obj, Ector_GL_Buffer_Base_Data *pd, int x, int y, unsigned int w, Efl_Gfx_Colorspace cspace, unsigned int *length) +{ +} + +static void +_ector_gl_buffer_base_ector_generic_buffer_span_free(Eo *obj, Ector_GL_Buffer_Base_Data *pd, uint8_t *data) +{ +} + +static uint8_t * +_ector_gl_buffer_base_ector_generic_buffer_map(Eo *obj, Ector_GL_Buffer_Base_Data *pd, int *offset, unsigned int *length, Ector_Buffer_Access_Flag mode, unsigned int x, unsigned int y, unsigned int w, unsigned int h, Efl_Gfx_Colorspace cspace, unsigned int *stride) +{ +} + +static void +_ector_gl_buffer_base_ector_generic_buffer_unmap(Eo *obj, Ector_GL_Buffer_Base_Data *pd, void *data, int offset, unsigned int length) +{ +} + +static Eo_Base * +_ector_gl_buffer_eo_base_constructor(Eo *obj, void *pd) +{ +} + +static void +_ector_gl_buffer_eo_base_destructor(Eo *obj, void *pd) +{ +} + +#include "ector_gl_buffer.eo.c" +#include "ector_gl_buffer_base.eo.c" diff --git a/src/lib/ector/gl/ector_gl_buffer.eo b/src/lib/ector/gl/ector_gl_buffer.eo new file mode 100644 index 0000000000..e83fda41f1 --- /dev/null +++ b/src/lib/ector/gl/ector_gl_buffer.eo @@ -0,0 +1,9 @@ +class Ector.GL.Buffer (Eo.Base, Ector.GL.Buffer.Base) +{ + legacy_prefix: null; + data: null; + implements { + Eo.Base.constructor; + Eo.Base.destructor; + } +} diff --git a/src/lib/ector/gl/ector_gl_buffer_base.eo b/src/lib/ector/gl/ector_gl_buffer_base.eo new file mode 100644 index 0000000000..441f7814fe --- /dev/null +++ b/src/lib/ector/gl/ector_gl_buffer_base.eo @@ -0,0 +1,14 @@ +mixin Ector.GL.Buffer.Base (Ector.Generic.Buffer) +{ + [[A buffer in Ector GL is a readable & optionally writable image]] + eo_prefix: ector_gl_buffer; + legacy_prefix: null; + implements { + Ector.Generic.Buffer.flags.get; + Ector.Generic.Buffer.pixels_set; + Ector.Generic.Buffer.span_get; + Ector.Generic.Buffer.span_free; + Ector.Generic.Buffer.map; + Ector.Generic.Buffer.unmap; + } +} diff --git a/src/lib/ector/gl/ector_gl_private.h b/src/lib/ector/gl/ector_gl_private.h new file mode 100644 index 0000000000..0362e7e723 --- /dev/null +++ b/src/lib/ector/gl/ector_gl_private.h @@ -0,0 +1,69 @@ +#ifndef ECTOR_GL_PRIVATE_H_ +# define ECTOR_GL_PRIVATE_H_ + +#define SHADER_FLAG_SAM_BITSHIFT 3 +#define SHADER_FLAG_MASKSAM_BITSHIFT 6 + +typedef enum { + SHADER_FLAG_TEX = (1 << 0), + SHADER_FLAG_BGRA = (1 << 1), + SHADER_FLAG_MASK = (1 << 2), + SHADER_FLAG_SAM12 = (1 << (SHADER_FLAG_SAM_BITSHIFT + 0)), + SHADER_FLAG_SAM21 = (1 << (SHADER_FLAG_SAM_BITSHIFT + 1)), + SHADER_FLAG_SAM22 = (1 << (SHADER_FLAG_SAM_BITSHIFT + 2)), + SHADER_FLAG_MASKSAM12 = (1 << (SHADER_FLAG_MASKSAM_BITSHIFT + 0)), + SHADER_FLAG_MASKSAM21 = (1 << (SHADER_FLAG_MASKSAM_BITSHIFT + 1)), + SHADER_FLAG_MASKSAM22 = (1 << (SHADER_FLAG_MASKSAM_BITSHIFT + 2)), + SHADER_FLAG_IMG = (1 << 9), + SHADER_FLAG_BIGENDIAN = (1 << 10), + SHADER_FLAG_YUV = (1 << 11), + SHADER_FLAG_YUY2 = (1 << 12), + SHADER_FLAG_NV12 = (1 << 13), + SHADER_FLAG_YUV_709 = (1 << 14), + SHADER_FLAG_EXTERNAL = (1 << 15), + SHADER_FLAG_AFILL = (1 << 16), + SHADER_FLAG_NOMUL = (1 << 17), + SHADER_FLAG_ALPHA = (1 << 18), + SHADER_FLAG_RGB_A_PAIR = (1 << 19), +} Shader_Flag; +#define SHADER_FLAG_COUNT 20 + +#define SHAD_VERTEX 0 +#define SHAD_COLOR 1 +#define SHAD_TEXUV 2 +#define SHAD_TEXUV2 3 +#define SHAD_TEXUV3 4 +#define SHAD_TEXA 5 +#define SHAD_TEXSAM 6 +#define SHAD_MASK 7 +#define SHAD_MASKSAM 8 + +static inline void +gl_compile_link_error(GLuint target, const char *action, Eina_Bool is_shader) +{ + int loglen = 0, chars = 0; + char *logtxt; + + if (is_shader) + /* Shader info log */ + GL.glGetShaderiv(target, GL_INFO_LOG_LENGTH, &loglen); + else + /* Program info log */ + GL.glGetProgramiv(target, GL_INFO_LOG_LENGTH, &loglen); + + if (loglen > 0) + { + logtxt = calloc(loglen, sizeof(char)); + if (logtxt) + { + if (is_shader) GL.glGetShaderInfoLog(target, loglen, &chars, logtxt); + else GL.glGetProgramInfoLog(target, loglen, &chars, logtxt); + ERR("Failed to %s: %s", action, logtxt); + free(logtxt); + } + } +} + +GLuint ector_gl_shader_compile(uint64_t flags); + +#endif diff --git a/src/lib/ector/gl/ector_gl_shader.c b/src/lib/ector/gl/ector_gl_shader.c new file mode 100644 index 0000000000..acc366e692 --- /dev/null +++ b/src/lib/ector/gl/ector_gl_shader.c @@ -0,0 +1,168 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include + +#include "gl/Ector_GL.h" +#include "ector_private.h" +#include "ector_gl_private.h" + +#include "shader/ector_gl_shaders.x" + +static const char *_shader_flags[SHADER_FLAG_COUNT] = { + "TEX", + "BGRA", + "MASK", + "SAM12", + "SAM21", + "SAM22", + "MASKSAM12", + "MASKSAM21", + "MASKSAM22", + "IMG", + "BIGENDIAN", + "YUV", + "YUY2", + "NV12", + "YUV_709", + "EXTERNAL", + "AFILL", + "NOMUL", + "ALPHA", + "RGB_A_PAIR" +}; + +static Eina_Strbuf * +_ector_gl_shader_glsl_get(uint64_t flags, const char *base) +{ + Eina_Strbuf *r; + unsigned int k; + + r = eina_strbuf_new(); + for (k =0; k < SHADER_FLAG_COUNT; k++) + { + if (flags & (1 << k)) + eina_strbuf_append_printf(r, "#define SHD_%s\n", _shader_flags[k]); + } + + eina_strbuf_append(r, base); + + return r; +} + +static GLint +_ector_gl_shader_glsl_compile(GLuint s, const Eina_Strbuf *shader, const char *type) +{ + const char *str; + GLint ok = 0; + + str = eina_strbuf_string_get(shader); + + GL.glShaderSource(s, 1, &str, NULL); + GL.glCompileShader(s); + GL.glGetShaderiv(s, GL_COMPILE_STATUS, &ok); + if (!ok) + { + Eina_Strbuf *err; + + err = eina_strbuf_new(); + if (!err) goto on_error; + eina_strbuf_append_printf(err, "compile of %s shader", type); + + gl_compile_link_error(s, eina_strbuf_string_get(err), EINA_TRUE); + ERR("Abort %s:\n%s", eina_strbuf_string_get(err), str); + + eina_strbuf_free(err); + } + + on_error: + return ok; +} + +static GLint +_ector_gl_shader_glsl_link(uint64_t flags, + const Eina_Strbuf *vertex, + const Eina_Strbuf *fragment) +{ + GLuint vtx = 0, frg = 0, prg = 0; + GLint ok = 0; + + vtx = GL.glCreateShader(GL_VERTEX_SHADER); + frg = GL.glCreateShader(GL_FRAGMENT_SHADER); + + // Compiling vertex shader + ok = _ector_gl_shader_glsl_compile(vtx, vertex, "vertex"); + if (!ok) goto on_error; + + // Compile fragment shader + ok = _ector_gl_shader_glsl_compile(frg, fragment, "fragment"); + if (!ok) goto on_error; + + // Link both shader together + ok = 0; + + prg = GL.glCreateProgram(); +#ifndef GL_GLES + if ((GL.glGetProgramBinary) && (GL.glProgramParameteri)) + GL.glProgramParameteri(prg, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); +#endif + GL.glAttachShader(prg, vtx); + GL.glAttachShader(prg, frg); + + GL.glBindAttribLocation(prg, SHAD_VERTEX, "vertex"); + GL.glBindAttribLocation(prg, SHAD_COLOR, "color"); + GL.glBindAttribLocation(prg, SHAD_TEXUV, "tex_coord"); + GL.glBindAttribLocation(prg, SHAD_TEXUV2, "tex_coord2"); + GL.glBindAttribLocation(prg, SHAD_TEXUV3, "tex_coord3"); + GL.glBindAttribLocation(prg, SHAD_TEXA, "tex_coorda"); + GL.glBindAttribLocation(prg, SHAD_TEXSAM, "tex_sample"); + GL.glBindAttribLocation(prg, SHAD_MASK, "mask_coord"); + GL.glBindAttribLocation(prg, SHAD_MASKSAM, "tex_masksample"); + + GL.glLinkProgram(prg); + GL.glGetProgramiv(prg, GL_LINK_STATUS, &ok); + if (!ok) + { + gl_compile_link_error(prg, "link fragment and vertex shaders", EINA_FALSE); + ERR("Abort compile of shader (flags: %16lx)", flags); + GL.glDeleteProgram(prg); + prg = 0; + goto on_error; + } + + on_error: + if (vtx) GL.glDeleteShader(vtx); + if (frg) GL.glDeleteShader(frg); + + return prg; +} + +GLuint +ector_gl_shader_compile(uint64_t flags) +{ + Eina_Strbuf *vertex, *fragment; + GLuint shd = 0; + + vertex = _ector_gl_shader_glsl_get(flags, vertex_glsl); + fragment = _ector_gl_shader_glsl_get(flags, fragment_glsl); + if (!vertex || !fragment) goto on_error; + + shd = _ector_gl_shader_glsl_link(flags, vertex, fragment); + + on_error: + eina_strbuf_free(vertex); + eina_strbuf_free(fragment); + +#ifdef GL_GLES + GL.glReleaseShaderCompiler(); +#else + if (GL.glReleaseShaderCompiler) + GL.glReleaseShaderCompiler(); +#endif + + return shd; +} diff --git a/src/lib/ector/gl/ector_gl_surface.c b/src/lib/ector/gl/ector_gl_surface.c new file mode 100644 index 0000000000..3397e567ed --- /dev/null +++ b/src/lib/ector/gl/ector_gl_surface.c @@ -0,0 +1,383 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include + +#include "gl/Ector_GL.h" +#include "ector_private.h" +#include "ector_gl_private.h" + +typedef struct _Ector_GL_Surface_Data Ector_GL_Surface_Data; +struct _Ector_GL_Surface_Data +{ + struct { + int x, y; + } reference_point; + + Efl_Gfx_Render_Op op; +}; + +typedef struct _Ector_Shader Ector_Shader; +struct _Ector_Shader +{ + uint64_t flags; + GLuint prg; +}; + +static Eina_Hash *shader_cache = NULL; +static Eet_File *shader_file = NULL; + +static void +_shader_free(void *s) +{ + Ector_Shader *shd = s; + + GL.glDeleteProgram(shd->prg); + free(shd); +} + +static Ector_Renderer * +_ector_gl_surface_ector_generic_surface_renderer_factory_new(Eo *obj, + Ector_GL_Surface_Data *pd EINA_UNUSED, + const Eo_Class *type) +{ + if (type == ECTOR_RENDERER_GENERIC_SHAPE_MIXIN) + return eo_add(ECTOR_RENDERER_GL_SHAPE_CLASS, NULL, + ector_renderer_surface_set(obj)); + else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN) + return eo_add(ECTOR_RENDERER_GL_GRADIENT_LINEAR_CLASS, NULL, + ector_renderer_surface_set(obj)); + else if (type == ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN) + return eo_add(ECTOR_RENDERER_GL_GRADIENT_RADIAL_CLASS, NULL, + ector_renderer_surface_set(obj)); + + ERR("Couldn't find class for type: %s\n", eo_class_name_get(type)); + return NULL; +} + +static void +_ector_gl_surface_ector_generic_surface_reference_point_set(Eo *obj EINA_UNUSED, + Ector_GL_Surface_Data *pd, + int x, int y) +{ + pd->reference_point.x = x; + pd->reference_point.y = y; +} + +#define VERTEX_CNT 3 +#define COLOR_CNT 4 + +static Eina_Bool +_ector_gl_surface_push(Eo *obj, + Ector_GL_Surface_Data *pd EINA_UNUSED, + uint64_t flags, GLshort *vertex, unsigned int vertex_count, unsigned int mul_col) +{ + unsigned int prog; + + eo_do(obj, prog = ector_gl_surface_shader_get(flags)); + + // FIXME: Not using mapp/unmap buffer yet, nor any pipe + // FIXME: Move some of the state change to surface drawing start ? + GL.glUseProgram(prog); + GL.glDisable(GL_TEXTURE_2D); + GL.glDisable(GL_SCISSOR_TEST); + GL.glVertexAttribPointer(SHAD_VERTEX, VERTEX_CNT, GL_SHORT, GL_FALSE, 0, vertex); + GL.glEnableVertexAttribArray(SHAD_COLOR); + GL.glVertexAttribPointer(SHAD_COLOR, COLOR_CNT, GL_UNSIGNED_BYTE, GL_TRUE, 0, &mul_col); + GL.glDrawArrays(GL_TRIANGLES, 0, vertex_count); + + return EINA_TRUE; +} + +static Eina_Bool +_ector_gl_surface_state_define(Eo *obj EINA_UNUSED, Ector_GL_Surface_Data *pd, Efl_Gfx_Render_Op op, Eina_Array *clips) +{ + if (pd->op == op) return EINA_TRUE; + + // FIXME: no pipe yet, so we can just change the mode right away + // Get & apply matrix transformation to + switch (op) + { + case EFL_GFX_RENDER_OP_BLEND: /**< default op: d = d*(1-sa) + s */ + GL.glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + GL.glEnable(GL_BLEND); + break; + case EFL_GFX_RENDER_OP_COPY: /**< d = s */ + // just disable blend mode. no need to set blend func + GL.glDisable(GL_BLEND); + break; + case EFL_GFX_RENDER_OP_LAST: + default: + return EINA_FALSE; + } + + pd->op = op; + + //FIXME: we should not ignore clipping, but that can last for later + (void) clips; + + return EINA_TRUE; +} + +static void +_ector_gl_shader_textures_bind(Ector_Shader *p) +{ + struct { + const char *name; + int enabled; + } textures[] = { + { "tex", 0 }, + { "texm", 0 }, + { "texa", 0 }, + { "texu", 0 }, + { "texv", 0 }, + { "texuv", 0 }, + { NULL, 0 } + }; + Eina_Bool hastex = 0; + int tex_count = 0; + GLint loc; + int i; + + if (!p) return; + + if ((p->flags & SHADER_FLAG_TEX) != 0) + { + textures[0].enabled = 1; + hastex = 1; + } + if ((p->flags & SHADER_FLAG_MASK) != 0) + { + textures[1].enabled = 1; + hastex = 1; + } + if ((p->flags & SHADER_FLAG_RGB_A_PAIR) != 0) + { + textures[2].enabled = 1; + hastex = 1; + } + if (p->flags & SHADER_FLAG_YUV) + { + textures[3].enabled = 1; + textures[4].enabled = 1; + hastex = 1; + } + else if ((p->flags & SHADER_FLAG_NV12) || (p->flags & SHADER_FLAG_YUY2)) + { + textures[5].enabled = 1; + hastex = 1; + } + + if (hastex) + { + GL.glUseProgram(p->prg); // is this necessary?? + for (i = 0; textures[i].name; i++) + { + if (!textures[i].enabled) continue; + loc = GL.glGetUniformLocation(p->prg, textures[i].name); + if (loc < 0) + { + ERR("Couldn't find uniform '%s' (shader: %16lx)", + textures[i].name, p->flags); + } + GL.glUniform1i(loc, tex_count++); + } + } +} + +static Ector_Shader * +_ector_gl_shader_load(uint64_t flags) +{ + Eina_Strbuf *buf; + Ector_Shader *r = NULL; + void *data; + int *formats = NULL; + int length = 0, num = 0; + GLuint prg; + GLint ok = 0, vtx = GL_NONE, frg = GL_NONE; + Eina_Bool direct = 1; + + buf = eina_strbuf_new(); + if (!buf) return NULL; + + eina_strbuf_append_printf(buf, "ector/shader/%16lx", flags); + + data = (void*) eet_read_direct(shader_file, eina_strbuf_string_get(buf), &length); + if (!data) + { + data = eet_read(shader_file, eina_strbuf_string_get(buf), &length); + direct = 0; + } + if ((!data) || (length <= 0)) goto on_error; + + GL.glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &num); + if (num <= 0) goto on_error; + + formats = calloc(num, sizeof(int)); + if (!formats) goto on_error; + + GL.glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, formats); + if (!formats[0]) goto on_error; + + prg = GL.glCreateProgram(); + // TODO: invalid rendering error occurs when attempting to use a + // glProgramBinary. in order to render correctly we should create a dummy + // vertex shader. + vtx = GL.glCreateShader(GL_VERTEX_SHADER); + GL.glAttachShader(prg, vtx); + frg = GL.glCreateShader(GL_FRAGMENT_SHADER); + GL.glAttachShader(prg, frg); + + GL.glProgramBinary(prg, formats[0], data, length); + + GL.glBindAttribLocation(prg, SHAD_VERTEX, "vertex"); + GL.glBindAttribLocation(prg, SHAD_COLOR, "color"); + GL.glBindAttribLocation(prg, SHAD_TEXUV, "tex_coord"); + GL.glBindAttribLocation(prg, SHAD_TEXUV2, "tex_coord2"); + GL.glBindAttribLocation(prg, SHAD_TEXUV3, "tex_coord3"); + GL.glBindAttribLocation(prg, SHAD_TEXA, "tex_coorda"); + GL.glBindAttribLocation(prg, SHAD_TEXSAM, "tex_sample"); + GL.glBindAttribLocation(prg, SHAD_MASK, "mask_coord"); + GL.glBindAttribLocation(prg, SHAD_MASKSAM, "tex_masksample"); + + GL.glGetProgramiv(prg, GL_LINK_STATUS, &ok); + if (!ok) + { + gl_compile_link_error(prg, "load a program object", EINA_FALSE); + ERR("Abort load of program (%s)", eina_strbuf_string_get(buf)); + GL.glDeleteProgram(prg); + goto on_error; + } + + r = malloc(sizeof (Ector_Shader)); + r->prg = prg; + r->flags = flags; + + _ector_gl_shader_textures_bind(r); + + on_error: + if (vtx) GL.glDeleteShader(vtx); + if (frg) GL.glDeleteShader(frg); + free(formats); + + if (!direct) free(data); + eina_strbuf_free(buf); + return r; +} + +static unsigned int +_ector_gl_surface_shader_get(Eo *obj EINA_UNUSED, Ector_GL_Surface_Data *pd EINA_UNUSED, uint64_t flags) +{ + Ector_Shader *shd; + Eina_Strbuf *buf = NULL; + void *data = NULL; + int length = 0, size = 0; + GLenum format; + GLuint prg; + + shd = eina_hash_find(shader_cache, &flags); + if (shd) return shd->prg; + + shd = _ector_gl_shader_load(flags); + if (shd) return shd->prg; + + prg = ector_gl_shader_compile(flags); + if (prg <= 0) return -1; + + GL.glGetProgramiv(prg, GL_PROGRAM_BINARY_LENGTH, &length); + if (length <= 0) return prg; + + if (GL.glGetProgramBinary) + { + data = malloc(length); + if (!data) return prg; + + GL.glGetProgramBinary(prg, length, &size, &format, data); + if (length != size) goto on_error; + } + + shd = malloc(sizeof (Ector_Shader)); + if (!shd) goto on_error; + + shd->prg = prg; + shd->flags = flags; + + // Saving the shader in the memory cache + eina_hash_direct_add(shader_cache, &shd->flags, shd); + + // Saving binary shader in the cache file. + if (GL.glGetProgramBinary) + { + buf = eina_strbuf_new(); + eina_strbuf_append_printf(buf, "ector/shader/%16lx", flags); + + eet_write(shader_file, eina_strbuf_string_get(buf), data, length, 1); + + eina_strbuf_free(buf); + } + + on_error: + free(data); + + return prg; +} + +static void +_ector_gl_surface_eo_base_destructor(Eo *obj, Ector_GL_Surface_Data *pd EINA_UNUSED) +{ + eo_do_super(obj, ECTOR_GL_SURFACE_CLASS, eo_destructor()); + + eina_hash_free(shader_cache); + shader_cache = NULL; + eet_close(shader_file); + shader_file = NULL; +} + +static Eo_Base * +_ector_gl_surface_eo_base_constructor(Eo *obj, Ector_GL_Surface_Data *pd EINA_UNUSED) +{ + Eina_Strbuf *file_path = NULL; + + eo_do_super(obj, ECTOR_GL_SURFACE_CLASS, obj = eo_constructor()); + if (!obj) return NULL; + + if (shader_cache) return obj; + + // Only initialize things once + shader_cache = eina_hash_int64_new(_shader_free); + + /* glsym_glProgramBinary = _ector_gl_symbol_get(obj, "glProgramBinary"); */ + /* glsym_glGetProgramBinary = _ector_gl_symbol_get(obj, "glGetProgramBinary"); */ + /* glsym_glProgramParameteri = _ector_gl_symbol_get(obj, "glProgramParameteri"); */ + /* glsym_glReleaseShaderCompiler = _ector_gl_symbol_get(obj, "glReleaseShaderCompiler"); */ + + if (GL.glProgramBinary && GL.glGetProgramBinary) + { + file_path = eina_strbuf_new(); + if (eina_environment_home_get()) + eina_strbuf_append(file_path, eina_environment_home_get()); + else + eina_strbuf_append(file_path, eina_environment_tmp_get()); + eina_strbuf_append_printf(file_path, "%c.cache", EINA_PATH_SEP_C); + // FIXME: test and create path if necessary + eina_strbuf_append_printf(file_path, "%cector", EINA_PATH_SEP_C); + eina_strbuf_append_printf(file_path, "%cector-shader-%i.%i.eet", + EINA_PATH_SEP_C, EFL_VERSION_MAJOR, EFL_VERSION_MINOR); + shader_file = eet_open(eina_strbuf_string_get(file_path), EET_FILE_MODE_READ_WRITE); + } + if (!shader_file) + { + ERR("Unable to create '%s' ector binary shader file.", eina_strbuf_string_get(file_path)); + GL.glProgramBinary = NULL; + } + eina_strbuf_free(file_path); + + return obj; +} + +#include "ector_gl_surface.eo.c" diff --git a/src/lib/ector/gl/ector_gl_surface.eo b/src/lib/ector/gl/ector_gl_surface.eo new file mode 100644 index 0000000000..31e6657975 --- /dev/null +++ b/src/lib/ector/gl/ector_gl_surface.eo @@ -0,0 +1,35 @@ +class Ector.GL.Surface (Ector.GL.Buffer, Ector.Generic.Surface) +{ + eo_prefix: ector_gl_surface; + legacy_prefix: null; + methods { + shader_get { + return: uint; + params { + @in flags: uint64_t; + } + } + push { + return: bool; + params { + @in flags: uint64_t; + @in vertex: GLshort *; + @in vertex_count: uint; + @in mul_col: uint; + } + } + state_define { + return: bool; + params { + @in op: Efl.Gfx.Render_Op; + @in clips: array *; [[array of @Eina.Rectangle clip]] + } + } + } + implements { + Ector.Generic.Surface.renderer_factory_new; + Ector.Generic.Surface.reference_point.set; + Eo.Base.destructor; + Eo.Base.constructor; + } +} diff --git a/src/lib/ector/gl/ector_renderer_gl_base.c b/src/lib/ector/gl/ector_renderer_gl_base.c new file mode 100644 index 0000000000..a659d3dfb6 --- /dev/null +++ b/src/lib/ector/gl/ector_renderer_gl_base.c @@ -0,0 +1,56 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "gl/Ector_GL.h" +#include "ector_private.h" +#include "ector_gl_private.h" + +typedef struct _Ector_Renderer_GL_Base_Data Ector_Renderer_GL_Base_Data; +struct _Ector_Renderer_GL_Base_Data +{ + Ector_Renderer_Generic_Base_Data *base; +}; + +static Eina_Bool +_ector_renderer_gl_base_ector_renderer_generic_base_prepare(Eo *obj EINA_UNUSED, + Ector_Renderer_GL_Base_Data *pd EINA_UNUSED) +{ + return EINA_TRUE; +} + +static Eina_Bool +_ector_renderer_gl_base_ector_renderer_generic_base_draw(Eo *obj EINA_UNUSED, + Ector_Renderer_GL_Base_Data *pd, + Efl_Gfx_Render_Op op, + Eina_Array *clips, + unsigned int mul_col EINA_UNUSED) +{ + Eina_Bool r; + + eo_do(pd->base->surface, + r = ector_gl_surface_state_define(op, clips)); + + return r; +} + +static Eo_Base * +_ector_renderer_gl_base_eo_base_constructor(Eo *obj, Ector_Renderer_GL_Base_Data *pd) +{ + eo_do_super(obj, ECTOR_RENDERER_GL_BASE_CLASS, obj = eo_constructor()); + if (!obj) return NULL; + + pd->base = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_BASE_CLASS, obj); + return obj; +} + +static void +_ector_renderer_gl_base_eo_base_destructor(Eo *obj, Ector_Renderer_GL_Base_Data *pd) +{ + eo_data_xunref(obj, pd->base, obj); +} + +#include "ector_renderer_gl_base.eo.c" diff --git a/src/lib/ector/gl/ector_renderer_gl_base.eo b/src/lib/ector/gl/ector_renderer_gl_base.eo new file mode 100644 index 0000000000..0bbcd56a32 --- /dev/null +++ b/src/lib/ector/gl/ector_renderer_gl_base.eo @@ -0,0 +1,22 @@ +abstract Ector.Renderer.GL.Base (Ector.Renderer.Generic.Base) +{ + legacy_prefix: null; + methods { + fill { + return: bool; + params { + @in flags: uint64_t; + @in vertex: GLshort*; + @in vertex_count: uint; + @in mul_col: uint; + } + } + } + implements { + @virtual .fill; + Ector.Renderer.Generic.Base.prepare; + Ector.Renderer.Generic.Base.draw; + Eo.Base.constructor; + Eo.Base.destructor; + } +} diff --git a/src/lib/ector/gl/ector_renderer_gl_gradient_linear.c b/src/lib/ector/gl/ector_renderer_gl_gradient_linear.c new file mode 100644 index 0000000000..6920ac1ad1 --- /dev/null +++ b/src/lib/ector/gl/ector_renderer_gl_gradient_linear.c @@ -0,0 +1,115 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "gl/Ector_GL.h" +#include "ector_private.h" +#include "ector_gl_private.h" + +typedef struct _Ector_Renderer_GL_Gradient_Linear_Data Ector_Renderer_GL_Gradient_Linear_Data; +struct _Ector_Renderer_GL_Gradient_Linear_Data +{ + Ector_Renderer_Generic_Gradient_Linear_Data *linear; + Ector_Renderer_Generic_Gradient_Data *gradient; + Ector_Renderer_Generic_Base_Data *base; +}; + +static Eina_Bool +_ector_renderer_gl_gradient_linear_ector_renderer_generic_base_prepare(Eo *obj, + Ector_Renderer_GL_Gradient_Linear_Data *pd) +{ + // FIXME: prepare something + (void) obj; + (void) pd; + + return EINA_TRUE; +} + +static Eina_Bool +_ector_renderer_gl_gradient_linear_ector_renderer_generic_base_draw(Eo *obj, Ector_Renderer_GL_Gradient_Linear_Data *pd, Efl_Gfx_Render_Op op, Eina_Array *clips, unsigned int mul_col) +{ + eo_do_super(obj, ECTOR_RENDERER_GL_GRADIENT_LINEAR_CLASS, + ector_renderer_draw(op, clips, mul_col)); + + // FIXME: draw something ! + (void) pd; + + return EINA_TRUE; +} + +static void +_ector_renderer_gl_gradient_linear_ector_renderer_generic_base_bounds_get(Eo *obj EINA_UNUSED, + Ector_Renderer_GL_Gradient_Linear_Data *pd, + Eina_Rectangle *r) +{ + EINA_RECTANGLE_SET(r, + pd->base->origin.x + pd->linear->start.x, + pd->base->origin.y + pd->linear->start.y, + pd->linear->end.x - pd->linear->start.x, + pd->linear->end.y - pd->linear->start.y); +} + +static Eina_Bool +_ector_renderer_gl_gradient_linear_ector_renderer_gl_base_fill(Eo *obj, Ector_Renderer_GL_Gradient_Linear_Data *pd, uint64_t flags, GLshort *vertex, unsigned int vertex_count, unsigned int mul_col) +{ + // FIXME: The idea here is to select the right shader and push the needed parameter for it + // along with the other value + (void) obj; + (void) pd; + (void) flags; + (void) vertex; + (void) vertex_count; + (void) mul_col; + + return EINA_TRUE; +} + +static Eo_Base * +_ector_renderer_gl_gradient_linear_eo_base_constructor(Eo *obj, Ector_Renderer_GL_Gradient_Linear_Data *pd) +{ + eo_do_super(obj, ECTOR_RENDERER_GL_GRADIENT_LINEAR_CLASS, obj = eo_constructor()); + + if (!obj) return NULL; + + pd->base = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_BASE_CLASS, obj); + pd->linear = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_LINEAR_MIXIN, obj); + pd->gradient = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_MIXIN, obj); + + return obj; +} + +static void +_ector_renderer_gl_gradient_linear_eo_base_destructor(Eo *obj, Ector_Renderer_GL_Gradient_Linear_Data *pd) +{ + eo_data_xunref(obj, pd->base, obj); + eo_data_xunref(obj, pd->linear, obj); + eo_data_xunref(obj, pd->gradient, obj); +} + +static void +_ector_renderer_gl_gradient_linear_efl_gfx_gradient_base_stop_set(Eo *obj, Ector_Renderer_GL_Gradient_Linear_Data *pd EINA_UNUSED, const Efl_Gfx_Gradient_Stop *colors, unsigned int length) +{ + eo_do_super(obj, ECTOR_RENDERER_GL_GRADIENT_LINEAR_CLASS, + efl_gfx_gradient_stop_set(colors, length)); +} + +static unsigned int +_ector_renderer_gl_gradient_linear_ector_renderer_generic_base_crc_get(Eo *obj, Ector_Renderer_GL_Gradient_Linear_Data *pd) +{ + unsigned int crc; + + eo_do_super(obj, ECTOR_RENDERER_GL_GRADIENT_LINEAR_CLASS, + crc = ector_renderer_crc_get()); + + crc = eina_crc((void*) pd->gradient->s, sizeof (Efl_Gfx_Gradient_Spread), crc, EINA_FALSE); + if (pd->gradient->colors_count) + crc = eina_crc((void*) pd->gradient->colors, sizeof (Efl_Gfx_Gradient_Stop) * pd->gradient->colors_count, crc, EINA_FALSE); + crc = eina_crc((void*) pd->linear, sizeof (Ector_Renderer_Generic_Gradient_Linear_Data), crc, EINA_FALSE); + + return crc; +} + +#include "ector_renderer_gl_gradient_linear.eo.c" diff --git a/src/lib/ector/gl/ector_renderer_gl_gradient_linear.eo b/src/lib/ector/gl/ector_renderer_gl_gradient_linear.eo new file mode 100644 index 0000000000..4ba0d5b3a6 --- /dev/null +++ b/src/lib/ector/gl/ector_renderer_gl_gradient_linear.eo @@ -0,0 +1,15 @@ +class Ector.Renderer.GL.Gradient_Linear (Ector.Renderer.GL.Base, Ector.Renderer.Generic.Gradient, Ector.Renderer.Generic.Gradient_Linear) +{ + eo_prefix: ector_renderer_gl_gradient_linear; + legacy_prefix: null; + implements { + Ector.Renderer.Generic.Base.prepare; + Ector.Renderer.Generic.Base.draw; + Ector.Renderer.Generic.Base.bounds_get; + Ector.Renderer.Generic.Base.crc.get; + Ector.Renderer.GL.Base.fill; + Eo.Base.constructor; + Eo.Base.destructor; + Efl.Gfx.Gradient.Base.stop.set; + } +} diff --git a/src/lib/ector/gl/ector_renderer_gl_gradient_radial.c b/src/lib/ector/gl/ector_renderer_gl_gradient_radial.c new file mode 100644 index 0000000000..9d7d65c886 --- /dev/null +++ b/src/lib/ector/gl/ector_renderer_gl_gradient_radial.c @@ -0,0 +1,113 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "gl/Ector_GL.h" +#include "ector_private.h" +#include "ector_gl_private.h" + +typedef struct _Ector_Renderer_GL_Gradient_Radial_Data Ector_Renderer_GL_Gradient_Radial_Data; +struct _Ector_Renderer_GL_Gradient_Radial_Data +{ + Ector_Renderer_Generic_Gradient_Radial_Data *radial; + Ector_Renderer_Generic_Gradient_Data *gradient; + Ector_Renderer_Generic_Base_Data *base; +}; + +static Eina_Bool +_ector_renderer_gl_gradient_radial_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_GL_Gradient_Radial_Data *pd) +{ + // FIXME: prepare something + (void) obj; + (void) pd; + + return EINA_TRUE; +} + +static Eina_Bool +_ector_renderer_gl_gradient_radial_ector_renderer_generic_base_draw(Eo *obj, Ector_Renderer_GL_Gradient_Radial_Data *pd, Efl_Gfx_Render_Op op, Eina_Array *clips, unsigned int mul_col) +{ + eo_do_super(obj, ECTOR_RENDERER_GL_GRADIENT_RADIAL_CLASS, + ector_renderer_draw(op, clips, mul_col)); + + // FIXME: draw something ! + (void) pd; + + return EINA_TRUE; +} + +static Eina_Bool +_ector_renderer_gl_gradient_radial_ector_renderer_gl_base_fill(Eo *obj, Ector_Renderer_GL_Gradient_Radial_Data *pd, uint64_t flags, GLshort *vertex, unsigned int vertex_count, unsigned int mul_col) +{ + // FIXME: The idea here is to select the right shader and push the needed parameter for it + // along with the other value + (void) obj; + (void) pd; + (void) flags; + (void) vertex; + (void) vertex_count; + (void) mul_col; + + return EINA_TRUE; +} + +static void +_ector_renderer_gl_gradient_radial_ector_renderer_generic_base_bounds_get(Eo *obj EINA_UNUSED, + Ector_Renderer_GL_Gradient_Radial_Data *pd, + Eina_Rectangle *r) +{ + EINA_RECTANGLE_SET(r, + pd->base->origin.x + pd->radial->radial.x - pd->radial->radius, + pd->base->origin.y + pd->radial->radial.y - pd->radial->radius, + pd->radial->radius * 2, pd->radial->radius * 2 ); +} + +static unsigned int +_ector_renderer_gl_gradient_radial_ector_renderer_generic_base_crc_get(Eo *obj, Ector_Renderer_GL_Gradient_Radial_Data *pd) +{ + unsigned int crc; + + eo_do_super(obj, ECTOR_RENDERER_GL_GRADIENT_RADIAL_CLASS, + crc = ector_renderer_crc_get()); + + crc = eina_crc((void*) pd->gradient->s, sizeof (Efl_Gfx_Gradient_Spread), crc, EINA_FALSE); + if (pd->gradient->colors_count) + crc = eina_crc((void*) pd->gradient->colors, sizeof (Efl_Gfx_Gradient_Stop) * pd->gradient->colors_count, crc, EINA_FALSE); + crc = eina_crc((void*) pd->radial, sizeof (Ector_Renderer_Generic_Gradient_Radial_Data), crc, EINA_FALSE); + + return crc; +} + +static Eo_Base * +_ector_renderer_gl_gradient_radial_eo_base_constructor(Eo *obj, Ector_Renderer_GL_Gradient_Radial_Data *pd) +{ + eo_do_super(obj, ECTOR_RENDERER_GL_GRADIENT_RADIAL_CLASS, obj = eo_constructor()); + + if (!obj) return NULL; + + pd->base = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_BASE_CLASS, obj); + pd->radial = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_RADIAL_MIXIN, obj); + pd->gradient = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_GRADIENT_MIXIN, obj); + + return obj; +} + +static void +_ector_renderer_gl_gradient_radial_eo_base_destructor(Eo *obj, Ector_Renderer_GL_Gradient_Radial_Data *pd) +{ + eo_data_xunref(obj, pd->base, obj); + eo_data_xunref(obj, pd->radial, obj); + eo_data_xunref(obj, pd->gradient, obj); +} + +static void +_ector_renderer_gl_gradient_radial_efl_gfx_gradient_base_stop_set(Eo *obj, Ector_Renderer_GL_Gradient_Radial_Data *pd EINA_UNUSED, const Efl_Gfx_Gradient_Stop *colors, unsigned int length) +{ + eo_do_super(obj, ECTOR_RENDERER_GL_GRADIENT_RADIAL_CLASS, + efl_gfx_gradient_stop_set(colors, length)); +} + +#include "ector_renderer_gl_gradient_radial.eo.c" diff --git a/src/lib/ector/gl/ector_renderer_gl_gradient_radial.eo b/src/lib/ector/gl/ector_renderer_gl_gradient_radial.eo new file mode 100644 index 0000000000..c1c7a81440 --- /dev/null +++ b/src/lib/ector/gl/ector_renderer_gl_gradient_radial.eo @@ -0,0 +1,15 @@ +class Ector.Renderer.GL.Gradient_Radial (Ector.Renderer.GL.Base, Ector.Renderer.Generic.Gradient, Ector.Renderer.Generic.Gradient_Radial) +{ + eo_prefix: ector_renderer_gl_gradient_radial; + legacy_prefix: null; + implements { + Ector.Renderer.Generic.Base.prepare; + Ector.Renderer.Generic.Base.draw; + Ector.Renderer.Generic.Base.bounds_get; + Ector.Renderer.Generic.Base.crc.get; + Ector.Renderer.GL.Base.fill; + Eo.Base.constructor; + Eo.Base.destructor; + Efl.Gfx.Gradient.Base.stop.set; + } +} diff --git a/src/lib/ector/gl/ector_renderer_gl_shape.c b/src/lib/ector/gl/ector_renderer_gl_shape.c new file mode 100644 index 0000000000..bf69e0b42b --- /dev/null +++ b/src/lib/ector/gl/ector_renderer_gl_shape.c @@ -0,0 +1,170 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "gl/Ector_GL.h" +#include "ector_private.h" +#include "ector_gl_private.h" + +typedef struct _Ector_Renderer_GL_Shape_Data Ector_Renderer_GL_Shape_Data; +struct _Ector_Renderer_GL_Shape_Data +{ + Efl_Gfx_Shape_Public *public_shape; + + Ector_Renderer_Generic_Shape_Data *shape; + Ector_Renderer_Generic_Base_Data *base; + + GLshort *vertex; +}; + +static Eina_Bool +_ector_renderer_gl_shape_path_changed(void *data, Eo *obj EINA_UNUSED, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Ector_Renderer_GL_Shape_Data *pd = data; + + free(pd->vertex); + pd->vertex = NULL; + + return EINA_TRUE; +} + +static Eina_Bool +_ector_renderer_gl_shape_ector_renderer_generic_base_prepare(Eo *obj, Ector_Renderer_GL_Shape_Data *pd) +{ + Eina_Rectangle bounding_box; + Eina_Bool r; + + if (pd->vertex) return EINA_TRUE; + + eo_do_super(obj, ECTOR_RENDERER_GL_SHAPE_CLASS, r = ector_renderer_prepare()); + + eo_do(obj, ector_renderer_bounds_get(&bounding_box)); + + pd->vertex = malloc(sizeof (GLshort) * 6 * 3); + + // Pushing 2 triangles + pd->vertex[0] = bounding_box.x; + pd->vertex[1] = bounding_box.y; + pd->vertex[2] = 0; + pd->vertex[3] = bounding_box.x + bounding_box.w; + pd->vertex[4] = bounding_box.y; + pd->vertex[5] = 0; + pd->vertex[6] = bounding_box.x; + pd->vertex[7] = bounding_box.y + bounding_box.h; + pd->vertex[8] = 0; + + pd->vertex[9] = bounding_box.x; + pd->vertex[10] = bounding_box.y + bounding_box.h; + pd->vertex[11] = 0; + pd->vertex[12] = bounding_box.x + bounding_box.w; + pd->vertex[13] = bounding_box.y + bounding_box.h; + pd->vertex[14] = 0; + pd->vertex[15] = bounding_box.x + bounding_box.w; + pd->vertex[16] = bounding_box.y; + pd->vertex[17] = 0; + + return r; +} + +static Eina_Bool +_ector_renderer_gl_shape_ector_renderer_generic_base_draw(Eo *obj, Ector_Renderer_GL_Shape_Data *pd, Efl_Gfx_Render_Op op, Eina_Array *clips, unsigned int mul_col) +{ + uint64_t flags = 0; + + eo_do_super(obj, ECTOR_RENDERER_GL_SHAPE_CLASS, ector_renderer_draw(op, clips, mul_col)); + + // FIXME: adjust flags content correctly + // FIXME: should not ignore clips (idea is that the geometry will be cliped here and the + // context will just look up clips for match with current pipe to render)... + + if (pd->shape->fill) + { + eo_do(pd->shape->fill, ector_renderer_gl_base_fill(flags, pd->vertex, 6, mul_col)); + } + else + { + eo_do(pd->base->surface, + ector_gl_surface_push(flags, pd->vertex, 6, mul_col)); + } + + return EINA_TRUE; +} + +static Eina_Bool +_ector_renderer_gl_shape_ector_renderer_gl_base_fill(Eo *obj EINA_UNUSED, + Ector_Renderer_GL_Shape_Data *pd EINA_UNUSED, + uint64_t flags EINA_UNUSED, + GLshort *vertex EINA_UNUSED, + unsigned int vertex_count EINA_UNUSED, + unsigned int mul_col EINA_UNUSED) +{ + // FIXME: let's find out how to fill a shape with a shape later. + // I need to read SVG specification and see what to do here. + ERR("fill with shape not implemented\n"); + return EINA_FALSE; +} + +static void +_ector_renderer_gl_shape_ector_renderer_generic_base_bounds_get(Eo *obj, Ector_Renderer_GL_Shape_Data *pd, Eina_Rectangle *r) +{ + eo_do(obj, efl_gfx_shape_bounds_get(r)); + + r->x += pd->base->origin.x; + r->y += pd->base->origin.y; +} + +static unsigned int +_ector_renderer_gl_shape_ector_renderer_generic_base_crc_get(Eo *obj, Ector_Renderer_GL_Shape_Data *pd) +{ + unsigned int crc; + + eo_do_super(obj, ECTOR_RENDERER_GL_SHAPE_CLASS, + crc = ector_renderer_crc_get()); + + // This code should be shared with other implementation + crc = eina_crc((void*) &pd->shape->stroke.marker, sizeof (pd->shape->stroke.marker), crc, EINA_FALSE); + crc = eina_crc((void*) &pd->public_shape->stroke.scale, sizeof (pd->public_shape->stroke.scale) * 3, crc, EINA_FALSE); // scale, width, centered + crc = eina_crc((void*) &pd->public_shape->stroke.color, sizeof (pd->public_shape->stroke.color), crc, EINA_FALSE); + crc = eina_crc((void*) &pd->public_shape->stroke.cap, sizeof (pd->public_shape->stroke.cap), crc, EINA_FALSE); + crc = eina_crc((void*) &pd->public_shape->stroke.join, sizeof (pd->public_shape->stroke.join), crc, EINA_FALSE); + + if (pd->shape->fill) crc = _renderer_crc_get(pd->shape->fill, crc); + if (pd->shape->stroke.fill) crc = _renderer_crc_get(pd->shape->stroke.fill, crc); + if (pd->shape->stroke.marker) crc = _renderer_crc_get(pd->shape->stroke.marker, crc); + if (pd->public_shape->stroke.dash_length) + { + crc = eina_crc((void*) pd->public_shape->stroke.dash, sizeof (Efl_Gfx_Dash) * pd->public_shape->stroke.dash_length, crc, EINA_FALSE); + } + + return crc; +} + +static Eo_Base * +_ector_renderer_gl_shape_eo_base_constructor(Eo *obj, Ector_Renderer_GL_Shape_Data *pd) +{ + eo_do_super(obj, ECTOR_RENDERER_GL_SHAPE_CLASS, obj = eo_constructor()); + + if (!obj) return NULL; + + pd->public_shape = eo_data_xref(obj, EFL_GFX_SHAPE_MIXIN, obj); + pd->shape = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_SHAPE_MIXIN, obj); + pd->base = eo_data_xref(obj, ECTOR_RENDERER_GENERIC_BASE_CLASS, obj); + + eo_do(obj, + eo_event_callback_add(EFL_GFX_PATH_CHANGED, _ector_renderer_gl_shape_path_changed, pd)); + + return obj; +} + +static void +_ector_renderer_gl_shape_eo_base_destructor(Eo *obj, Ector_Renderer_GL_Shape_Data *pd) +{ + eo_data_xunref(obj, pd->shape, obj); + eo_data_xunref(obj, pd->base, obj); + eo_data_xunref(obj, pd->public_shape, obj); +} + +#include "ector_renderer_gl_shape.eo.c" diff --git a/src/lib/ector/gl/ector_renderer_gl_shape.eo b/src/lib/ector/gl/ector_renderer_gl_shape.eo new file mode 100644 index 0000000000..46d6a5e23b --- /dev/null +++ b/src/lib/ector/gl/ector_renderer_gl_shape.eo @@ -0,0 +1,14 @@ +class Ector.Renderer.GL.Shape (Ector.Renderer.GL.Base, Ector.Renderer.Generic.Shape) +{ + eo_prefix: ector_renderer_gl_shape; + legacy_prefix: null; + implements { + Ector.Renderer.Generic.Base.prepare; + Ector.Renderer.Generic.Base.draw; + Ector.Renderer.Generic.Base.bounds_get; + Ector.Renderer.Generic.Base.crc.get; + Ector.Renderer.GL.Base.fill; + Eo.Base.constructor; + Eo.Base.destructor; + } +} diff --git a/src/lib/ector/gl/shader/.gitignore b/src/lib/ector/gl/shader/.gitignore new file mode 100644 index 0000000000..0074827b13 --- /dev/null +++ b/src/lib/ector/gl/shader/.gitignore @@ -0,0 +1 @@ +*.shd diff --git a/src/lib/ector/gl/shader/ector_gl_shaders.x b/src/lib/ector/gl/shader/ector_gl_shaders.x new file mode 100644 index 0000000000..19120e26c3 --- /dev/null +++ b/src/lib/ector/gl/shader/ector_gl_shaders.x @@ -0,0 +1,285 @@ +/* DO NOT MODIFY THIS FILE AS IT IS AUTO-GENERATED */ +/* IF IT IS CHANGED PLEASE COMMIT THE CHANGES */ + +static const char fragment_glsl[] = + "/* General-purpose fragment shader for all operations in Evas.\n" + " * This file can either be used directly by evas at runtime to\n" + " * generate its shaders with the appropriate #defines, or passed\n" + " * through cpp first (in which case the precision must be manually added).\n" + " */\n" + "#ifdef GL_ES\n" + "# ifdef GL_FRAGMENT_PRECISION_HIGH\n" + "precision highp float;\n" + "# else\n" + "precision mediump float;\n" + "# endif\n" + "# ifdef SHD_EXTERNAL\n" + "extension GL_OES_EGL_image_external : require\n" + "# define SAMPLER_EXTERNAL_OES samplerExternalOES\n" + "# endif\n" + "#else\n" + "# define SAMPLER_EXTERNAL_OES sampler2D\n" + "#endif\n" + "#ifndef SHD_NOMUL\n" + "varying vec4 col;\n" + "#endif\n" + "#ifdef SHD_EXTERNAL\n" + "uniform SAMPLER_EXTERNAL_OES tex;\n" + "varying vec2 tex_c;\n" + "#elif defined(SHD_TEX)\n" + "uniform sampler2D tex;\n" + "varying vec2 tex_c;\n" + "#endif\n" + "#if defined(SHD_NV12) || defined(SHD_YUY2)\n" + "uniform sampler2D texuv;\n" + "varying vec2 tex_c2;\n" + "#endif\n" + "#if defined(SHD_YUV)\n" + "uniform sampler2D texu;\n" + "uniform sampler2D texv;\n" + "varying vec2 tex_c2;\n" + "varying vec2 tex_c3;\n" + "#endif\n" + "#ifdef SHD_TEXA\n" + "uniform sampler2D texa;\n" + "varying vec2 tex_a;\n" + "#endif\n" + "#if defined(SHD_SAM12) || defined(SHD_SAM21) || defined(SHD_SAM22)\n" + "varying vec4 div_s;\n" + "# if defined(SHD_SAM12) || defined(SHD_SAM21)\n" + "varying vec2 tex_s[2];\n" + "# else\n" + "varying vec2 tex_s[4];\n" + "# endif\n" + "#endif\n" + "#ifdef SHD_MASK\n" + "uniform sampler2D texm;\n" + "varying vec2 tex_m;\n" + "# if defined(SHD_MASKSAM12) || defined(SHD_MASKSAM21)\n" + "varying float maskdiv_s;\n" + "varying vec2 masktex_s[2];\n" + "# elif defined(SHD_MASKSAM22)\n" + "varying float maskdiv_s;\n" + "varying vec2 masktex_s[4];\n" + "# endif\n" + "#endif\n" + "#ifdef SHD_ALPHA\n" + "# define SWZ aaaa\n" + "#else\n" + "# ifndef SHD_BGRA\n" + "# if defined(SHD_IMG) && defined(BIGENDIAN)\n" + "# define SWZ gbar\n" + "# else\n" + "# define SWZ bgra\n" + "#endif\n" + "# else\n" + "# if defined(SHD_IMG) && defined(BIGENDIAN)\n" + "# define SWZ grab\n" + "# else\n" + "# define SWZ rgba\n" + "# endif\n" + "# endif\n" + "#endif\n" + "void main()\n" + "{\n" + " vec4 c;\n" + "#if defined(SHD_YUV) || defined(SHD_NV12) || defined(SHD_YUY2)\n" + " float r, g, b, y, u, v, vmu;\n" + "# if defined(SHD_YUV)\n" + " y = texture2D(tex, tex_c).r;\n" + " u = texture2D(texu, tex_c2).r;\n" + " v = texture2D(texv, tex_c3).r;\n" + "# elif defined(SHD_NV12) || defined(SHD_YUY2)\n" + " y = texture2D(tex, tex_c).g;\n" + " u = texture2D(texuv, tex_c2).g;\n" + " v = texture2D(texuv, tex_c2).a;\n" + "# endif\n" + "// center u and v around 0 for uv and y (with 128/255 for u + v, 16/255 for y)\n" + " u = u - 0.5;\n" + " v = v - 0.5;\n" + "# if defined (SHD_YUV_709)\n" + "// 709 yuv colorspace for hd content\n" + " y = (y - 0.062) * 1.164;\n" + " vmu = (v * 0.534) + (u * 0.213);\n" + " v = v * 1.793;\n" + " u = u * 2.115;\n" + "# else\n" + "// 601 colorspace constants (older yuv content)\n" + " y = (y - 0.062) * 1.164;\n" + " vmu = (v * 0.813) + (u * 0.391);\n" + " v = v * 1.596;\n" + " u = u * 2.018;\n" + "# endif\n" + "// common yuv\n" + " r = y + v;\n" + " g = y - vmu;\n" + " b = y + u;\n" + " c = vec4(r, g, b, 1.0);\n" + "#elif defined(SHD_SAM12) || defined(SHD_SAM21)\n" + " vec4 col00 = texture2D(tex, tex_c + tex_s[0]).SWZ;\n" + " vec4 col01 = texture2D(tex, tex_c + tex_s[1]).SWZ;\n" + " c = (col00 + col01) / div_s;\n" + "#elif defined(SHD_SAM22)\n" + " vec4 col00 = texture2D(tex, tex_c + tex_s[0]).SWZ;\n" + " vec4 col01 = texture2D(tex, tex_c + tex_s[1]).SWZ;\n" + " vec4 col10 = texture2D(tex, tex_c + tex_s[2]).SWZ;\n" + " vec4 col11 = texture2D(tex, tex_c + tex_s[3]).SWZ;\n" + " c = (col00 + col01 + col10 + col11) / div_s;\n" + "#elif defined(SHD_TEX) || defined(SHD_EXTERNAL)\n" + " c = texture2D(tex, tex_c).SWZ;\n" + "#else\n" + " c = vec4(1, 1, 1, 1);\n" + "#endif\n" + "#ifdef SHD_MASK\n" + " float ma;\n" + "# if defined(SHD_MASKSAM12) || defined(SHD_MASKSAM21)\n" + " float ma00 = texture2D(texm, tex_m + masktex_s[0]).a;\n" + " float ma01 = texture2D(texm, tex_m + masktex_s[1]).a;\n" + " ma = (ma00 + ma01) / maskdiv_s;\n" + "# elif defined(SHD_MASKSAM22)\n" + " float ma00 = texture2D(texm, tex_m + masktex_s[0]).a;\n" + " float ma01 = texture2D(texm, tex_m + masktex_s[1]).a;\n" + " float ma10 = texture2D(texm, tex_m + masktex_s[2]).a;\n" + " float ma11 = texture2D(texm, tex_m + masktex_s[3]).a;\n" + " ma = (ma00 + ma01 + ma10 + ma11) / maskdiv_s;\n" + "# else\n" + " ma = texture2D(texm, tex_m).a;\n" + "# endif\n" + "#endif\n" + " gl_FragColor =\n" + " c\n" + "#ifndef SHD_NOMUL\n" + " * col\n" + "#endif\n" + "#ifdef SHD_MASK\n" + " * ma\n" + "#endif\n" + "#ifdef SHD_TEXA\n" + " * texture2D(texa, tex_a).r\n" + "#endif\n" + " ;\n" + "#ifdef SHD_AFILL\n" + " gl_FragColor.a = 1.0;\n" + "#endif\n" + "}\n"; + +static const char vertex_glsl[] = + "/* General-purpose vertex shader for all operations in Evas.\n" + " * This file can either be used directly by evas at runtime to\n" + " * generate its shaders with the appropriate #defines, or passed\n" + " * through cpp first (in which case the precision must be manually added).\n" + " */\n" + "#ifdef GL_ES\n" + "precision highp float;\n" + "#endif\n" + "attribute vec4 vertex;\n" + "uniform mat4 mvp;\n" + "/* All except nomul */\n" + "#ifndef SHD_NOMUL\n" + "attribute vec4 color;\n" + "varying vec4 col;\n" + "#endif\n" + "/* All images & fonts */\n" + "#if defined(SHD_TEX) || defined(SHD_EXTERNAL)\n" + "attribute vec2 tex_coord;\n" + "varying vec2 tex_c;\n" + "#endif\n" + "/* NV12, YUY2 */\n" + "#if defined(SHD_NV12) || defined(SHD_YUY2) || defined(SHD_YUV)\n" + "attribute vec2 tex_coord2;\n" + "varying vec2 tex_c2;\n" + "#endif\n" + "/* YUV */\n" + "#ifdef SHD_YUV\n" + "attribute vec2 tex_coord3;\n" + "varying vec2 tex_c3;\n" + "#endif\n" + "/* RGB+A */\n" + "#ifdef SHD_TEXA\n" + "attribute vec2 tex_coorda;\n" + "varying vec2 tex_a;\n" + "#endif\n" + "/* Sampling */\n" + "#if defined(SHD_SAM12) || defined(SHD_SAM21) || defined(SHD_SAM22)\n" + "attribute vec2 tex_sample;\n" + "varying vec4 div_s;\n" + "# if defined(SHD_SAM12) || defined(SHD_SAM21)\n" + "varying vec2 tex_s[2];\n" + "# else\n" + "varying vec2 tex_s[4];\n" + "# endif\n" + "#endif\n" + "/* Masking */\n" + "#ifdef SHD_MASK\n" + "attribute vec4 mask_coord;\n" + "varying vec2 tex_m;\n" + "# if defined(SHD_MASKSAM12) || defined(SHD_MASKSAM21)\n" + "attribute vec2 tex_masksample;\n" + "varying float maskdiv_s;\n" + "varying vec2 masktex_s[2];\n" + "# elif defined(SHD_MASKSAM22)\n" + "attribute vec2 tex_masksample;\n" + "varying float maskdiv_s;\n" + "varying vec2 masktex_s[4];\n" + "# endif\n" + "#endif\n" + "void main()\n" + "{\n" + " gl_Position = mvp * vertex;\n" + "#ifndef SHD_NOMUL\n" + " col = color;\n" + "#endif\n" + "#if defined(SHD_TEX) || defined(SHD_EXTERNAL)\n" + " tex_c = tex_coord;\n" + "#endif\n" + "#ifdef SHD_NV12\n" + " tex_c2 = tex_coord2 * 0.5;\n" + "#endif\n" + "#ifdef SHD_YUY2\n" + " tex_c2 = vec2(tex_coord2.x * 0.5, tex_coord2.y);\n" + "#endif\n" + "#ifdef SHD_YUV\n" + " tex_c2 = tex_coord2;\n" + " tex_c3 = tex_coord3;\n" + "#endif\n" + "#ifdef SHD_TEXA\n" + " tex_a = tex_coorda;\n" + "#endif\n" + "#if defined(SHD_SAM12)\n" + " tex_s[0] = vec2(0, -tex_sample.y);\n" + " tex_s[1] = vec2(0, tex_sample.y);\n" + " div_s = vec4(2, 2, 2, 2);\n" + "#elif defined(SHD_SAM21)\n" + " tex_s[0] = vec2(-tex_sample.x, 0);\n" + " tex_s[1] = vec2( tex_sample.x, 0);\n" + " div_s = vec4(2, 2, 2, 2);\n" + "#elif defined(SHD_SAM22)\n" + " tex_s[0] = vec2(-tex_sample.x, -tex_sample.y);\n" + " tex_s[1] = vec2( tex_sample.x, -tex_sample.y);\n" + " tex_s[2] = vec2( tex_sample.x, tex_sample.y);\n" + " tex_s[3] = vec2(-tex_sample.x, tex_sample.y);\n" + " div_s = vec4(4, 4, 4, 4);\n" + "#endif\n" + "#if defined(SHD_MASKSAM12)\n" + " masktex_s[0] = vec2(0, -tex_masksample.y);\n" + " masktex_s[1] = vec2(0, tex_masksample.y);\n" + " maskdiv_s = 2.0;\n" + "#elif defined(SHD_MASKSAM21)\n" + " masktex_s[0] = vec2(-tex_masksample.x, 0);\n" + " masktex_s[1] = vec2( tex_masksample.x, 0);\n" + " maskdiv_s = 2.0;\n" + "#elif defined(SHD_MASKSAM22)\n" + " masktex_s[0] = vec2(-tex_masksample.x, -tex_masksample.y);\n" + " masktex_s[1] = vec2( tex_masksample.x, -tex_masksample.y);\n" + " masktex_s[2] = vec2( tex_masksample.x, tex_masksample.y);\n" + " masktex_s[3] = vec2(-tex_masksample.x, tex_masksample.y);\n" + " maskdiv_s = 4.0;\n" + "#endif\n" + "#ifdef SHD_MASK\n" + " // mask_coord.w contains the Y-invert flag\n" + " // position on screen in [0..1] range of current pixel\n" + " vec4 mask_Position = mvp * vertex * vec4(0.5, sign(mask_coord.w) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0);\n" + " tex_m = mask_Position.xy * abs(mask_coord.zw) + mask_coord.xy;\n" + "#endif\n" + "}\n"; + diff --git a/src/lib/ector/gl/shader/fragment.glsl b/src/lib/ector/gl/shader/fragment.glsl new file mode 100644 index 0000000000..3dce873f40 --- /dev/null +++ b/src/lib/ector/gl/shader/fragment.glsl @@ -0,0 +1,168 @@ +/* General-purpose fragment shader for all operations in Evas. + * This file can either be used directly by evas at runtime to + * generate its shaders with the appropriate #defines, or passed + * through cpp first (in which case the precision must be manually added). + */ + +FRAGMENT_SHADER + +#ifndef SHD_NOMUL +varying vec4 col; +#endif + +#ifdef SHD_EXTERNAL +uniform SAMPLER_EXTERNAL_OES tex; +varying vec2 tex_c; +#elif defined(SHD_TEX) +uniform sampler2D tex; +varying vec2 tex_c; +#endif + +#if defined(SHD_NV12) || defined(SHD_YUY2) +uniform sampler2D texuv; +varying vec2 tex_c2; +#endif + +#if defined(SHD_YUV) +uniform sampler2D texu; +uniform sampler2D texv; +varying vec2 tex_c2; +varying vec2 tex_c3; +#endif + +#ifdef SHD_TEXA +uniform sampler2D texa; +varying vec2 tex_a; +#endif + +#if defined(SHD_SAM12) || defined(SHD_SAM21) || defined(SHD_SAM22) +varying vec4 div_s; +# if defined(SHD_SAM12) || defined(SHD_SAM21) +varying vec2 tex_s[2]; +# else +varying vec2 tex_s[4]; +# endif +#endif + +#ifdef SHD_MASK +uniform sampler2D texm; +varying vec2 tex_m; +# if defined(SHD_MASKSAM12) || defined(SHD_MASKSAM21) +varying float maskdiv_s; +varying vec2 masktex_s[2]; +# elif defined(SHD_MASKSAM22) +varying float maskdiv_s; +varying vec2 masktex_s[4]; +# endif +#endif + +#ifdef SHD_ALPHA +# define SWZ aaaa +#else +# ifndef SHD_BGRA +# if defined(SHD_IMG) && defined(BIGENDIAN) +# define SWZ gbar +# else +# define SWZ bgra +#endif +# else +# if defined(SHD_IMG) && defined(BIGENDIAN) +# define SWZ grab +# else +# define SWZ rgba +# endif +# endif +#endif + +void main() +{ + vec4 c; + +#if defined(SHD_YUV) || defined(SHD_NV12) || defined(SHD_YUY2) + float r, g, b, y, u, v, vmu; +# if defined(SHD_YUV) + y = texture2D(tex, tex_c).r; + u = texture2D(texu, tex_c2).r; + v = texture2D(texv, tex_c3).r; +# elif defined(SHD_NV12) || defined(SHD_YUY2) + y = texture2D(tex, tex_c).g; + u = texture2D(texuv, tex_c2).g; + v = texture2D(texuv, tex_c2).a; +# endif +// center u and v around 0 for uv and y (with 128/255 for u + v, 16/255 for y) + u = u - 0.5; + v = v - 0.5; + +# if defined (SHD_YUV_709) +// 709 yuv colorspace for hd content + y = (y - 0.062) * 1.164; + vmu = (v * 0.534) + (u * 0.213); + v = v * 1.793; + u = u * 2.115; +# else +// 601 colorspace constants (older yuv content) + y = (y - 0.062) * 1.164; + vmu = (v * 0.813) + (u * 0.391); + v = v * 1.596; + u = u * 2.018; +# endif +// common yuv + r = y + v; + g = y - vmu; + b = y + u; + c = vec4(r, g, b, 1.0); + +#elif defined(SHD_SAM12) || defined(SHD_SAM21) + vec4 col00 = texture2D(tex, tex_c + tex_s[0]).SWZ; + vec4 col01 = texture2D(tex, tex_c + tex_s[1]).SWZ; + c = (col00 + col01) / div_s; + +#elif defined(SHD_SAM22) + vec4 col00 = texture2D(tex, tex_c + tex_s[0]).SWZ; + vec4 col01 = texture2D(tex, tex_c + tex_s[1]).SWZ; + vec4 col10 = texture2D(tex, tex_c + tex_s[2]).SWZ; + vec4 col11 = texture2D(tex, tex_c + tex_s[3]).SWZ; + c = (col00 + col01 + col10 + col11) / div_s; + +#elif defined(SHD_TEX) || defined(SHD_EXTERNAL) + c = texture2D(tex, tex_c).SWZ; + +#else + c = vec4(1, 1, 1, 1); +#endif + +#ifdef SHD_MASK + float ma; +# if defined(SHD_MASKSAM12) || defined(SHD_MASKSAM21) + float ma00 = texture2D(texm, tex_m + masktex_s[0]).a; + float ma01 = texture2D(texm, tex_m + masktex_s[1]).a; + ma = (ma00 + ma01) / maskdiv_s; +# elif defined(SHD_MASKSAM22) + float ma00 = texture2D(texm, tex_m + masktex_s[0]).a; + float ma01 = texture2D(texm, tex_m + masktex_s[1]).a; + float ma10 = texture2D(texm, tex_m + masktex_s[2]).a; + float ma11 = texture2D(texm, tex_m + masktex_s[3]).a; + ma = (ma00 + ma01 + ma10 + ma11) / maskdiv_s; +# else + ma = texture2D(texm, tex_m).a; +# endif +#endif + + gl_FragColor = + c +#ifndef SHD_NOMUL + * col +#endif +#ifdef SHD_MASK + * ma +#endif +#ifdef SHD_TEXA + * texture2D(texa, tex_a).r +#endif + ; + +#ifdef SHD_AFILL + gl_FragColor.a = 1.0; +#endif +} + diff --git a/src/lib/ector/gl/shader/gen_shaders.sh b/src/lib/ector/gl/shader/gen_shaders.sh new file mode 100755 index 0000000000..139d5ea109 --- /dev/null +++ b/src/lib/ector/gl/shader/gen_shaders.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# This script will generate a C file containing all the shaders used by Evas + +DIR=`dirname $0` + +OUTPUT=${DIR}/ector_gl_shaders.x + +# Skip generation if there is no diff (or no git) +if ! git rev-parse 2>> /dev/null >> /dev/null ; then exit 0 ; fi +if git diff --quiet --exit-code -- "$DIR" +then + touch "${OUTPUT}" + exit 0 +fi + +exec 1<&- +exec 1>${OUTPUT} + +# Write header +printf "/* DO NOT MODIFY THIS FILE AS IT IS AUTO-GENERATED */\n" +printf "/* IF IT IS CHANGED PLEASE COMMIT THE CHANGES */\n\n" + +for shd in fragment vertex ; do + m4 ${DIR}/include.glsl ${DIR}/${shd}.glsl > ${shd}.tmp + + OIFS=$IFS + IFS=$'\n' + printf "static const char ${shd}_glsl[] =" + for line in `cat ${shd}.tmp` ; do + printf "\n \"${line}\\\n\"" + done + printf ";\n\n" + IFS=${OIFS} + + rm ${shd}.tmp +done + diff --git a/src/lib/ector/gl/shader/include.glsl b/src/lib/ector/gl/shader/include.glsl new file mode 100644 index 0000000000..b8f8ac115e --- /dev/null +++ b/src/lib/ector/gl/shader/include.glsl @@ -0,0 +1,22 @@ +define(`FRAGMENT_SHADER',` +#ifdef GL_ES +# ifdef GL_FRAGMENT_PRECISION_HIGH +precision highp float; +# else +precision mediump float; +# endif +# ifdef SHD_EXTERNAL +extension GL_OES_EGL_image_external : require +# define SAMPLER_EXTERNAL_OES samplerExternalOES +# endif +#else +# define SAMPLER_EXTERNAL_OES sampler2D +#endif +') + +define(`VERTEX_SHADER',` +#ifdef GL_ES +precision highp float; +#endif +') + diff --git a/src/lib/ector/gl/shader/vertex.glsl b/src/lib/ector/gl/shader/vertex.glsl new file mode 100644 index 0000000000..d67eb0684e --- /dev/null +++ b/src/lib/ector/gl/shader/vertex.glsl @@ -0,0 +1,137 @@ +/* General-purpose vertex shader for all operations in Evas. + * This file can either be used directly by evas at runtime to + * generate its shaders with the appropriate #defines, or passed + * through cpp first (in which case the precision must be manually added). + */ + +VERTEX_SHADER + +attribute vec4 vertex; +uniform mat4 mvp; + +/* All except nomul */ +#ifndef SHD_NOMUL +attribute vec4 color; +varying vec4 col; +#endif + +/* All images & fonts */ +#if defined(SHD_TEX) || defined(SHD_EXTERNAL) +attribute vec2 tex_coord; +varying vec2 tex_c; +#endif + +/* NV12, YUY2 */ +#if defined(SHD_NV12) || defined(SHD_YUY2) || defined(SHD_YUV) +attribute vec2 tex_coord2; +varying vec2 tex_c2; +#endif + +/* YUV */ +#ifdef SHD_YUV +attribute vec2 tex_coord3; +varying vec2 tex_c3; +#endif + +/* RGB+A */ +#ifdef SHD_TEXA +attribute vec2 tex_coorda; +varying vec2 tex_a; +#endif + +/* Sampling */ +#if defined(SHD_SAM12) || defined(SHD_SAM21) || defined(SHD_SAM22) +attribute vec2 tex_sample; +varying vec4 div_s; +# if defined(SHD_SAM12) || defined(SHD_SAM21) +varying vec2 tex_s[2]; +# else +varying vec2 tex_s[4]; +# endif +#endif + +/* Masking */ +#ifdef SHD_MASK +attribute vec4 mask_coord; +varying vec2 tex_m; +# if defined(SHD_MASKSAM12) || defined(SHD_MASKSAM21) +attribute vec2 tex_masksample; +varying float maskdiv_s; +varying vec2 masktex_s[2]; +# elif defined(SHD_MASKSAM22) +attribute vec2 tex_masksample; +varying float maskdiv_s; +varying vec2 masktex_s[4]; +# endif +#endif + + +void main() +{ + gl_Position = mvp * vertex; + +#ifndef SHD_NOMUL + col = color; +#endif + +#if defined(SHD_TEX) || defined(SHD_EXTERNAL) + tex_c = tex_coord; +#endif + +#ifdef SHD_NV12 + tex_c2 = tex_coord2 * 0.5; +#endif + +#ifdef SHD_YUY2 + tex_c2 = vec2(tex_coord2.x * 0.5, tex_coord2.y); +#endif + +#ifdef SHD_YUV + tex_c2 = tex_coord2; + tex_c3 = tex_coord3; +#endif + +#ifdef SHD_TEXA + tex_a = tex_coorda; +#endif + +#if defined(SHD_SAM12) + tex_s[0] = vec2(0, -tex_sample.y); + tex_s[1] = vec2(0, tex_sample.y); + div_s = vec4(2, 2, 2, 2); +#elif defined(SHD_SAM21) + tex_s[0] = vec2(-tex_sample.x, 0); + tex_s[1] = vec2( tex_sample.x, 0); + div_s = vec4(2, 2, 2, 2); +#elif defined(SHD_SAM22) + tex_s[0] = vec2(-tex_sample.x, -tex_sample.y); + tex_s[1] = vec2( tex_sample.x, -tex_sample.y); + tex_s[2] = vec2( tex_sample.x, tex_sample.y); + tex_s[3] = vec2(-tex_sample.x, tex_sample.y); + div_s = vec4(4, 4, 4, 4); +#endif + +#if defined(SHD_MASKSAM12) + masktex_s[0] = vec2(0, -tex_masksample.y); + masktex_s[1] = vec2(0, tex_masksample.y); + maskdiv_s = 2.0; +#elif defined(SHD_MASKSAM21) + masktex_s[0] = vec2(-tex_masksample.x, 0); + masktex_s[1] = vec2( tex_masksample.x, 0); + maskdiv_s = 2.0; +#elif defined(SHD_MASKSAM22) + masktex_s[0] = vec2(-tex_masksample.x, -tex_masksample.y); + masktex_s[1] = vec2( tex_masksample.x, -tex_masksample.y); + masktex_s[2] = vec2( tex_masksample.x, tex_masksample.y); + masktex_s[3] = vec2(-tex_masksample.x, tex_masksample.y); + maskdiv_s = 4.0; +#endif + +#ifdef SHD_MASK + // mask_coord.w contains the Y-invert flag + // position on screen in [0..1] range of current pixel + vec4 mask_Position = mvp * vertex * vec4(0.5, sign(mask_coord.w) * 0.5, 0.5, 0.5) + vec4(0.5, 0.5, 0, 0); + tex_m = mask_Position.xy * abs(mask_coord.zw) + mask_coord.xy; +#endif +} + diff --git a/src/lib/eina/eina_util.c b/src/lib/eina/eina_util.c index 0adc412008..02f90d47bd 100644 --- a/src/lib/eina/eina_util.c +++ b/src/lib/eina/eina_util.c @@ -91,7 +91,7 @@ eina_environment_tmp_get(void) # endif { tmp = getenv("TMPDIR"); - if (!tmp) tmp = getenv("XDG_RUNTIME_DIR"); + if (!tmp) tmp = getenv("XDG_RUNTIME_DIR"); } if (!tmp) tmp = "/tmp"; diff --git a/src/modules/evas/engines/gl_common/evas_gl_shader.c b/src/modules/evas/engines/gl_common/evas_gl_shader.c index 9df1806630..6a7209cd8b 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_shader.c +++ b/src/modules/evas/engines/gl_common/evas_gl_shader.c @@ -123,7 +123,6 @@ _evas_gl_common_shader_program_binary_load(Eet_File *ef, unsigned int flags) if (!formats[0]) goto finish; prg = glCreateProgram(); - #if 1 // TODO: invalid rendering error occurs when attempting to use a // glProgramBinary. in order to render correctly we should create a dummy @@ -151,8 +150,6 @@ _evas_gl_common_shader_program_binary_load(Eet_File *ef, unsigned int flags) gl_compile_link_error(prg, "load a program object", EINA_FALSE); ERR("Abort load of program (%s)", pname); glDeleteProgram(prg); - glDeleteShader(vtx); - glDeleteShader(frg); goto finish; }