lib/ector/gl/ector_renderer_gl_gradient_radial.c \
lib/ector/gl/ector_renderer_gl_shape.c \
lib/ector/gl/ector_gl_surface.c \
+lib/ector/gl/ector_gl_engine.c \
+lib/ector/gl/ector_gl_shaders.x \
static_libs/triangulator/triangulator_stroker.c \
static_libs/triangulator/triangulator_simple.c
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <Ector_Gl.h>
+#include "ector_private.h"
+#include "ector_gl_private.h"
+#include "ector_gl_shaders.x"
+
+static void
+_init_matrix(float *m)
+{
+ m[0] = 1.0f;
+ m[1] = 0.0f;
+ m[2] = 0.0f;
+ m[3] = 0.0f;
+
+ m[4] = 0.0f;
+ m[5] = 1.0f;
+ m[6] = 0.0f;
+ m[7] = 0.0f;
+
+ m[8] = 0.0f;
+ m[9] = 0.0f;
+ m[10] = 1.0f;
+ m[11] = 0.0f;
+
+ m[12] = 0.0f;
+ m[13] = 0.0f;
+ m[14] = 0.0f;
+ m[15] = 1.0f;
+}
+
+static void
+_matrix_ortho(GLfloat *m,
+ GLfloat l, GLfloat r,
+ GLfloat t, GLfloat b,
+ GLfloat near_, GLfloat far_,
+ int rot, int vw, int vh,
+ int foc, GLfloat orth)
+{
+ GLfloat rotf;
+ GLfloat cosv, sinv;
+ GLfloat tx, ty;
+
+ rotf = (((rot / 90) & 0x3) * M_PI) / 2.0;
+
+ tx = -0.5 * (1.0 - orth);
+ ty = -0.5 * (1.0 - orth);
+
+ if (rot == 90)
+ {
+ tx += -(vw * 1.0);
+ ty += -(vh * 0.0);
+ }
+ if (rot == 180)
+ {
+ tx += -(vw * 1.0);
+ ty += -(vh * 1.0);
+ }
+ if (rot == 270)
+ {
+ tx += -(vw * 0.0);
+ ty += -(vh * 1.0);
+ }
+
+ cosv = cos(rotf);
+ sinv = sin(rotf);
+
+ m[0] = (2.0 / (r - l)) * ( cosv);
+ m[1] = (2.0 / (r - l)) * ( sinv);
+ m[2] = 0.0;
+ m[3] = 0.0;
+
+ m[4] = (2.0 / (t - b)) * (-sinv);
+ m[5] = (2.0 / (t - b)) * ( cosv);
+ m[6] = 0.0;
+ m[7] = 0.0;
+
+ m[8] = 0.0;
+ m[9] = 0.0;
+ m[10] = -(2.0 / (far_ - near_));
+ m[11] = 1.0 / (GLfloat)foc;
+
+ m[12] = (m[0] * tx) + (m[4] * ty) - ((r + l) / (r - l));
+ m[13] = (m[1] * tx) + (m[5] * ty) - ((t + b) / (t - b));
+ m[14] = (m[2] * tx) + (m[6] * ty) - ((near_ + far_) / (far_ - near_));
+ m[15] = (m[3] * tx) + (m[7] * ty) + orth;
+}
+
+
+static Ector_Gl_Engine_Data *ENG = NULL;
+
+static void
+_destroy_shader_program(Shader_Program *shader)
+{
+ if (shader)
+ {
+ if (shader->v_shader) GL.glDeleteShader(shader->v_shader);
+ if (shader->f_shader)GL.glDeleteShader(shader->f_shader);
+ if (shader->program) GL.glDeleteProgram(shader->program);
+ free(shader);
+ }
+}
+static Shader_Program *
+_create_shader_program(const char *v_shader, const char* f_shader)
+{
+ Shader_Program *shader = calloc(1, sizeof(Shader_Program));
+ GLint ok = 0;
+
+ shader->v_shader = GL.glCreateShader(GL_VERTEX_SHADER);
+ GL.glShaderSource(shader->v_shader, 1, &v_shader, NULL);
+ GL.glCompileShader(shader->v_shader);
+ GL.glGetShaderiv(shader->v_shader, GL_COMPILE_STATUS, &ok);
+ if (!ok)
+ {
+ ERR("vertex shader compilation failed ");
+ goto fail;
+ }
+
+ shader->f_shader = GL.glCreateShader(GL_FRAGMENT_SHADER);
+ GL.glShaderSource(shader->f_shader, 1, &f_shader, NULL);
+ GL.glCompileShader(shader->f_shader);
+ GL.glGetShaderiv(shader->f_shader, GL_COMPILE_STATUS, &ok);
+ if (!ok)
+ {
+ ERR("fragment shader compilation failed ");
+ goto fail;
+ }
+
+ shader->program = GL.glCreateProgram();
+ GL.glAttachShader(shader->program, shader->v_shader);
+ GL.glAttachShader(shader->program, shader->f_shader);
+ GL.glBindAttribLocation(shader->program, ECTOR_SHAD_VERTEX, "vertex");
+ GL.glBindAttribLocation(shader->program, ECTOR_SHAD_TEXUV, "v_tex_coord");
+ GL.glLinkProgram(shader->program);
+ GL.glGetProgramiv(shader->program, GL_LINK_STATUS, &ok);
+ if (!ok)
+ {
+ ERR("linking failed for shader program");
+ goto fail;
+ }
+ shader->u_color = GL.glGetUniformLocation(shader->program, "color");
+ shader->u_pos = GL.glGetUniformLocation(shader->program, "pos");
+ shader->u_mvp = GL.glGetUniformLocation(shader->program, "mvp");
+ shader->u_texture = GL.glGetUniformLocation(shader->program, "texture");
+ return shader;
+fail:
+ _destroy_shader_program(shader);
+ return NULL;
+}
+
+static void
+_update_lg_uniform()
+{
+ ENG->shader.lg->u_half_viewport_size = GL.glGetUniformLocation(ENG->shader.lg->program, "half_viewport_size");
+ ENG->shader.lg->linear.u_linear_data = GL.glGetUniformLocation(ENG->shader.lg->program, "linear_data");
+}
+
+static void
+_update_rg_uniform()
+{
+ ENG->shader.rg->u_half_viewport_size = GL.glGetUniformLocation(ENG->shader.rg->program, "half_viewport_size");
+ ENG->shader.rg->radial.u_fmp = GL.glGetUniformLocation(ENG->shader.rg->program, "fmp");
+ ENG->shader.rg->radial.u_bradius = GL.glGetUniformLocation(ENG->shader.rg->program, "bradius");
+ ENG->shader.rg->radial.u_fmp2_m_radius2 = GL.glGetUniformLocation(ENG->shader.rg->program, "fmp2_m_radius2");
+ ENG->shader.rg->radial.u_inverse_2_fmp2_m_radius2 = GL.glGetUniformLocation(ENG->shader.rg->program, "inverse_2_fmp2_m_radius2");
+ ENG->shader.rg->radial.u_sqrfr = GL.glGetUniformLocation(ENG->shader.rg->program, "sqrfr");
+}
+
+void
+update_gradient_texture(Ector_Renderer_Gl_Gradient_Data *gdata)
+{
+ if (gdata->color_table) return;
+
+ GLenum wrapMode = GL_CLAMP_TO_EDGE;
+
+ gdata->color_table = malloc(GRADIENT_ARRAY_SIZE * 4);
+ gdata->alpha = _generate_gradient_color_table(gdata->gd->colors, gdata->gd->colors_count, gdata->color_table, GRADIENT_ARRAY_SIZE);
+
+ if (gdata->gd->s == EFL_GFX_GRADIENT_SPREAD_REPEAT)
+ wrapMode = GL_REPEAT;
+ else if (gdata->gd->s == EFL_GFX_GRADIENT_SPREAD_REFLECT)
+ wrapMode = GL_MIRRORED_REPEAT;
+
+ GL.glGenTextures(1, &(gdata->texture));
+ GL.glBindTexture(GL_TEXTURE_2D, gdata->texture);
+ GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
+ GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);
+ GL.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GRADIENT_ARRAY_SIZE, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, gdata->color_table);
+
+ GL.glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+void
+destroy_gradient_texture(Ector_Renderer_Gl_Gradient_Data *gdata)
+{
+ if (gdata->color_table)
+ {
+ free(gdata->color_table);
+ gdata->color_table = NULL;
+ GL.glDeleteTextures(1, &(gdata->texture));
+ gdata->texture = 0;
+ }
+}
+
+static void
+_ector_gl_engine_destroy_surface()
+{
+ if (!ENG->surface.fbo.id) return;
+
+ if (ENG->surface.fbo.rbo_color)
+ GL.glDeleteRenderbuffers(1, &(ENG->surface.fbo.rbo_color));
+ if (ENG->surface.fbo.rbo_stencil)
+ GL.glDeleteRenderbuffers(1, &(ENG->surface.fbo.rbo_stencil));
+ if (ENG->surface.fbo.texture)
+ GL.glDeleteTextures(1, &(ENG->surface.fbo.texture));
+ if (ENG->surface.fbo.id)
+ GL.glDeleteFramebuffers(1, &(ENG->surface.fbo.id));
+
+ ENG->surface.fbo.id = 0;
+ ENG->surface.fbo.rbo_color = 0;
+ ENG->surface.fbo.rbo_stencil = 0;
+ ENG->surface.fbo.texture = 0;
+}
+
+static Eina_Bool
+_ector_gl_engine_create_fbo_rbo_surface()
+{
+ GL.glGenRenderbuffers(1, &ENG->surface.fbo.rbo_color);
+ GL.glBindRenderbuffer(GL_RENDERBUFFER, ENG->surface.fbo.rbo_color);
+ GL.glRenderbufferStorageMultisample(GL_RENDERBUFFER,
+ ENG->surface.capability.multisample_size,
+ GL_RGBA,
+ ENG->surface.fbo.w, ENG->surface.fbo.h);
+
+ // create a 4x MSAA renderbuffer object for depthbuffer
+ GL.glGenRenderbuffers(1, &ENG->surface.fbo.rbo_stencil);
+ GL.glBindRenderbuffer(GL_RENDERBUFFER, ENG->surface.fbo.rbo_stencil);
+ GL.glRenderbufferStorageMultisample(GL_RENDERBUFFER,
+ ENG->surface.capability.multisample_size,
+ GL_STENCIL_INDEX8,
+ ENG->surface.fbo.w, ENG->surface.fbo.h);
+
+
+ GL.glGenFramebuffers(1, &ENG->surface.fbo.id);
+ GL.glBindFramebuffer(GL_FRAMEBUFFER, ENG->surface.fbo.id);
+
+ // attach colorbuffer image to FBO
+ GL.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER,
+ ENG->surface.fbo.rbo_color);
+
+ // attach stencil buffer to FBO
+ GL.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER,
+ ENG->surface.fbo.rbo_stencil);
+
+ // check FBO status
+ GLenum status = GL.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if(status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ ERR("cretaing MSAA fbo rbo failed");
+ GL.glDeleteRenderbuffers(1, &(ENG->surface.fbo.rbo_color));
+ GL.glDeleteRenderbuffers(1, &(ENG->surface.fbo.rbo_stencil));
+ GL.glDeleteFramebuffers(1, &(ENG->surface.fbo.id));
+ ENG->surface.fbo.id = 0;
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_ector_gl_engine_create_fbo_text_ext_surface()
+{
+ GL.glGenTextures(1, &ENG->surface.fbo.texture);
+ GL.glBindTexture(GL_TEXTURE_2D, ENG->surface.fbo.texture);
+ GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ GL.glTexImage2D(GL_TEXTURE_2D, 0,
+ GL_RGBA, ENG->surface.fbo.w, ENG->surface.fbo.h, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, NULL);
+ GL.glBindTexture(GL_TEXTURE_2D, 0);
+
+
+ // create a MSAA renderbuffer object for stencil buffer
+ GL.glGenRenderbuffers(1, &ENG->surface.fbo.rbo_stencil);
+ GL.glBindRenderbuffer(GL_RENDERBUFFER, ENG->surface.fbo.rbo_stencil);
+ GL.glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
+ ENG->surface.capability.multisample_size,
+ GL_STENCIL_INDEX8,
+ ENG->surface.fbo.w, ENG->surface.fbo.h);
+
+
+ GL.glGenFramebuffers(1, &ENG->surface.fbo.id);
+ GL.glBindFramebuffer(GL_FRAMEBUFFER, ENG->surface.fbo.id);
+
+ // attach texture to FBO
+ GL.glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D,
+ ENG->surface.fbo.texture,
+ 0,
+ ENG->surface.capability.multisample_size);
+
+ // attach stencil buffer to FBO
+ GL.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER,
+ ENG->surface.fbo.rbo_stencil);
+
+ // check FBO status
+ GLenum status = GL.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if(status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ ERR("cretaing MSAA fbo texture failed");
+ GL.glDeleteTextures(1, &(ENG->surface.fbo.texture));
+ GL.glDeleteRenderbuffers(1, &(ENG->surface.fbo.rbo_stencil));
+ GL.glDeleteFramebuffers(1, &(ENG->surface.fbo.id));
+ ENG->surface.fbo.id = 0;
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_ector_gl_engine_create_fbo_text_surface()
+{
+ GL.glGenTextures(1, &ENG->surface.fbo.texture);
+ GL.glBindTexture(GL_TEXTURE_2D, ENG->surface.fbo.texture);
+ GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ GL.glTexImage2D(GL_TEXTURE_2D, 0,
+ GL_RGBA, ENG->surface.fbo.w, ENG->surface.fbo.h, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, NULL);
+ GL.glBindTexture(GL_TEXTURE_2D, 0);
+
+
+ GL.glGenRenderbuffers(1, &ENG->surface.fbo.rbo_stencil);
+ GL.glBindRenderbuffer(GL_RENDERBUFFER, ENG->surface.fbo.rbo_stencil);
+ GL.glRenderbufferStorage(GL_RENDERBUFFER,
+ GL_STENCIL_INDEX8,
+ ENG->surface.fbo.w, ENG->surface.fbo.h);
+
+
+ GL.glGenFramebuffers(1, &ENG->surface.fbo.id);
+ GL.glBindFramebuffer(GL_FRAMEBUFFER, ENG->surface.fbo.id);
+
+ // attach texture to FBO
+ GL.glFramebufferTexture2D(GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D,
+ ENG->surface.fbo.texture,
+ 0);
+
+ // attach stencil buffer to FBO
+ GL.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER,
+ ENG->surface.fbo.rbo_stencil);
+
+ // check FBO status
+ GLenum status = GL.glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if(status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ ERR("cretaing normal fbo texture failed");
+ GL.glDeleteTextures(1, &(ENG->surface.fbo.texture));
+ GL.glDeleteRenderbuffers(1, &(ENG->surface.fbo.rbo_stencil));
+ GL.glDeleteFramebuffers(1, &(ENG->surface.fbo.id));
+ ENG->surface.fbo.id = 0;
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+Eina_Bool
+_ector_gl_engine_update_surface()
+{
+ if (ENG->info.direct_draw)
+ return EINA_TRUE;
+
+ if (ENG->surface.fbo.w >= ENG->surface.w && ENG->surface.fbo.h >= ENG->surface.h)
+ {
+ // no need to update the scratch buffer
+ GL.glBindFramebuffer(GL_FRAMEBUFFER, ENG->surface.fbo.id);
+ return EINA_TRUE;
+ }
+
+ // delete old buffer if any
+ _ector_gl_engine_destroy_surface();
+
+ // update the new size
+ ENG->surface.fbo.w = ENG->surface.w > ENG->surface.fbo.w ? ENG->surface.w : ENG->surface.fbo.w;
+ ENG->surface.fbo.h = ENG->surface.h > ENG->surface.fbo.h ? ENG->surface.h : ENG->surface.fbo.h;
+
+ if (ENG->surface.capability.multisample)
+ {
+ return _ector_gl_engine_create_fbo_rbo_surface();
+ }
+ else if (ENG->surface.capability.ext_multisample)
+ {
+ return _ector_gl_engine_create_fbo_text_ext_surface();
+ }
+ else
+ {
+ return _ector_gl_engine_create_fbo_text_surface();
+ }
+}
+
+static void
+_update_viewport(int width, int height)
+{
+ if ((ENG->info.rotation == 0) || (ENG->info.rotation == 180))
+ {
+ GL.glViewport(0, 0, width, height);
+ }
+ else
+ {
+ GL.glViewport(0, 0, height, width);
+ }
+
+ _init_matrix(ENG->mvp);
+
+ if (ENG->info.flip)
+ {
+ _matrix_ortho(ENG->mvp,
+ 0, width,
+ height, 0,
+ -1000000.0, 1000000.0, ENG->info.rotation,
+ width, height,
+ 1, 1.0);
+ }
+ else
+ {
+ _matrix_ortho(ENG->mvp,
+ 0, width,
+ 0, height,
+ -1000000.0, 1000000.0, ENG->info.rotation,
+ width, height,
+ 1, 1.0);
+ }
+}
+
+Eina_Bool
+ector_gl_engine_begin()
+{
+ if (!_ector_gl_engine_update_surface()) return EINA_FALSE;
+
+ _update_viewport(ENG->surface.w, ENG->surface.h);
+
+ GL.glEnable(GL_SCISSOR_TEST);
+ GL.glScissor(ENG->master.clip.x, ENG->master.clip.y, ENG->master.clip.w, ENG->master.clip.h);
+ GL.glClearStencil(0);
+ GL.glClearColor(0, 0, 0, 0);
+ if (!(ENG->info.direct_draw) || ENG->info.clear_surface)
+ {
+ GL.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+ GL.glDisable(GL_DEPTH_TEST);
+ GL.glEnable(GL_BLEND);
+ GL.glDisable(GL_STENCIL_TEST);
+ GL.glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
+
+ return EINA_TRUE;
+}
+
+void
+ector_gl_engine_end()
+{
+ GL.glDisable(GL_DEPTH_TEST);
+ GL.glDisable(GL_STENCIL_TEST);
+ GL.glDisable(GL_BLEND);
+ GL.glDisable(GL_SCISSOR_TEST);
+ GL.glScissor(0, 0, 0, 0);
+
+ ENG->state.program = NULL;
+ ENG->state.u_color = 0;
+ ENG->state.u_pos_x = 0;
+ ENG->state.u_pos_y = 0;
+}
+
+static inline void
+_update_color_uniform(GLuint pos, unsigned int color)
+{
+ GL.glUniform4f(pos, (R_VAL(&color)/255.0), (G_VAL(&color)/255.0), (B_VAL(&color)/255.0), (A_VAL(&color)/255.0));
+}
+
+static void
+_load_simple_program()
+{
+ //Already the program is used
+ if (ENG->state.program == ENG->shader.simple)
+ {
+ GL.glUniform4f(ENG->shader.simple->u_pos, ENG->master.offset.x + ENG->offset.x, ENG->master.offset.y + ENG->offset.y, 0, 0);
+ _update_color_uniform(ENG->shader.simple->u_color, ECTOR_MUL4_SYM(ENG->brush.color, ENG->info.color));
+ }
+ else
+ {
+ GL.glUseProgram(ENG->shader.simple->program);
+ GL.glEnableVertexAttribArray(ECTOR_SHAD_VERTEX);
+ GL.glUniformMatrix4fv(ENG->shader.simple->u_mvp, 1, GL_FALSE, ENG->mvp);
+ GL.glUniform4f(ENG->shader.simple->u_pos, ENG->master.offset.x + ENG->offset.x, ENG->master.offset.y + ENG->offset.y, 0, 0);
+ _update_color_uniform(ENG->shader.simple->u_color, ECTOR_MUL4_SYM(ENG->brush.color, ENG->info.color));
+
+ // keep the state
+ ENG->state.program = ENG->shader.simple;
+ ENG->state.u_pos_x = ENG->master.offset.x + ENG->offset.x;
+ ENG->state.u_pos_y = ENG->master.offset.y + ENG->offset.y;
+ ENG->state.u_color = ENG->brush.color;
+ }
+}
+
+static void
+_load_lg_program()
+{
+ //Already the program is used
+ GL.glUseProgram(ENG->shader.lg->program);
+ GL.glEnableVertexAttribArray(ECTOR_SHAD_VERTEX);
+ GL.glUniformMatrix4fv(ENG->shader.lg->u_mvp, 1, GL_FALSE, ENG->mvp);
+ GL.glUniform4f(ENG->shader.lg->u_pos, ENG->master.offset.x + ENG->offset.x, ENG->master.offset.y + ENG->offset.y, 0, 0);
+ GL.glUniform2f(ENG->shader.lg->u_half_viewport_size, ENG->surface.w * 0.5, ENG->surface.h * 0.5);
+ GL.glUniform3f(ENG->shader.lg->linear.u_linear_data, ENG->brush.g->linear.dx, ENG->brush.g->linear.dy, ENG->brush.g->linear.l);
+
+ GL.glActiveTexture(GL_TEXTURE0);
+ GL.glBindTexture(GL_TEXTURE_2D, ENG->brush.g->texture);
+ GL.glUniform1i(ENG->shader.lg->u_texture, 0);
+
+ // keep the state
+ ENG->state.program = ENG->shader.lg;
+ ENG->state.u_pos_x = ENG->master.offset.x + ENG->offset.x;
+ ENG->state.u_pos_y = ENG->master.offset.y + ENG->offset.y;
+ ENG->state.u_color = 0;
+}
+
+static void
+_load_rg_program()
+{
+ //Already the program is used
+ GL.glUseProgram(ENG->shader.rg->program);
+ GL.glEnableVertexAttribArray(ECTOR_SHAD_VERTEX);
+ GL.glUniformMatrix4fv(ENG->shader.rg->u_mvp, 1, GL_FALSE, ENG->mvp);
+ GL.glUniform4f(ENG->shader.rg->u_pos, ENG->master.offset.x + ENG->offset.x, ENG->master.offset.y + ENG->offset.y, 0, 0);
+ GL.glUniform2f(ENG->shader.rg->u_half_viewport_size, ENG->surface.w * 0.5, ENG->surface.h * 0.5);
+
+ GL.glUniform2f(ENG->shader.rg->radial.u_fmp, ENG->brush.g->radial.dx, ENG->brush.g->radial.dy);
+ GL.glUniform1f(ENG->shader.rg->radial.u_fmp2_m_radius2, ENG->brush.g->radial.a);
+ GL.glUniform1f(ENG->shader.rg->radial.u_inverse_2_fmp2_m_radius2, ENG->brush.g->radial.inv2a);
+ GL.glUniform1f(ENG->shader.rg->radial.u_sqrfr, ENG->brush.g->radial.fradius * ENG->brush.g->radial.fradius);
+
+ GL.glUniform3f(ENG->shader.rg->radial.u_bradius,
+ 2 * ENG->brush.g->radial.dr * ENG->brush.g->radial.fradius,
+ ENG->brush.g->radial.fradius,
+ ENG->brush.g->radial.dr);
+
+
+ GL.glActiveTexture(GL_TEXTURE0);
+ GL.glBindTexture(GL_TEXTURE_2D, ENG->brush.g->texture);
+ GL.glUniform1i(ENG->shader.rg->u_texture, 0);
+
+ // keep the state
+ ENG->state.program = ENG->shader.rg;
+ ENG->state.u_pos_x = ENG->master.offset.x + ENG->offset.x;
+ ENG->state.u_pos_y = ENG->master.offset.y + ENG->offset.y;
+ ENG->state.u_color = 0;
+}
+
+static void
+_update_brush()
+{
+ switch(ENG->brush.type)
+ {
+ case Solid:
+ {
+ _load_simple_program();
+ break;
+ }
+ case LinearGradient:
+ {
+ _load_lg_program();
+ break;
+ }
+ case RadialGradient:
+ {
+ _load_rg_program();
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static Eina_Bool
+_is_stencil_available()
+{
+ if (ENG->info.direct_draw && !(ENG->info.stencil))
+ return EINA_FALSE;
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_is_solid_brush()
+{
+ if ((ENG->brush.type == Solid) && (A_VAL(&(ENG->brush.color)) == 255))
+ return EINA_TRUE;
+ else if ((ENG->brush.g) && (!ENG->brush.g->alpha))
+ return EINA_TRUE;
+
+ return EINA_FALSE;
+}
+
+void
+ector_gl_engine_path_stroke(float *vertex, int count)
+{
+ if (!(_is_stencil_available()) || _is_solid_brush())
+ {
+ _load_simple_program();
+ GL.glVertexAttribPointer(ECTOR_SHAD_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, vertex);
+ GL.glDrawArrays(GL_TRIANGLE_STRIP, 0, count/2);
+ return;
+ }
+ else
+ {
+ _load_simple_program();
+ GL.glVertexAttribPointer(ECTOR_SHAD_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, vertex);
+
+ GL.glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes
+
+ GL.glEnable(GL_STENCIL_TEST);
+ GL.glStencilMask(0xff);
+ GL.glClear(GL_STENCIL_BUFFER_BIT);
+ GL.glStencilMask(GL_STENCIL_HIGH_BIT);
+
+ GL.glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
+
+ GL.glStencilFunc(GL_ALWAYS, GL_STENCIL_HIGH_BIT, 0xff);
+
+ GL.glDrawArrays(GL_TRIANGLE_STRIP, 0, count/2); // here the shape is drawn in the stencil
+
+ // Enable color writes & disable stencil writes
+ GL.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ GL.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
+ // Pass when high bit is set, replace stencil value with 0
+ GL.glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT);
+
+ // draw a rectangle
+ _update_brush();
+ float rect_bound[10] = {0, 0 ,
+ ENG->surface.w, 0,
+ ENG->surface.w, ENG->surface.h,
+ 0, ENG->surface.h};
+ GL.glVertexAttribPointer(ECTOR_SHAD_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, rect_bound);
+ GL.glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ // reset
+ GL.glStencilFunc(GL_ALWAYS, 0, 0xff);
+ GL.glDisable(GL_STENCIL_TEST);
+ }
+}
+
+
+void
+ector_gl_engine_path_fill(float *vertex,
+ unsigned int vertex_count EINA_UNUSED,
+ int *stops,
+ unsigned int stop_count)
+{
+ unsigned int i, previous_stop = 0, stop = 0;
+
+ if (!_is_stencil_available())
+ {
+ _update_brush();
+ GL.glVertexAttribPointer(ECTOR_SHAD_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, vertex);
+ for (i = 0 ; i < stop_count; i++)
+ {
+ stop = stops[i];
+ GL.glDrawArrays(GL_TRIANGLE_FAN, previous_stop/2, (stop - previous_stop)/2);
+ previous_stop = stop;
+ }
+ return;
+ }
+
+ _load_simple_program();
+
+ GL.glVertexAttribPointer(ECTOR_SHAD_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, vertex);
+
+ // 1. Disable color writes
+ GL.glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
+
+ // 2. Enable Stencil and draw the shape in stencil
+ GL.glEnable(GL_STENCIL_TEST);
+ GL.glStencilMask(0xff);
+ GL.glClear(GL_STENCIL_BUFFER_BIT);
+ GL.glStencilMask(GL_STENCIL_HIGH_BIT);
+
+ // 3. set the Op for odd/even fill
+ GL.glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit
+
+ // 4. draw the shape
+ for (i = 0 ; i < stop_count; i++)
+ {
+ stop = stops[i];
+ GL.glDrawArrays(GL_TRIANGLE_FAN, previous_stop/2, (stop - previous_stop)/2);
+ previous_stop = stop;
+ }
+
+ // 5. Enable color writes
+ GL.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+
+ // 6. setup stencil op
+ GL.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
+ GL.glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT);
+
+ // 7.draw a bounding rectangle covering the shape
+ float rect_bound[10] = {0, 0 ,
+ ENG->surface.w, 0,
+ ENG->surface.w, ENG->surface.h,
+ 0, ENG->surface.h};
+ GL.glVertexAttribPointer(ECTOR_SHAD_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, rect_bound);
+
+ _update_brush();
+
+ GL.glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ // reset
+ GL.glStencilFunc(GL_ALWAYS, 0, 0xff);
+ GL.glDisable(GL_STENCIL_TEST);
+}
+
+
+void
+ector_gl_engine_surface_copy(GLuint dst_surface, int dst_surface_w, int dst_surface_h,
+ Eina_Rectangle *dest)
+{
+ if (ENG->info.direct_draw) return;
+
+ GL.glDisable(GL_SCISSOR_TEST);
+
+ if (ENG->surface.capability.multisample)
+ {
+ GL.glBindFramebuffer(GL_READ_FRAMEBUFFER, ENG->surface.fbo.id);
+ GL.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_surface);
+ GL.glBlitFramebuffer(ENG->master.clip.x, ENG->master.clip.y, ENG->master.clip.w, ENG->master.clip.h,
+ dest->x, dest->y, dest->w, dest->h,
+ GL_COLOR_BUFFER_BIT,
+ GL_LINEAR);
+ return;
+ }
+
+ // copy texture by drawing a quad
+ GL.glBindFramebuffer(GL_FRAMEBUFFER, dst_surface);
+
+ _update_viewport(dst_surface_w, dst_surface_h);
+
+ if (ENG->info.clear_surface)
+ GL.glClear(GL_COLOR_BUFFER_BIT);
+
+ GL.glUseProgram(ENG->shader.tex->program);
+ GL.glUniformMatrix4fv(ENG->shader.tex->u_mvp, 1, GL_FALSE, ENG->mvp);
+ GL.glUniform4f(ENG->shader.tex->u_pos, 0, 0, 0, 0);
+ _update_color_uniform(ENG->shader.tex->u_color, ENG->info.color);
+
+ GL.glEnableVertexAttribArray(ECTOR_SHAD_VERTEX);
+ GL.glEnableVertexAttribArray(ECTOR_SHAD_TEXUV);
+
+ GL.glActiveTexture(GL_TEXTURE0);
+ GL.glBindTexture(GL_TEXTURE_2D, ENG->surface.fbo.texture);
+ GL.glUniform1i(ENG->shader.tex->u_texture, 0);
+
+ float rect_bound[10] = {dest->x, dest->y ,
+ dest->x + dest->w, dest->y,
+ dest->x + dest->w, dest->y + dest->h,
+ dest->x, dest->y + dest->h};
+ float uv_w = (float)(ENG->master.clip.w)/ ENG->surface.fbo.w;
+ float uv_h = (float)(ENG->master.clip.h)/ ENG->surface.fbo.h;
+ float uv_x = (float)(ENG->master.clip.x)/ ENG->surface.fbo.w;
+ float uv_y = (float)(ENG->master.clip.y)/ ENG->surface.fbo.h;
+ float tex_uv[10] = {uv_x, uv_y ,
+ uv_x + uv_w, uv_y,
+ uv_x + uv_w, uv_y + uv_h,
+ uv_x, uv_y + uv_h};
+
+ GL.glVertexAttribPointer(ECTOR_SHAD_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, rect_bound);
+ GL.glVertexAttribPointer(ECTOR_SHAD_TEXUV, 2, GL_FLOAT, GL_FALSE, 0, tex_uv);
+
+ GL.glEnable(GL_BLEND);
+
+ GL.glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+}
+
+void
+ector_gl_engine_param_color(unsigned int color)
+{
+ ENG->brush.color = color;
+ ENG->brush.g = NULL;
+ ENG->brush.type = Solid;
+}
+
+void
+ector_gl_engine_param_linear_gradient(Ector_Renderer_Gl_Gradient_Data* lg)
+{
+ ENG->brush.g = lg;
+ ENG->brush.type = LinearGradient;
+}
+
+void
+ector_gl_engine_param_radial_gradient(Ector_Renderer_Gl_Gradient_Data* rg)
+{
+ ENG->brush.g = rg;
+ ENG->brush.type = RadialGradient;
+}
+
+void
+ector_gl_engine_param_offset(int x, int y)
+{
+ ENG->offset.x = x;
+ ENG->offset.y = y;
+}
+
+void
+ector_gl_engine_surface_size_set(int width, int height)
+{
+ ENG->surface.w = width;
+ ENG->surface.h = height;
+}
+
+void
+ector_gl_engine_info_set(Eina_Bool direct_draw, Eina_Bool stencil, Eina_Bool clear_surface, Eina_Bool flip, int rotation)
+{
+ ENG->info.direct_draw = direct_draw;
+ ENG->info.stencil = stencil;
+ ENG->info.clear_surface = clear_surface;
+ ENG->info.flip = flip;
+ ENG->info.rotation = rotation;
+}
+
+void
+ector_gl_engine_master_clip_set(Eina_Rectangle *clip)
+{
+ ENG->master.clip.x = clip->x;
+ ENG->master.clip.y = clip->y;
+ ENG->master.clip.w = clip->w;
+ ENG->master.clip.h = clip->h;
+}
+
+void
+ector_gl_engine_master_offset_set(int x, int y)
+{
+ ENG->master.offset.x = x;
+ ENG->master.offset.y = y;
+}
+
+void
+ector_gl_engine_mul_color_set(int mul_color)
+{
+ ENG->info.color = mul_color;
+}
+
+
+void
+ector_gl_engine_init()
+{
+ const char *ector_msaa = NULL;
+
+ if (ENG)
+ {
+ ENG->ref++;
+ return;
+ }
+
+ GL.finalize();
+
+ ENG = calloc(1,sizeof(Ector_Gl_Engine_Data));
+ ENG->ref = 1;
+ GL.finalize();
+
+ ENG->shader.simple = _create_shader_program(vertex_shader, fragment_shader);
+ ENG->shader.tex = _create_shader_program(tex_vertex_shader, tex_fragment_shader);
+ ENG->shader.lg = _create_shader_program(linear_gradient_vertex_shader, linear_gradient_fragment_shader);
+ ENG->shader.rg = _create_shader_program(radial_gradient_vertex_shader, radial_gradient_fragment_shader);
+ _update_lg_uniform();
+ _update_rg_uniform();
+
+ ENG->mvp = malloc(16 * sizeof(float));
+
+ if (GL.version == 3) ENG->surface.capability.multisample = EINA_TRUE;
+
+ if (GL.ext_ms_render_to_tex) ENG->surface.capability.ext_multisample = EINA_TRUE;
+
+ ector_msaa = getenv("ECTOR_MSAA");
+
+ if (ector_msaa)
+ {
+ //@TODO parse the msaa level;
+ ENG->surface.capability.multisample_size = 4;
+ }
+ else
+ {
+ ENG->surface.capability.multisample_size = 4;
+ }
+}
+
+void
+ector_gl_engine_shutdown()
+{
+ if (ENG)
+ {
+ ENG->ref--;
+ if (ENG->ref) return;
+
+ _destroy_shader_program(ENG->shader.simple);
+ _destroy_shader_program(ENG->shader.tex);
+ _destroy_shader_program(ENG->shader.lg);
+ _destroy_shader_program(ENG->shader.rg);
+ _ector_gl_engine_destroy_surface();
+ free(ENG->mvp);
+ free(ENG);
+ ENG = NULL;
+ }
+
+}
#ifndef ECTOR_GL_PRIVATE_H_
#define ECTOR_GL_PRIVATE_H_
-#define SHAD_VERTEX 0
-#define SHAD_TEXUV 1
+#include "ector_private.h"
+#include <Eina.h>
+
+#define ECTOR_SHAD_VERTEX 0
+#define ECTOR_SHAD_TEXUV 1
#define GL_STENCIL_HIGH_BIT 0x80
typedef struct _Ector_Renderer_Gl_Gradient_Data Ector_Renderer_Gl_Gradient_Data;
typedef struct _Ector_Gl_Surface_Data Ector_Gl_Surface_Data;
+typedef struct _Ector_Renderer_Gl_Gradient_Data Ector_Renderer_Gl_Gradient_Data;
typedef struct _Shader_Program Shader_Program;
GLuint u_mvp;
GLuint u_pos;
GLuint u_texture;
+
+ GLuint u_half_viewport_size;
+ struct {
+ GLuint u_linear_data;
+ }linear;
+ struct {
+ GLuint u_fmp;
+ GLuint u_bradius;
+ GLuint u_fmp2_m_radius2;
+ GLuint u_inverse_2_fmp2_m_radius2;
+ GLuint u_sqrfr;
+ }radial;
};
struct _Ector_Gl_Surface_Data
{
struct {
- int x, y;
- } ref_point;
+ GLuint fbo;
+ int w;
+ int h;
+ int rotation;
+ Eina_Bool flip;
+ Eina_Bool clear;
+ Eina_Bool stencil;
+ Eina_Rectangle clip;
+ }context;
+
struct {
- int x, y;
- } offset;
+ Eina_Rectangle geom;
+ int color;
+ }vg;
- Shader_Program *simple_shader;
- Shader_Program *texture_shader;
+ struct {
+ int x, y;
+ } ref_point;
struct {
- int w, h;
- GLuint fbo;
+ int w, h;
+ GLuint fbo;
+ Eina_Bool flip;
+ int rotation;
+ Eina_Bool clear;
} dest_fbo;
- struct {
- int w, h;
- GLuint fbo;
- GLuint texture;
- GLuint rbo_color;
- GLuint rbo_stencil;
- Eina_Bool msaa;
- Eina_Bool ext_msaa;
- int msaa_level;
- } scratch_fbo;
+ int vg_width;
+ int vg_height;
+
+ Eina_Rectangle clip;
+
+ Eina_Bool direct_draw;
};
+// GRADIENT
+
+#define GRADIENT_ARRAY_SIZE 512
+
+typedef struct _Gl_Gradient_Linear_Data
+{
+ float x1, y1, x2, y2;
+ float dx, dy, l;
+} Gl_Gradient_Linear_Data;
+
+typedef struct _Gl_Gradient_Radial_Data
+{
+ float cx, cy, fx, fy, cradius, fradius;
+ float dx, dy, dr, sqrfr, a, inv2a;
+ Eina_Bool extended;
+} Gl_Gradient_Radial_Data;
+
// Gradient related structure
struct _Ector_Renderer_Gl_Gradient_Data
{
Ector_Renderer_Generic_Gradient_Linear_Data *gld;
Ector_Renderer_Generic_Gradient_Radial_Data *grd;
};
- Eina_Bool alpha;
- uint32_t* color_table;
+ union {
+ Gl_Gradient_Linear_Data linear;
+ Gl_Gradient_Radial_Data radial;
+ };
+ Eina_Bool alpha;
+ unsigned int* color_table;
+ GLuint texture;
+};
+
+void update_gradient_texture(Ector_Renderer_Gl_Gradient_Data *gdata);
+void destroy_gradient_texture(Ector_Renderer_Gl_Gradient_Data *gdata);
+
+
+// Ector Gl Engine
+typedef struct _Ector_Gl_Engine_Data Ector_Gl_Engine_Data;
+
+typedef enum _Brush_Type {
+ Solid,
+ LinearGradient,
+ RadialGradient,
+} Brush_Type;
+
+struct _Ector_Gl_Engine_Data
+{
+ struct {
+ Shader_Program *simple;
+ Shader_Program *tex;
+ Shader_Program *lg;
+ Shader_Program *rg;
+ }shader;
+
+ struct {
+ int w, h;
+ struct {
+ int w, h;
+ GLuint id;
+ GLuint texture;
+ GLuint rbo_color;
+ GLuint rbo_stencil;
+ }fbo;
+
+ struct {
+ Eina_Bool multisample;
+ Eina_Bool ext_multisample;
+ int multisample_size;
+ int max_multisample;
+ }capability;
+ } surface;
+
+ struct {
+ Eina_Bool direct_draw; // draw directly to bounded fbo
+ Eina_Bool stencil; // whether stencil buffer available in the bounded fbo
+ Eina_Bool clear_surface; // whether to clear the bounded fbo
+ Eina_Bool flip;
+ int rotation;
+ int color;
+ }info;
+
+ struct {
+ unsigned int color;
+ Ector_Renderer_Gl_Gradient_Data *g;
+ Brush_Type type;
+ }brush;
+
+ struct{
+ Shader_Program *program;
+ unsigned int u_color;
+ int u_pos_x;
+ int u_pos_y;
+ }state;
+
+ struct {
+ int x;
+ int y;
+ }offset;
+
+ struct {
+ Eina_Rectangle clip;
+ struct {
+ int x;
+ int y;
+ }offset;
+ }master;
+
+ float *mvp;
+
+ int ref;
};
+
+void ector_gl_engine_init();
+void ector_gl_engine_shutdown();
+void ector_gl_engine_info_set(Eina_Bool direct_draw, Eina_Bool stencil, Eina_Bool clear_surface, Eina_Bool flip, int rotation);
+Eina_Bool ector_gl_engine_begin();
+void ector_gl_engine_end();
+void ector_gl_engine_surface_size_set(int width, int height);
+void ector_gl_engine_master_clip_set(Eina_Rectangle *clip);
+void ector_gl_engine_master_offset_set(int x, int y);
+void ector_gl_engine_mul_color_set(int mul_color);
+void ector_gl_engine_surface_copy(GLuint dst_surface, int dst_surface_w, int dst_surface_h,
+ Eina_Rectangle *dst);
+
+void ector_gl_engine_param_offset(int x, int y);
+void ector_gl_engine_param_matrix(Eina_Matrix3 *m);
+void ector_gl_engine_param_color(unsigned int color);
+
+void ector_gl_engine_param_linear_gradient(Ector_Renderer_Gl_Gradient_Data* lg);
+void ector_gl_engine_param_radial_gradient(Ector_Renderer_Gl_Gradient_Data* rg);
+
+void ector_gl_engine_fill_set();
+
+void ector_gl_engine_path_fill(float *vertex, unsigned int vertex_count,
+ int *stops, unsigned int stop_count);
+
+void ector_gl_engine_path_stroke(float *vertex, int count);
+
#endif
--- /dev/null
+static const char vertex_shader[] =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "attribute vec4 vertex;\n"
+ "attribute vec2 tex_coord;\n"
+ "uniform mat4 mvp;\n"
+ "uniform vec4 pos;\n"
+ "void main()\n"
+ "{\n"
+ " vec4 new_vert = pos + vertex;\n"
+ " gl_Position = mvp * new_vert;\n"
+ "}\n";
+
+static const char fragment_shader[] =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "# endif\n"
+ "uniform vec4 color;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = color;\n"
+ "}\n";
+
+static const char tex_vertex_shader[] =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "attribute vec4 vertex;\n"
+ "attribute vec2 tex_coord;\n"
+ "uniform mat4 mvp;\n"
+ "uniform vec4 pos;\n"
+ "varying vec2 v_tex_coord;\n"
+ "void main()\n"
+ "{\n"
+ " vec4 new_vert = pos + vertex;\n"
+ " gl_Position = mvp * new_vert;\n"
+ " v_tex_coord = tex_coord;\n"
+ "}\n";
+
+static const char tex_fragment_shader[] =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "# endif\n"
+ "varying vec2 v_tex_coord;\n"
+ "uniform sampler2D texture;\n"
+ "uniform vec4 color;\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = color * texture2D(texture, v_tex_coord);\n"
+ "}\n";
+
+static const char linear_gradient_vertex_shader[] =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "attribute vec4 vertex;\n"
+ "attribute vec2 tex_coord;\n"
+ "uniform mat4 mvp;\n"
+ "uniform vec4 pos;\n"
+ "uniform vec2 half_viewport_size; \n"
+ "uniform vec3 linear_data; \n"
+ "varying float index; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 new_vert = pos + vertex;\n"
+ " gl_Position = mvp * new_vert;\n"
+ " vec2 viewport_coords = (gl_Position.xy + 1.0) * half_viewport_size; \n"
+ " vec3 hTexCoords = vec3(viewport_coords, 1); \n"
+ " index = (dot(linear_data.xy, hTexCoords.xy) * linear_data.z); \n"
+ "}\n";
+
+static const char linear_gradient_fragment_shader[] =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "# endif\n"
+ "uniform sampler2D texture;\n"
+ "varying float index; \n"
+ "void main()\n"
+ "{\n"
+ "vec2 val = vec2(index, 0.5); \n"
+ "gl_FragColor = texture2D(texture, val);\n"
+ "}\n";
+
+
+ // Radial Gradient Brush
+static const char radial_gradient_vertex_shader[] =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "attribute vec4 vertex;\n"
+ "attribute vec2 tex_coord;\n"
+ "uniform mat4 mvp;\n"
+ "uniform vec4 pos;\n"
+ "uniform vec2 half_viewport_size; \n"
+ "uniform vec2 fmp; \n"
+ "uniform vec3 bradius; \n"
+ "varying float b; \n"
+ "varying vec2 A; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 new_vert = pos + vertex;\n"
+ " gl_Position = mvp * new_vert;\n"
+ " vec2 viewport_coords = (gl_Position.xy + 1.0) * half_viewport_size; \n"
+ " vec3 hTexCoords = vec3(viewport_coords, 1); \n"
+ " A = hTexCoords.xy; \n"
+ " b = bradius.x + 2.0 * dot(A, fmp); \n"
+ "}\n";
+
+ static const char radial_gradient_fragment_shader[] =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "# endif\n"
+ "uniform sampler2D texture;\n"
+ "uniform float fmp2_m_radius2; \n"
+ "uniform float inverse_2_fmp2_m_radius2; \n"
+ "uniform float sqrfr; \n"
+ "uniform vec3 bradius; \n"
+ "varying float b; \n"
+ "varying vec2 A; \n"
+ "void main()\n"
+ "{\n"
+ " float c = sqrfr - dot(A, A); \n"
+ " float det = b*b - 4.0*fmp2_m_radius2*c; \n"
+ " vec4 result = vec4(0.0); \n"
+ " if (det >= 0.0) \n"
+ " { \n"
+ " float detSqrt = sqrt(det); \n"
+ " float w = max((-b - detSqrt) * inverse_2_fmp2_m_radius2, (-b + detSqrt) * inverse_2_fmp2_m_radius2); \n"
+ " if (bradius.y + w * bradius.z >= 0.0) \n"
+ " result = texture2D(texture, vec2(w, 0.5)); \n"
+ " } \n"
+ " gl_FragColor = result;\n"
+ "}\n";
{
};
-static const char vertex_shader[] =
- "#ifdef GL_ES\n"
- "precision mediump float;\n"
- "#endif\n"
- "attribute vec4 vertex;\n"
- "attribute vec2 tex_coord;\n"
- "uniform mat4 mvp;\n"
- "uniform vec4 pos;\n"
- "void main()\n"
- "{\n"
- " vec4 new_vert = pos + vertex;\n"
- " gl_Position = mvp * new_vert;\n"
- "}\n";
-
-static const char fragment_shader[] =
- "#ifdef GL_ES\n"
- "precision mediump float;\n"
- "# endif\n"
- "uniform vec4 color;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = color;\n"
- "}\n";
-
-static const char tex_vertex_shader[] =
- "#ifdef GL_ES\n"
- "precision mediump float;\n"
- "#endif\n"
- "attribute vec4 vertex;\n"
- "attribute vec2 tex_coord;\n"
- "uniform mat4 mvp;\n"
- "uniform vec4 pos;\n"
- "varying vec2 v_tex_coord;\n"
- "void main()\n"
- "{\n"
- " vec4 new_vert = pos + vertex;\n"
- " gl_Position = mvp * new_vert;\n"
- " v_tex_coord = tex_coord;\n"
- "}\n";
-
-static const char tex_fragment_shader[] =
- "#ifdef GL_ES\n"
- "precision mediump float;\n"
- "# endif\n"
- "varying vec2 v_tex_coord;\n"
- "uniform sampler2D texture;\n"
- "void main()\n"
- "{\n"
- " gl_FragColor = texture2D(texture, v_tex_coord);\n"
- "}\n";
-
-static void
-init_matrix(float matrix[16])
-{
- matrix[0] = 1.0f;
- matrix[1] = 0.0f;
- matrix[2] = 0.0f;
- matrix[3] = 0.0f;
-
- matrix[4] = 0.0f;
- matrix[5] = 1.0f;
- matrix[6] = 0.0f;
- matrix[7] = 0.0f;
-
- matrix[8] = 0.0f;
- matrix[9] = 0.0f;
- matrix[10] = 1.0f;
- matrix[11] = 0.0f;
-
- matrix[12] = 0.0f;
- matrix[13] = 0.0f;
- matrix[14] = 0.0f;
- matrix[15] = 1.0f;
-}
-
-static void
-matrix_ortho(GLfloat *m,
- GLfloat l, GLfloat r,
- GLfloat t, GLfloat b,
- GLfloat near_, GLfloat far_,
- int rot, int vw, int vh,
- int foc, GLfloat orth)
-{
- GLfloat rotf;
- GLfloat cosv, sinv;
- GLfloat tx, ty;
-
- rotf = (((rot / 90) & 0x3) * M_PI) / 2.0;
-
- tx = -0.5 * (1.0 - orth);
- ty = -0.5 * (1.0 - orth);
-
- if (rot == 90)
- {
- tx += -(vw * 1.0);
- ty += -(vh * 0.0);
- }
- if (rot == 180)
- {
- tx += -(vw * 1.0);
- ty += -(vh * 1.0);
- }
- if (rot == 270)
- {
- tx += -(vw * 0.0);
- ty += -(vh * 1.0);
- }
-
- cosv = cos(rotf);
- sinv = sin(rotf);
-
- m[0] = (2.0 / (r - l)) * ( cosv);
- m[1] = (2.0 / (r - l)) * ( sinv);
- m[2] = 0.0;
- m[3] = 0.0;
-
- m[4] = (2.0 / (t - b)) * (-sinv);
- m[5] = (2.0 / (t - b)) * ( cosv);
- m[6] = 0.0;
- m[7] = 0.0;
-
- m[8] = 0.0;
- m[9] = 0.0;
- m[10] = -(2.0 / (far_ - near_));
- m[11] = 1.0 / (GLfloat)foc;
-
- m[12] = (m[0] * tx) + (m[4] * ty) - ((r + l) / (r - l));
- m[13] = (m[1] * tx) + (m[5] * ty) - ((t + b) / (t - b));
- m[14] = (m[2] * tx) + (m[6] * ty) - ((near_ + far_) / (far_ - near_));
- m[15] = (m[3] * tx) + (m[7] * ty) + orth;
-}
-
-static void
-_destroy_shader_program(Shader_Program *shader)
-{
- if (shader)
- {
- if (shader->v_shader) GL.glDeleteShader(shader->v_shader);
- if (shader->f_shader)GL.glDeleteShader(shader->f_shader);
- if (shader->program) GL.glDeleteProgram(shader->program);
- free(shader);
- }
-}
-static Shader_Program *
-_create_shader_program(const char *v_shader, const char* f_shader)
-{
- Shader_Program *shader = calloc(1, sizeof(Shader_Program));
- GLint ok = 0;
-
- shader->v_shader = GL.glCreateShader(GL_VERTEX_SHADER);
- GL.glShaderSource(shader->v_shader, 1, &v_shader, NULL);
- GL.glCompileShader(shader->v_shader);
- GL.glGetShaderiv(shader->v_shader, GL_COMPILE_STATUS, &ok);
- if (!ok)
- {
- ERR("vertex shader compilation failed ");
- goto fail;
- }
-
- shader->f_shader = GL.glCreateShader(GL_FRAGMENT_SHADER);
- GL.glShaderSource(shader->f_shader, 1, &f_shader, NULL);
- GL.glCompileShader(shader->f_shader);
- GL.glGetShaderiv(shader->f_shader, GL_COMPILE_STATUS, &ok);
- if (!ok)
- {
- ERR("fragment shader compilation failed ");
- goto fail;
- }
-
- shader->program = GL.glCreateProgram();
- GL.glAttachShader(shader->program, shader->v_shader);
- GL.glAttachShader(shader->program, shader->f_shader);
- GL.glBindAttribLocation(shader->program, SHAD_VERTEX, "vertex");
- GL.glBindAttribLocation(shader->program, SHAD_TEXUV, "v_tex_coord");
- GL.glLinkProgram(shader->program);
- GL.glGetProgramiv(shader->program, GL_LINK_STATUS, &ok);
- if (!ok)
- {
- ERR("linking failed for shader program");
- goto fail;
- }
- shader->u_color = GL.glGetUniformLocation(shader->program, "color");
- shader->u_pos = GL.glGetUniformLocation(shader->program, "pos");
- shader->u_mvp = GL.glGetUniformLocation(shader->program, "mvp");
- shader->u_texture = GL.glGetUniformLocation(shader->program, "texture");
- return shader;
-fail:
- _destroy_shader_program(shader);
- return NULL;
-}
-
static Ector_Renderer *
_ector_gl_surface_ector_generic_surface_renderer_factory_new(Eo *obj,
Ector_Gl_Surface_Data *pd EINA_UNUSED,
}
static void
-_ector_gl_surface_path_fill(Eo *obj EINA_UNUSED,
- Ector_Gl_Surface_Data *pd,
- float *vertex,
- unsigned int vertex_count EINA_UNUSED,
- int *stops,
- unsigned int stop_count,
- unsigned int color)
+_ector_gl_surface_context_info_set(Eo *obj EINA_UNUSED, Ector_Gl_Surface_Data *pd, int width, int height, int rotation, Eina_Rectangle *clip, Eina_Bool clear)
{
- unsigned int i, previous_stop = 0, stop = 0;
-
- GL.glUniform4f(pd->simple_shader->u_color, (R_VAL(&color)/255.0), (G_VAL(&color)/255.0), (B_VAL(&color)/255.0), (A_VAL(&color)/255.0));
- GL.glVertexAttribPointer(SHAD_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, vertex);
-
- // 1. Disable color writes
- GL.glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
- // 2. Enable Stencil and draw the shape in stencil
- GL.glEnable(GL_STENCIL_TEST);
- GL.glStencilMask(0xff);
- GL.glClear(GL_STENCIL_BUFFER_BIT);
- GL.glStencilMask(GL_STENCIL_HIGH_BIT);
-
- // 3. set the Op for odd/even fill
- GL.glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit
-
- // 4. draw the shape
- for (i = 0 ; i < stop_count; i++)
- {
- stop = stops[i];
- GL.glDrawArrays(GL_TRIANGLE_FAN, previous_stop/2, (stop - previous_stop)/2);
- previous_stop = stop;
- }
-
- // 5. Enable color writes
- GL.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ GLint current_fbo;
- // 6. setup stencil op
- GL.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
- GL.glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT);
+ GL.glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤t_fbo);
- if (A_VAL(&color) == 255)
- {
- GL.glDisable(GL_BLEND);
- }
- else
+ if (current_fbo) // render to texture
{
- GL.glEnable(GL_BLEND);
+ pd->context.flip = EINA_TRUE;
+ pd->context.rotation = 0;
}
-
- // 7.draw a bounding rectangle covering the shape
- float rect_bound[10] = {0, 0 , pd->dest_fbo.w, 0, pd->dest_fbo.w, pd->dest_fbo.h, 0, pd->dest_fbo.h};
- GL.glVertexAttribPointer(SHAD_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, rect_bound);
- GL.glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- // reset
- GL.glStencilFunc(GL_ALWAYS, 0, 0xff);
- GL.glDisable(GL_STENCIL_TEST);
-}
-
-static void
-_ector_gl_surface_path_stroke(Eo *obj EINA_UNUSED,
- Ector_Gl_Surface_Data *pd,
- float *vertex,
- unsigned int vertex_count,
- unsigned int color)
-{
- GL.glUniform4f(pd->simple_shader->u_color, (R_VAL(&color)/255.0), (G_VAL(&color)/255.0), (B_VAL(&color)/255.0), (A_VAL(&color)/255.0));
- GL.glVertexAttribPointer(SHAD_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, vertex);
-
- if (A_VAL(&color) == 255)
+ else // default frame buffer
{
- GL.glDisable(GL_BLEND);
- GL.glDrawArrays(GL_TRIANGLE_STRIP, 0, vertex_count/2);
- return;
+ pd->context.flip = EINA_FALSE;
+ pd->context.rotation = rotation;
}
- else
- {
- GL.glEnable(GL_BLEND);
-
- GL.glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes
-
- GL.glEnable(GL_STENCIL_TEST);
- GL.glStencilMask(0xff);
- GL.glClear(GL_STENCIL_BUFFER_BIT);
- GL.glStencilMask(GL_STENCIL_HIGH_BIT);
-
- GL.glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
-
- GL.glStencilFunc(GL_ALWAYS, GL_STENCIL_HIGH_BIT, 0xff);
- GL.glDrawArrays(GL_TRIANGLE_STRIP, 0, vertex_count/2); // here the shape is drawn in the stencil
+ //@TODO update the stencil info
+ pd->context.stencil = EINA_FALSE;
- // Enable color writes & disable stencil writes
- GL.glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ pd->context.fbo = current_fbo;
+ pd->context.w = width;
+ pd->context.h = height;
+ pd->context.clear = clear;
- GL.glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
- // Pass when high bit is set, replace stencil value with 0
- GL.glStencilFunc(GL_NOTEQUAL, 0, GL_STENCIL_HIGH_BIT);
+ pd->context.clip.x = clip->x;
+ pd->context.clip.y = clip->y;
+ pd->context.clip.w = clip->w;
+ pd->context.clip.h = clip->h;
- // draw a rectangle
- float rect_bound[10] = {0, 0 , pd->dest_fbo.w, 0, pd->dest_fbo.w, pd->dest_fbo.h, 0, pd->dest_fbo.h};
- GL.glVertexAttribPointer(SHAD_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, rect_bound);
- GL.glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- // reset
- GL.glStencilFunc(GL_ALWAYS, 0, 0xff);
- GL.glDisable(GL_STENCIL_TEST);
- }
}
-static void
-_delete_fbo(Ector_Gl_Surface_Data *pd)
-{
- if (!pd->scratch_fbo.fbo) return;
-
- if (pd->scratch_fbo.rbo_color)
- GL.glDeleteRenderbuffers(1, &(pd->scratch_fbo.rbo_color));
- if (pd->scratch_fbo.rbo_stencil)
- GL.glDeleteRenderbuffers(1, &(pd->scratch_fbo.rbo_stencil));
- if (pd->scratch_fbo.texture)
- GL.glDeleteTextures(1, &(pd->scratch_fbo.texture));
- if (pd->scratch_fbo.fbo)
- GL.glDeleteFramebuffers(1, &(pd->scratch_fbo.fbo));
-
- pd->scratch_fbo.fbo = 0;
- pd->scratch_fbo.rbo_color = 0;
- pd->scratch_fbo.rbo_stencil = 0;
- pd->scratch_fbo.texture = 0;
-}
-
-static void
-_create_msaa_fbo_rbo(Ector_Gl_Surface_Data *pd)
+void
+_ector_gl_surface_vg_info_set(Eo *obj EINA_UNUSED, Ector_Gl_Surface_Data *pd, Eina_Rectangle *geom, int color)
{
- GL.glGenRenderbuffers(1, &pd->scratch_fbo.rbo_color);
- GL.glBindRenderbuffer(GL_RENDERBUFFER, pd->scratch_fbo.rbo_color);
- GL.glRenderbufferStorageMultisample(GL_RENDERBUFFER,
- pd->scratch_fbo.msaa_level,
- GL_RGBA,
- pd->scratch_fbo.w, pd->scratch_fbo.h);
-
- // create a 4x MSAA renderbuffer object for depthbuffer
- GL.glGenRenderbuffers(1, &pd->scratch_fbo.rbo_stencil);
- GL.glBindRenderbuffer(GL_RENDERBUFFER, pd->scratch_fbo.rbo_stencil);
- GL.glRenderbufferStorageMultisample(GL_RENDERBUFFER,
- pd->scratch_fbo.msaa_level,
- GL_STENCIL_INDEX8,
- pd->scratch_fbo.w, pd->scratch_fbo.h);
-
-
- GL.glGenFramebuffers(1, &pd->scratch_fbo.fbo);
- GL.glBindFramebuffer(GL_FRAMEBUFFER, pd->scratch_fbo.fbo);
-
- // attach colorbuffer image to FBO
- GL.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_RENDERBUFFER,
- pd->scratch_fbo.rbo_color);
-
- // attach stencil buffer to FBO
- GL.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
- GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER,
- pd->scratch_fbo.rbo_stencil);
-
- // check FBO status
- GLenum status = GL.glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if(status != GL_FRAMEBUFFER_COMPLETE)
- {
- ERR("cretaing MSAA fbo rbo failed");
- GL.glDeleteRenderbuffers(1, &(pd->scratch_fbo.rbo_color));
- GL.glDeleteRenderbuffers(1, &(pd->scratch_fbo.rbo_stencil));
- GL.glDeleteFramebuffers(1, &(pd->scratch_fbo.fbo));
- pd->scratch_fbo.fbo = 0;
- }
+ pd->vg.geom.x = geom->x;
+ pd->vg.geom.y = geom->y;
+ pd->vg.geom.w = geom->w;
+ pd->vg.geom.h = geom->h;
+ pd->vg.color = color;
}
static void
-_create_msaa_fbo_texture_ext(Ector_Gl_Surface_Data *pd)
+_ector_gl_surface_draw_begin(Eo *obj EINA_UNUSED, Ector_Gl_Surface_Data *pd EINA_UNUSED)
{
- GL.glGenTextures(1, &pd->scratch_fbo.texture);
- GL.glBindTexture(GL_TEXTURE_2D, pd->scratch_fbo.texture);
- GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- GL.glTexImage2D(GL_TEXTURE_2D, 0,
- GL_RGBA, pd->scratch_fbo.w, pd->scratch_fbo.h, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, NULL);
- GL.glBindTexture(GL_TEXTURE_2D, 0);
-
-
- // create a MSAA renderbuffer object for stencil buffer
- GL.glGenRenderbuffers(1, &pd->scratch_fbo.rbo_stencil);
- GL.glBindRenderbuffer(GL_RENDERBUFFER, pd->scratch_fbo.rbo_stencil);
- GL.glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER,
- pd->scratch_fbo.msaa_level,
- GL_STENCIL_INDEX8,
- pd->scratch_fbo.w, pd->scratch_fbo.h);
-
-
- GL.glGenFramebuffers(1, &pd->scratch_fbo.fbo);
- GL.glBindFramebuffer(GL_FRAMEBUFFER, pd->scratch_fbo.fbo);
-
- // attach texture to FBO
- GL.glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D,
- pd->scratch_fbo.texture,
- 0,
- pd->scratch_fbo.msaa_level);
- // attach stencil buffer to FBO
- GL.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
- GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER,
- pd->scratch_fbo.rbo_stencil);
-
- // check FBO status
- GLenum status = GL.glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if(status != GL_FRAMEBUFFER_COMPLETE)
+ if (pd->direct_draw)
{
- ERR("cretaing MSAA fbo texture failed");
- GL.glDeleteTextures(1, &(pd->scratch_fbo.texture));
- GL.glDeleteRenderbuffers(1, &(pd->scratch_fbo.rbo_stencil));
- GL.glDeleteFramebuffers(1, &(pd->scratch_fbo.fbo));
- pd->scratch_fbo.fbo = 0;
+ ector_gl_engine_surface_size_set(pd->context.w, pd->context.h);
+ ector_gl_engine_master_clip_set(&(pd->context.clip));
+ ector_gl_engine_master_offset_set(pd->vg.geom.x, pd->vg.geom.y);
+ ector_gl_engine_info_set(pd->direct_draw, pd->context.stencil,
+ pd->context.clear, pd->context.flip, pd->context.rotation);
}
-}
-
-static void
-_create_fbo_texture(Ector_Gl_Surface_Data *pd)
-{
- GL.glGenTextures(1, &pd->scratch_fbo.texture);
- GL.glBindTexture(GL_TEXTURE_2D, pd->scratch_fbo.texture);
- GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- GL.glTexImage2D(GL_TEXTURE_2D, 0,
- GL_RGBA, pd->scratch_fbo.w, pd->scratch_fbo.h, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, NULL);
- GL.glBindTexture(GL_TEXTURE_2D, 0);
-
-
- GL.glGenRenderbuffers(1, &pd->scratch_fbo.rbo_stencil);
- GL.glBindRenderbuffer(GL_RENDERBUFFER, pd->scratch_fbo.rbo_stencil);
- GL.glRenderbufferStorage(GL_RENDERBUFFER,
- GL_STENCIL_INDEX8,
- pd->scratch_fbo.w, pd->scratch_fbo.h);
-
-
- GL.glGenFramebuffers(1, &pd->scratch_fbo.fbo);
- GL.glBindFramebuffer(GL_FRAMEBUFFER, pd->scratch_fbo.fbo);
-
- // attach texture to FBO
- GL.glFramebufferTexture2D(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D,
- pd->scratch_fbo.texture,
- 0);
-
- // attach stencil buffer to FBO
- GL.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
- GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER,
- pd->scratch_fbo.rbo_stencil);
-
- // check FBO status
- GLenum status = GL.glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if(status != GL_FRAMEBUFFER_COMPLETE)
+ else
{
- ERR("cretaing normal fbo texture failed");
- GL.glDeleteTextures(1, &(pd->scratch_fbo.texture));
- GL.glDeleteRenderbuffers(1, &(pd->scratch_fbo.rbo_stencil));
- GL.glDeleteFramebuffers(1, &(pd->scratch_fbo.fbo));
- pd->scratch_fbo.fbo = 0;
- }
-}
-
-
-Eina_Bool
-_update_scratch_fbo(Ector_Gl_Surface_Data *pd, int width, int height)
-{
- GLint current_fbo;
+ Eina_Rectangle vg_clip = {0, 0, pd->vg.geom.w, pd->vg.geom.h};
+ Eina_Rectangle ctx_clip;
+ // translate clip to vg co-ordinate
+ ctx_clip.x = pd->context.clip.x - pd->vg.geom.x;
+ ctx_clip.y = pd->context.clip.y - pd->vg.geom.y;
+ ctx_clip.w = pd->context.clip.w;
+ ctx_clip.h = pd->context.clip.h;
- GL.glGetIntegerv(GL_FRAMEBUFFER_BINDING, ¤t_fbo);
- // update dest info
- pd->dest_fbo.fbo = current_fbo;
- pd->dest_fbo.w = width;
- pd->dest_fbo.h = height;
-
- if (pd->scratch_fbo.w >= width && pd->scratch_fbo.h >= height)
- {
- // no need to update the scratch buffer
- GL.glBindFramebuffer(GL_FRAMEBUFFER, pd->scratch_fbo.fbo);
- return EINA_TRUE;
+ if (!eina_rectangle_intersection(&vg_clip, &ctx_clip))
+ return;
+ ector_gl_engine_surface_size_set(pd->vg.geom.w, pd->vg.geom.h);
+ ector_gl_engine_master_clip_set(&vg_clip);
+ ector_gl_engine_master_offset_set(0, 0);
+ ector_gl_engine_info_set(pd->direct_draw, EINA_FALSE, EINA_TRUE, EINA_TRUE, 0);
}
- // delete old buffer if any
- _delete_fbo(pd);
-
- // update the new size
- pd->scratch_fbo.w = pd->dest_fbo.w > pd->scratch_fbo.w ? pd->dest_fbo.w : pd->scratch_fbo.w;
- pd->scratch_fbo.h = pd->dest_fbo.h > pd->scratch_fbo.h ? pd->dest_fbo.h : pd->scratch_fbo.h;
+ ector_gl_engine_mul_color_set(pd->vg.color);
- if (pd->scratch_fbo.msaa)
- {
- _create_msaa_fbo_rbo(pd);
- }
- else if (pd->scratch_fbo.ext_msaa)
- {
- _create_msaa_fbo_texture_ext(pd);
- }
- else
- {
- _create_fbo_texture(pd);
- }
- return EINA_TRUE;
+ ector_gl_engine_begin();
}
-
-void
-_ector_gl_surface_surface_set(Eo *obj EINA_UNUSED,
- Ector_Gl_Surface_Data *pd,
- void *pixels EINA_UNUSED, unsigned int width,
- unsigned int height, unsigned int stride EINA_UNUSED)
+static void
+_ector_gl_surface_draw_end(Eo *obj EINA_UNUSED, Ector_Gl_Surface_Data *pd)
{
- if (pixels)
+ if (!pd->direct_draw)
{
- if (!_update_scratch_fbo(pd, width, height))
- return;
-
- float mvp[16];
- GL.glViewport(0, 0, pd->dest_fbo.w, pd->dest_fbo.h);
- GL.glClearStencil(0);
- GL.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- GL.glClearColor(0, 0, 0, 0);
- GL.glDisable(GL_DEPTH_TEST);
- GL.glDisable(GL_BLEND);
- GL.glDisable(GL_STENCIL_TEST);
- GL.glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
- init_matrix(mvp);
- matrix_ortho(mvp,0, pd->dest_fbo.w, pd->dest_fbo.h, 0,-1000000.0, 1000000.0,0, pd->dest_fbo.w, pd->dest_fbo.h,1, 1.0);
- GL.glUseProgram(pd->simple_shader->program);
- GL.glUniformMatrix4fv(pd->simple_shader->u_mvp, 1, GL_FALSE, mvp);
- GL.glEnableVertexAttribArray(SHAD_VERTEX);
+ if (!eina_rectangle_intersection(&(pd->vg.geom), &(pd->context.clip)))
+ goto end;
+ ector_gl_engine_info_set(pd->direct_draw, pd->context.stencil,
+ pd->context.clear, pd->context.flip, pd->context.rotation);
+ ector_gl_engine_surface_copy(pd->context.fbo, pd->context.w, pd->context.h, &(pd->vg.geom));
}
- else
- {
- if (pd->scratch_fbo.msaa)
- {
- GL.glBindFramebuffer(GL_READ_FRAMEBUFFER, pd->scratch_fbo.fbo);
- GL.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, pd->dest_fbo.fbo);
- GL.glBlitFramebuffer(0, 0, pd->dest_fbo.w, pd->dest_fbo.h,
- 0, 0, pd->dest_fbo.w, pd->dest_fbo.h,
- GL_COLOR_BUFFER_BIT,
- GL_LINEAR);
- }
- else
- {
- float mvp[16];
- GL.glBindFramebuffer(GL_FRAMEBUFFER, pd->dest_fbo.fbo);
- GL.glViewport(0, 0, pd->dest_fbo.w, pd->dest_fbo.h);
- GL.glClearColor(0, 0, 0, 0);
- GL.glDisable(GL_BLEND);
- GL.glClear(GL_COLOR_BUFFER_BIT);
- init_matrix(mvp);
- matrix_ortho(mvp,0, pd->dest_fbo.w, pd->dest_fbo.h, 0,-1000000.0, 1000000.0,0, pd->dest_fbo.w, pd->dest_fbo.h,1, 1.0);
- GL.glUseProgram(pd->texture_shader->program);
- GL.glUniformMatrix4fv(pd->texture_shader->u_mvp, 1, GL_FALSE, mvp);
- GL.glUniform4f(pd->texture_shader->u_pos, 0, 0, 0, 0);
- GL.glEnableVertexAttribArray(SHAD_VERTEX);
- GL.glEnableVertexAttribArray(SHAD_TEXUV);
- GL.glActiveTexture(GL_TEXTURE0);
- GL.glBindTexture(GL_TEXTURE_2D, pd->scratch_fbo.texture);
- GL.glUniform1i(pd->texture_shader->u_texture, 0);
- float rect_bound[10] = {0, 0 , pd->dest_fbo.w, 0, pd->dest_fbo.w, pd->dest_fbo.h, 0, pd->dest_fbo.h};
- float w_r = (float)pd->dest_fbo.w/ pd->scratch_fbo.w;
- float h_r = (float)pd->dest_fbo.h/ pd->scratch_fbo.h;
- float tex_uv[10] = {0, 0 , w_r, 0, w_r, h_r, 0, h_r};
- GL.glVertexAttribPointer(SHAD_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, rect_bound);
- GL.glVertexAttribPointer(SHAD_TEXUV, 2, GL_FLOAT, GL_FALSE, 0, tex_uv);
- GL.glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
- }
-}
-
-static void
-_ector_gl_surface_offset(Eo *obj EINA_UNUSED,
- Ector_Gl_Surface_Data *pd, int x, int y)
-{
- pd->offset.x = x;
- pd->offset.y = y;
- GL.glUniform4f(pd->simple_shader->u_pos, pd->ref_point.x + pd->offset.x, pd->ref_point.y + pd->offset.y, 0, 0);
-}
-
-void
-_ector_gl_surface_surface_get(Eo *obj EINA_UNUSED,
- Ector_Gl_Surface_Data *pd EINA_UNUSED,
- void **pixels EINA_UNUSED, unsigned int *width EINA_UNUSED,
- unsigned int *height EINA_UNUSED, unsigned int *stride EINA_UNUSED)
-{
-
+end:
+ ector_gl_engine_end();
}
static Eo *
_ector_gl_surface_eo_base_constructor(Eo *obj,
Ector_Gl_Surface_Data *pd EINA_UNUSED)
{
- const char *ector_msaa = NULL;
-
obj = eo_do_super_ret(obj, ECTOR_GL_SURFACE_CLASS, obj, eo_constructor());
- GL.finalize();
+ ector_gl_engine_init();
- pd->simple_shader = _create_shader_program(vertex_shader, fragment_shader);
- pd->texture_shader = _create_shader_program(tex_vertex_shader, tex_fragment_shader);
- ector_msaa = getenv("ECTOR_MSAA");
- if (ector_msaa)
- {
- //@TODO parse the msaa level;
- pd->scratch_fbo.msaa_level = 4;
- }
- else
- {
- pd->scratch_fbo.msaa_level = 4;
- }
-
- if (GL.version == 3)
- pd->scratch_fbo.msaa = EINA_TRUE;
- if (GL.ext_ms_render_to_tex)
- pd->scratch_fbo.ext_msaa = EINA_TRUE;
+ pd->direct_draw = EINA_FALSE;
return obj;
}
_ector_gl_surface_eo_base_destructor(Eo *obj EINA_UNUSED,
Ector_Gl_Surface_Data *pd EINA_UNUSED)
{
- _destroy_shader_program(pd->simple_shader);
- _destroy_shader_program(pd->texture_shader);
- _delete_fbo(pd);
+ ector_gl_engine_shutdown();
eo_do_super(obj, ECTOR_GL_SURFACE_CLASS, eo_destructor());
}
-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->ref_point.x = x;
- pd->ref_point.y = y;
-}
#include "ector_gl_surface.eo.c"
#include "ector_renderer_gl_base.eo.c"
eo_prefix: ector_gl_surface;
legacy_prefix: null;
methods {
- @property surface {
- set {
- }
- get {
- }
- values {
- pixels: void *;
- width: uint32_t;
- height: uint32_t;
- stride: uint32_t;
+ context_info_set {
+ params {
+ width: int;
+ height: int;
+ rotation: int;
+ clip: Eina_Rectangle *;
+ clear: Eina_Bool;
}
}
- offset {
- params {
- x:int;
- y:int;
- }
+ vg_info_set {
+ params {
+ geom: Eina_Rectangle *;
+ color: int;
+ }
}
- path_fill {
- params {
- vertex:float *;
- vertex_count: uint32_t;
- stops: int *;
- stop_count: uint32_t;
- color: uint32_t;
- }
+
+ draw_begin {
+ params {
+ }
}
- path_stroke {
- params {
- vertex:float *;
- vertex_count: uint32_t;
- color: uint32_t;
- }
+ draw_end {
+ params {
+ }
}
}
implements {
Ector.Generic.Surface.renderer_factory_new;
- Ector.Generic.Surface.reference_point.set;
Eo.Base.destructor;
Eo.Base.constructor;
}
typedef struct _Ector_Renderer_Gl_Shape_Data Ector_Renderer_Gl_Shape_Data;
struct _Ector_Renderer_Gl_Shape_Data
{
- Eo *surface;
Efl_Gfx_Shape_Public *public_shape;
Ector_Renderer_Generic_Shape_Data *shape;
Ector_Renderer_Generic_Base_Data *base;
+
+ Triangulator_Simple *filler;
+ Triangulator_Stroker *stroker;
};
static Eina_Bool
if (pd->shape->stroke.fill)
eo_do(pd->shape->stroke.fill, ector_renderer_prepare());
- if (!pd->surface)
- {
- eo_do(obj, pd->surface = eo_parent_get());
- if (!pd->surface)
- return EINA_FALSE;
- }
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_generate_stroke_data(Ector_Renderer_Gl_Shape_Data *pd)
+{
+ if (pd->stroker) return EINA_FALSE;
+
+ if (!pd->shape->stroke.fill &&
+ ((pd->public_shape->stroke.color.a == 0) ||
+ (pd->public_shape->stroke.width < 0.01)))
+ return EINA_FALSE;
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_generate_shape_data(Ector_Renderer_Gl_Shape_Data *pd)
+{
+ if (pd->filler) return EINA_FALSE;
+
+ if (!pd->shape->fill && (pd->base->color.a == 0)) return EINA_FALSE;
return EINA_TRUE;
}
+
static void _shape_transform(double *pts, int count , Eina_Matrix3 *m)
{
int i;
}
}
+static void
+_update_triangulators(Eo *obj, Ector_Renderer_Gl_Shape_Data *pd)
+{
+ const Efl_Gfx_Path_Command *cmds = NULL;
+ const double *pts;
+ double *new_pts;
+ unsigned int cmd_count = 0, pt_count = 0;
+ Eina_Bool cleanup = EINA_FALSE;
+
+ eo_do(obj, efl_gfx_shape_path_get(&cmds, &pts));
+ if (cmds && (_generate_stroke_data(pd) || _generate_shape_data(pd)))
+ {
+ eo_do(obj, efl_gfx_shape_path_length_get(&cmd_count, &pt_count));
+
+ if (pd->base->m &&
+ (eina_matrix3_type_get(pd->base->m) != EINA_MATRIX_TYPE_IDENTITY))
+ {
+ new_pts = malloc(sizeof(double) * pt_count);
+ memcpy(new_pts, pts, sizeof(double) * pt_count);
+ _shape_transform(new_pts, pt_count, pd->base->m);
+ cleanup = EINA_TRUE;
+ }
+ else
+ {
+ new_pts = (double *)pts;
+ }
+
+ //shape triangulator creation
+ if (_generate_shape_data(pd))
+ {
+ pd->filler = triangulator_simple_new();
+ triangulator_simple_process(pd->filler, cmds, new_pts, 0);
+ }
+
+ //stroke triangulator creation
+ if ( _generate_stroke_data(pd))
+ {
+ pd->stroker = triangulator_stroker_new();
+ triangulator_stroker_stroke_set(pd->stroker,
+ (pd->public_shape->stroke.width * pd->public_shape->stroke.scale),
+ pd->public_shape->stroke.cap,
+ pd->public_shape->stroke.join,
+ pd->base->m);
+
+ triangulator_stroker_process(pd->stroker, cmds, new_pts, cmd_count, pt_count);
+ }
+ if (cleanup) free(new_pts);
+ }
+}
+
static Eina_Bool
_ector_renderer_gl_shape_ector_renderer_generic_base_draw(Eo *obj EINA_UNUSED,
Ector_Rop op EINA_UNUSED, Eina_Array *clips EINA_UNUSED,
unsigned int mul_col EINA_UNUSED)
{
- const Efl_Gfx_Path_Command *cmds = NULL;
- const double *pts = NULL;
- double *new_pts = NULL;
- unsigned int cmd_count = 0, pt_count = 0;
- int count;
float *vertex;
+ int *stops , count, stop_count;
+ unsigned int color;
- eo_do(obj, efl_gfx_shape_path_get(&cmds, &pts));
- eo_do(obj, efl_gfx_shape_path_length_get(&cmd_count, &pt_count));
- if (!cmd_count) return EINA_FALSE;
+ _update_triangulators(obj, pd);
- new_pts = malloc(sizeof(double) * pt_count);
- memcpy(new_pts, pts, sizeof(double) * pt_count);
- _shape_transform(new_pts, pt_count, pd->base->m);
+ ector_gl_engine_param_offset(pd->base->origin.x, pd->base->origin.y);
- eo_do(pd->surface, ector_gl_surface_offset(pd->base->origin.x, pd->base->origin.y));
- if (pd->base->color.a > 0)
- {
- unsigned int fill_color = ECTOR_ARGB_JOIN(pd->base->color.a, pd->base->color.r, pd->base->color.g, pd->base->color.b);
- unsigned int res_color = ECTOR_MUL4_SYM(fill_color, mul_col);
- Triangulator_Simple *s = triangulator_simple_new();
- triangulator_simple_process(s, cmds, new_pts, 0);
- vertex = eina_inarray_nth(s->vertices, 0);
- count = eina_inarray_count(s->vertices);
- int stop_count = eina_inarray_count(s->stops);
- int *stops = eina_inarray_nth(s->stops, 0);
- eo_do(pd->surface, ector_gl_surface_path_fill(vertex, count, stops, stop_count, res_color));
- triangulator_simple_free(s);
- }
- if (pd->public_shape->stroke.color.a > 0)
+ if (pd->filler)
{
- unsigned int stroke_color = ECTOR_ARGB_JOIN(pd->public_shape->stroke.color.a, pd->public_shape->stroke.color.r,
- pd->public_shape->stroke.color.g, pd->public_shape->stroke.color.b);
- unsigned int res_color = ECTOR_MUL4_SYM(stroke_color, mul_col);
- Triangulator_Stroker *s = triangulator_stroker_new();
- triangulator_stroker_stroke_set(s, (pd->public_shape->stroke.width * pd->public_shape->stroke.scale),
- pd->public_shape->stroke.cap, pd->public_shape->stroke.join, pd->base->m);
-
- triangulator_stroker_process(s, cmds, new_pts, cmd_count, pt_count);
- vertex = eina_inarray_nth(s->vertices, 0);
- count = eina_inarray_count(s->vertices);
- eo_do(pd->surface, ector_gl_surface_path_stroke(vertex, count, res_color));
- triangulator_stroker_free(s);
+ if (pd->shape->fill)
+ eo_do(pd->shape->fill, ector_renderer_gl_base_fill());
+ else
+ {
+ color = ECTOR_ARGB_JOIN(pd->base->color.a,
+ pd->base->color.r,
+ pd->base->color.g,
+ pd->base->color.b);
+ color = ECTOR_MUL4_SYM(color, mul_col);
+ ector_gl_engine_param_color(color);
+ }
+
+ vertex = eina_inarray_nth(pd->filler->vertices, 0);
+ count = eina_inarray_count(pd->filler->vertices);
+ stop_count = eina_inarray_count(pd->filler->stops);
+ stops = eina_inarray_nth(pd->filler->stops, 0);
+
+ ector_gl_engine_path_fill(vertex, count, stops, stop_count);
}
- free(new_pts);
+
+ if (pd->stroker)
+ {
+ if (pd->shape->stroke.fill)
+ eo_do(pd->shape->stroke.fill, ector_renderer_gl_base_fill());
+ else
+ {
+ color = ECTOR_ARGB_JOIN(pd->public_shape->stroke.color.a,
+ pd->public_shape->stroke.color.r,
+ pd->public_shape->stroke.color.g,
+ pd->public_shape->stroke.color.b);
+ color = ECTOR_MUL4_SYM(color, mul_col);
+ ector_gl_engine_param_color(color);
+ }
+
+ vertex = eina_inarray_nth(pd->stroker->vertices, 0);
+ count = eina_inarray_count(pd->stroker->vertices);
+
+ ector_gl_engine_path_stroke(vertex, count);
+ }
+
return EINA_TRUE;
}
+static void
+_clear_path_compute_data(Ector_Renderer_Gl_Shape_Data *pd)
+{
+ if (pd->filler) triangulator_simple_free(pd->filler);
+ if (pd->stroker) triangulator_stroker_free(pd->stroker);
+
+ pd->filler = NULL;
+ pd->stroker = NULL;
+}
+
static Eina_Bool
_ector_renderer_gl_shape_ector_renderer_gl_base_fill(Eo *obj EINA_UNUSED,
Ector_Renderer_Gl_Shape_Data *pd EINA_UNUSED)
{
eo_do_super(obj, ECTOR_RENDERER_GL_SHAPE_CLASS, efl_gfx_shape_path_set(op, points));
+
+ _clear_path_compute_data(pd);
}
const Eo_Event_Description *desc EINA_UNUSED,
void *event_info EINA_UNUSED)
{
+ Ector_Renderer_Gl_Shape_Data *pd = data;
+
+ _clear_path_compute_data(pd);
return EINA_TRUE;
}
// call explicit API to free shape data.
eo_do(obj, efl_gfx_shape_reset());
+ _clear_path_compute_data(pd);
+
eo_data_xunref(obj, pd->public_shape, obj);
eo_data_xunref(obj, pd->shape, obj);
eo_data_xunref(obj, pd->base, obj);
static void
eng_ector_begin(void *data EINA_UNUSED, void *context EINA_UNUSED, Ector_Surface *ector,
- void *surface, Eina_Bool surface_clear EINA_UNUSED,
- int x, int y, int width EINA_UNUSED, int height EINA_UNUSED,
+ void *surface, Eina_Bool surface_clear,
+ int x, int y, int width, int height,
Eina_Bool do_async EINA_UNUSED)
{
int w, h, stride;
{
Evas_Engine_GL_Context *gl_context;
Render_Engine_GL_Generic *re = data;
+ RGBA_Draw_Context *dc;
+ Eina_Rectangle clip;
+ int mul_color = 0xffffffff;
re->window_use(re->software.ob);
gl_context = re->window_gl_context_get(re->software.ob);
evas_gl_common_context_target_surface_set(gl_context, surface);
+
+ // handle clip
+ dc = gl_context->dc;
+ if (surface_clear)
+ {
+ clip.x = 0;
+ clip.y = 0;
+ clip.w = width;
+ clip.h = height;
+ }
+ else
+ {
+ if (dc->clip.use)
+ {
+ clip.x = dc->clip.x;
+ clip.y = dc->clip.y;
+ clip.w = dc->clip.w;
+ clip.h = dc->clip.h;
+ // clip the clip rect to surface boundary.
+ RECTS_CLIP_TO_RECT(clip.x, clip.y, clip.w, clip.h, 0, 0, glim->w, glim->h);
+ }
+ else
+ {
+ clip.x = 0;
+ clip.y = 0;
+ clip.w = glim->w;
+ clip.h = glim->h;
+ }
+
+ mul_color = ector_color_multiply(dc->mul.use ? dc->mul.col : 0xffffffff, dc->col.col);
+
+ }
+ Eina_Rectangle vg_rect = {x, y, width, height};
eo_do(ector,
- ector_gl_surface_set(glim, glim->w, glim->h, 0),
- ector_surface_reference_point_set(x, y));
+ ector_gl_surface_vg_info_set(&vg_rect, mul_color),
+ ector_gl_surface_context_info_set(glim->w, glim->h, gl_context->rot, &clip, surface_clear),
+ ector_gl_surface_draw_begin());
return;
}
if (use_gl)
{
- eo_do(ector, ector_gl_surface_set(NULL, 0, 0, 0));
+ eo_do(ector, ector_gl_surface_draw_end());
return;
}