From: subhransu mohanty Date: Wed, 30 Nov 2016 07:24:34 +0000 (+0900) Subject: ector/gl: updated antialiasing drawing in gl backend. X-Git-Tag: accepted/tizen/common/20170102.152350~136 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e712396620a650a90782b66273a08efadcafa5e4;p=platform%2Fupstream%2Fefl.git ector/gl: updated antialiasing drawing in gl backend. Change-Id: I5a0a6b39c4ec605f825c426821f821459ae0e776 --- diff --git a/src/lib/ector/ector_gl_internal.h b/src/lib/ector/ector_gl_internal.h index 3dc073a..6a73cd0 100644 --- a/src/lib/ector/ector_gl_internal.h +++ b/src/lib/ector/ector_gl_internal.h @@ -781,6 +781,8 @@ struct _Ector_GL_API { // Struct is same as Evas_GL_API version 1 without extensions int init; + int version; + int ext_ms_render_to_tex; void (*glActiveTexture) (GLenum texture); void (*glAttachShader) (GLuint program, GLuint shader); @@ -880,7 +882,6 @@ struct _Ector_GL_API { void (*glReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels); void (*glReleaseShaderCompiler) (void); void (*glRenderbufferStorage) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); - void (*glRenderbufferStorageMultisample) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); void (*glSampleCoverage) (GLclampf value, GLboolean invert); void (*glScissor) (GLint x, GLint y, GLsizei width, GLsizei height); void (*glShaderBinary) (GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length); @@ -928,9 +929,21 @@ struct _Ector_GL_API { void (*glVertexAttrib4fv) (GLuint indx, const GLfloat* values); void (*glVertexAttribPointer) (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr); void (*glViewport) (GLint x, GLint y, GLsizei width, GLsizei height); + void* (*glXGetProcAddress)(char const * procname); + void* (*eglGetProcAddress)(char const * procname); + + // openGL ES 2 MSAA extension GL_EXT_multisampled_render_to_texture + void (*glRenderbufferStorageMultisampleEXT)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + void (*glFramebufferTexture2DMultisampleEXT)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, int level, GLsizei samples); + + // openGL ES 3 + void (*glRenderbufferStorageMultisample) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); void (*glBlitFramebuffer) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + + // custom function Eina_Bool (*glFuncExist) (void* gl_func); + void (*finalize)(void); }; #endif diff --git a/src/lib/ector/ector_main.c b/src/lib/ector/ector_main.c index f5c963c..bea7600 100644 --- a/src/lib/ector/ector_main.c +++ b/src/lib/ector/ector_main.c @@ -57,28 +57,101 @@ ector_init(void) return 0; } -static void -no_gl_impl() +static int +_gl_version() { + char *str; + + str = (char *)GL.glGetString(GL_VERSION); + if (!str) + { + return 0; + } + if (strstr(str, "OpenGL ES 3")) + { + return 3; + } + + if (strstr(str, "OpenGL ES 2")) + { + return 2; + } + + if (strstr(str, "3.") || strstr(str, "4.")) + { + return 3; + } + + if (strstr(str, "2.")) + { + return 2; + } + return 0; +} + +static int +_gl_extension(const char * extension) +{ + char *extensions; + extensions = (char *)GL.glGetString(GL_EXTENSIONS); + if (strstr(extensions, extension)) + return 1; + return 0; } static Eina_Bool gl_func_exist(void *fp) { - if (fp == no_gl_impl) return EINA_FALSE; + if (!fp) return EINA_FALSE; return EINA_TRUE; } +static void +_gl_finalize() +{ + if (GL.init) return; + GL.init = EINA_TRUE; + GL.version = _gl_version(); + + if (GL.version == 2) + { + GL.glRenderbufferStorageMultisample = NULL; + GL.glBlitFramebuffer = NULL; + GL.glRenderbufferStorageMultisampleEXT = NULL; + GL.glFramebufferTexture2DMultisampleEXT = NULL; + if (_gl_extension("GL_EXT_multisampled_render_to_texture")) + { + if (GL.eglGetProcAddress) + { + GL.glRenderbufferStorageMultisampleEXT = GL.eglGetProcAddress("glRenderbufferStorageMultisampleEXT"); + GL.glFramebufferTexture2DMultisampleEXT = GL.eglGetProcAddress("glFramebufferTexture2DMultisampleEXT"); + } + if (GL.glXGetProcAddress) + { + GL.glRenderbufferStorageMultisampleEXT = GL.glXGetProcAddress("glRenderbufferStorageMultisampleEXT"); + GL.glFramebufferTexture2DMultisampleEXT = GL.glXGetProcAddress("glFramebufferTexture2DMultisampleEXT"); + } + GL.ext_ms_render_to_tex = 1; + } + } + if (GL.version == 3) + { + GL.glRenderbufferStorageMultisampleEXT = 0; + GL.glFramebufferTexture2DMultisampleEXT = 0; + } + +} + EAPI Eina_Bool ector_glsym_set(void *(*glsym)(void *lib, const char *name), void *lib) { - Eina_Bool r = EINA_TRUE; + GL.init = 0; if (!glsym) return EINA_FALSE; -#define ORD(a) do { GL.a = glsym(lib, #a); if (!GL.a) { GL.a = (void*) no_gl_impl; r = EINA_FALSE; } } while (0) +#define ORD(a) GL.a = glsym(lib, #a); ORD(glActiveTexture); ORD(glAttachShader); @@ -178,7 +251,6 @@ ector_glsym_set(void *(*glsym)(void *lib, const char *name), void *lib) ORD(glReadPixels); ORD(glReleaseShaderCompiler); ORD(glRenderbufferStorage); - ORD(glRenderbufferStorageMultisample); ORD(glSampleCoverage); ORD(glScissor); ORD(glShaderBinary); @@ -226,10 +298,16 @@ ector_glsym_set(void *(*glsym)(void *lib, const char *name), void *lib) ORD(glVertexAttrib4fv); ORD(glVertexAttribPointer); ORD(glViewport); + ORD(eglGetProcAddress); + ORD(glXGetProcAddress); + + ORD(glRenderbufferStorageMultisample); ORD(glBlitFramebuffer); + GL.finalize = _gl_finalize; GL.glFuncExist = gl_func_exist; - GL.init = r; - return r; + GL.ext_ms_render_to_tex = 0; + + return EINA_TRUE; } EAPI int diff --git a/src/lib/ector/gl/ector_gl_private.h b/src/lib/ector/gl/ector_gl_private.h index b00e737..67053d2 100644 --- a/src/lib/ector/gl/ector_gl_private.h +++ b/src/lib/ector/gl/ector_gl_private.h @@ -2,11 +2,27 @@ #define ECTOR_GL_PRIVATE_H_ #define SHAD_VERTEX 0 +#define 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 _Shader_Program Shader_Program; + +struct _Shader_Program +{ + GLuint program; + GLuint v_shader; + GLuint f_shader; + GLuint u_color; + GLuint u_mvp; + GLuint u_pos; + GLuint u_texture; +}; + + struct _Ector_Gl_Surface_Data { struct { @@ -15,12 +31,9 @@ struct _Ector_Gl_Surface_Data struct { int x, y; } offset; - int width; - int height; - GLuint simple_program; - GLuint uniform_color; - GLuint uniform_mvp; - GLuint uniform_pos; + + Shader_Program *simple_shader; + Shader_Program *texture_shader; struct { int w, h; @@ -28,12 +41,14 @@ struct _Ector_Gl_Surface_Data } dest_fbo; struct { - int w, h; - GLuint fbo; - GLuint rbo_color; - GLuint rbo_stencil; + int w, h; + GLuint fbo; + GLuint texture; + GLuint rbo_color; + GLuint rbo_stencil; Eina_Bool msaa; - int msaa_level; + Eina_Bool ext_msaa; + int msaa_level; } scratch_fbo; }; diff --git a/src/lib/ector/gl/ector_gl_surface.c b/src/lib/ector/gl/ector_gl_surface.c index bff877f..7978e84 100644 --- a/src/lib/ector/gl/ector_gl_surface.c +++ b/src/lib/ector/gl/ector_gl_surface.c @@ -17,6 +17,7 @@ static const char vertex_shader[] = "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" @@ -35,6 +36,33 @@ static const char fragment_shader[] = " 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]) { @@ -116,56 +144,65 @@ matrix_ortho(GLfloat *m, 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, @@ -192,8 +229,7 @@ _ector_gl_surface_path_fill(Eo *obj 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 @@ -249,7 +285,7 @@ _ector_gl_surface_path_stroke(Eo *obj EINA_UNUSED, 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) @@ -293,38 +329,29 @@ _ector_gl_surface_path_stroke(Eo *obj EINA_UNUSED, } } -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, @@ -350,7 +377,7 @@ _update_scratch_fbo(Ector_Gl_Surface_Data *pd, int width, int height) 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, @@ -360,14 +387,151 @@ _update_scratch_fbo(Ector_Gl_Surface_Data *pd, int width, int height) 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; } @@ -394,8 +558,8 @@ _ector_gl_surface_surface_set(Eo *obj EINA_UNUSED, 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 @@ -409,6 +573,32 @@ _ector_gl_surface_surface_set(Eo *obj EINA_UNUSED, 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); + } } } @@ -418,7 +608,7 @@ _ector_gl_surface_offset(Eo *obj EINA_UNUSED, { 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 @@ -438,11 +628,10 @@ _ector_gl_surface_eo_base_constructor(Eo *obj, 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) { @@ -453,14 +642,12 @@ _ector_gl_surface_eo_base_constructor(Eo *obj, { 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; } @@ -468,17 +655,10 @@ static void _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()); }