"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"
" 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])
{
m[15] = (m[3] * tx) + (m[7] * ty) + orth;
}
-static GLuint
-_init_shader()
+static void
+_destroy_shader_program(Shader_Program *shader)
{
- const char *p;
- unsigned int program;
- unsigned int vtx_shader;
- unsigned int fgmt_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;
- p = vertex_shader;
- vtx_shader = GL.glCreateShader(GL_VERTEX_SHADER);
- GL.glShaderSource(vtx_shader, 1, &p, NULL);
- GL.glCompileShader(vtx_shader);
- GL.glGetShaderiv(vtx_shader, GL_COMPILE_STATUS, &ok);
+ 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 ");
- GL.glDeleteShader(vtx_shader);
- return 0;
+ goto fail;
}
- p = fragment_shader;
- fgmt_shader = GL.glCreateShader(GL_FRAGMENT_SHADER);
- GL.glShaderSource(fgmt_shader, 1, &p, NULL);
- GL.glCompileShader(fgmt_shader);
- GL.glGetShaderiv(fgmt_shader, GL_COMPILE_STATUS, &ok);
+ 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 ");
- GL.glDeleteShader(fgmt_shader);
- return 0;
+ goto fail;
}
- program = GL.glCreateProgram();
- GL.glAttachShader(program, vtx_shader);
- GL.glAttachShader(program, fgmt_shader);
- GL.glBindAttribLocation(program, SHAD_VERTEX, "vertex");
- GL.glLinkProgram(program);
- GL.glGetProgramiv(program, GL_LINK_STATUS, &ok);
+ 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");
- GL.glDeleteShader(vtx_shader);
- GL.glDeleteShader(fgmt_shader);
- return 0;
+ goto fail;
}
- return program;
+ 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,
{
unsigned int i, previous_stop = 0, stop = 0;
- GL.glUniform4f(pd->uniform_color, (R_VAL(&color)/255.0), (G_VAL(&color)/255.0), (B_VAL(&color)/255.0), (A_VAL(&color)/255.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
unsigned int vertex_count,
unsigned int color)
{
- GL.glUniform4f(pd->uniform_color, (R_VAL(&color)/255.0), (G_VAL(&color)/255.0), (B_VAL(&color)/255.0), (A_VAL(&color)/255.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);
if (A_VAL(&color) == 255)
}
}
-Eina_Bool
-_update_scratch_fbo(Ector_Gl_Surface_Data *pd, int width, int height)
+static void
+_delete_fbo(Ector_Gl_Surface_Data *pd)
{
- GLint current_fbo;
-
- 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.msaa) return EINA_TRUE;
-
- 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;
- }
-
- // delete old buffer if any
+ 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.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;
- }
+ GL.glDeleteFramebuffers(1, &(pd->scratch_fbo.fbo));
- pd->scratch_fbo.w = pd->dest_fbo.w;
- pd->scratch_fbo.h = pd->dest_fbo.h;
+ 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)
+{
GL.glGenRenderbuffers(1, &pd->scratch_fbo.rbo_color);
GL.glBindRenderbuffer(GL_RENDERBUFFER, pd->scratch_fbo.rbo_color);
GL.glRenderbufferStorageMultisample(GL_RENDERBUFFER,
GL_RENDERBUFFER,
pd->scratch_fbo.rbo_color);
- // attach depthbuffer image to FBO
+ // attach stencil buffer to FBO
GL.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER,
GLenum status = GL.glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
{
- ERR("cretaing MSAA fbo failed");
+ 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;
- return EINA_FALSE;
}
+}
+
+static void
+_create_msaa_fbo_texture_ext(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);
+
+ // 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)
+ {
+ 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;
+ }
+}
+
+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)
+ {
+ 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;
+
+ 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;
+ }
+
+ // 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;
+
+ 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;
}
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_program);
- GL.glUniformMatrix4fv(pd->uniform_mvp, 1, GL_FALSE, mvp);
+ GL.glUseProgram(pd->simple_shader->program);
+ GL.glUniformMatrix4fv(pd->simple_shader->u_mvp, 1, GL_FALSE, mvp);
GL.glEnableVertexAttribArray(SHAD_VERTEX);
}
else
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);
+ }
}
}
{
pd->offset.x = x;
pd->offset.y = y;
- GL.glUniform4f(pd->uniform_pos, pd->ref_point.x + pd->offset.x, pd->ref_point.y + pd->offset.y, 0, 0);
+ GL.glUniform4f(pd->simple_shader->u_pos, pd->ref_point.x + pd->offset.x, pd->ref_point.y + pd->offset.y, 0, 0);
}
void
obj = eo_do_super_ret(obj, ECTOR_GL_SURFACE_CLASS, obj, eo_constructor());
- pd->simple_program = _init_shader();
- pd->uniform_color = GL.glGetUniformLocation(pd->simple_program, "color");
- pd->uniform_pos = GL.glGetUniformLocation(pd->simple_program, "pos");
- pd->uniform_mvp = GL.glGetUniformLocation(pd->simple_program, "mvp");
+ GL.finalize();
+ 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)
{
{
pd->scratch_fbo.msaa_level = 4;
}
- if (GL.glFuncExist(GL.glBlitFramebuffer))
- {
- pd->scratch_fbo.msaa = EINA_FALSE;
- }
- else
- {
- pd->scratch_fbo.msaa = EINA_FALSE;
- }
+
+ if (GL.version == 3)
+ pd->scratch_fbo.msaa = EINA_TRUE;
+ if (GL.ext_ms_render_to_tex)
+ pd->scratch_fbo.ext_msaa = EINA_TRUE;
+
return obj;
}
_ector_gl_surface_eo_base_destructor(Eo *obj EINA_UNUSED,
Ector_Gl_Surface_Data *pd EINA_UNUSED)
{
- if (pd->simple_program)
- {
- GL.glDeleteProgram(pd->simple_program);
- }
- if (pd->scratch_fbo.fbo)
- {
- 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;
- }
+ _destroy_shader_program(pd->simple_shader);
+ _destroy_shader_program(pd->texture_shader);
+ _delete_fbo(pd);
+
eo_do_super(obj, ECTOR_GL_SURFACE_CLASS, eo_destructor());
}