From 5ccd7830697b45480bfd4fbef455a07a1f222dca Mon Sep 17 00:00:00 2001 From: DaeKwang Ryu Date: Wed, 11 Nov 2015 11:36:42 +0900 Subject: [PATCH] Evas GL: implement GLES2/GLES3 wrapper functions Summary: I found some bugs in EvasGL with OpenGL ES conformance test. 6 wrapper functions are added for GLES2, (glDeleteFramebuffers, glFramebufferRenderbuffer glFramebufferTexture2D, glGetError glGetFloatv, glGetFramebufferAttachmentParameteriv) 3 wrapper fucntions are added for GLES3. (glDrawbuffers, glGetStringi, glReadBuffer) Test Plan: GLES3 sample app, EvasGL(OpenGL ES CTS) for 2.0 is passed. For 3.0, 10 TCs are failed (Total : 2994TCs). Reviewers: wonsik, spacegrapher, jpeg Subscribers: cedric, JoogabYun, scholb.kim Maniphest Tasks: T2621 Differential Revision: https://phab.enlightenment.org/D3301 --- .../evas/engines/gl_common/evas_gl_api.c | 871 ++++++++++++++++-- .../evas/engines/gl_common/evas_gl_api_def.h | 12 +- .../evas/engines/gl_common/evas_gl_api_ext.c | 37 +- .../evas/engines/gl_common/evas_gl_api_ext.h | 2 + .../engines/gl_common/evas_gl_api_gles3_def.h | 7 +- .../evas/engines/gl_common/evas_gl_common.h | 2 + .../evas/engines/gl_common/evas_gl_core.c | 264 ++++-- .../engines/gl_common/evas_gl_core_private.h | 5 + 8 files changed, 1044 insertions(+), 156 deletions(-) diff --git a/src/modules/evas/engines/gl_common/evas_gl_api.c b/src/modules/evas/engines/gl_common/evas_gl_api.c index a97204e087..44a87cc58d 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_api.c +++ b/src/modules/evas/engines/gl_common/evas_gl_api.c @@ -14,6 +14,13 @@ #define EVGLD_FUNC_END() GLERRV(__FUNCTION__) #define _EVGL_INT_INIT_VALUE -3 +#define SET_GL_ERROR(gl_error_type) \ + if (ctx->gl_error == GL_NO_ERROR) \ + { \ + ctx->gl_error = glGetError(); \ + if (ctx->gl_error == GL_NO_ERROR) ctx->gl_error = gl_error_type; \ + } + static void *_gles3_handle = NULL; static Evas_GL_API _gles3_api; //---------------------------------------// @@ -80,42 +87,120 @@ _evgl_glBindFramebuffer(GLenum target, GLuint framebuffer) } // Take care of BindFramebuffer 0 issue - if (framebuffer==0) + if (ctx->version == EVAS_GL_GLES_2_X) { - if (_evgl_direct_enabled()) + if (framebuffer==0) { - glBindFramebuffer(target, 0); - - if (rsc->direct.partial.enabled) + if (_evgl_direct_enabled()) { - if (!ctx->partial_render) + glBindFramebuffer(target, 0); + + if (rsc->direct.partial.enabled) { - evgl_direct_partial_render_start(); - ctx->partial_render = 1; + if (!ctx->partial_render) + { + evgl_direct_partial_render_start(); + ctx->partial_render = 1; + } } } + else + { + glBindFramebuffer(target, ctx->surface_fbo); + } + ctx->current_fbo = 0; + } + else + { + if (_evgl_direct_enabled()) + { + if (ctx->current_fbo == 0) + { + if (rsc->direct.partial.enabled) + evgl_direct_partial_render_end(); + } + } + + glBindFramebuffer(target, framebuffer); + + // Save this for restore when doing make current + ctx->current_fbo = framebuffer; + } + } + else if (ctx->version == EVAS_GL_GLES_3_X) + { + if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER) + { + if (framebuffer==0) + { + if (_evgl_direct_enabled()) + { + glBindFramebuffer(target, 0); + + if (rsc->direct.partial.enabled) + { + if (!ctx->partial_render) + { + evgl_direct_partial_render_start(); + ctx->partial_render = 1; + } + } + } + else + { + glBindFramebuffer(target, ctx->surface_fbo); + } + ctx->current_draw_fbo = 0; + + if (target == GL_FRAMEBUFFER) + ctx->current_read_fbo = 0; + } + else + { + if (_evgl_direct_enabled()) + { + if (ctx->current_draw_fbo == 0) + { + if (rsc->direct.partial.enabled) + evgl_direct_partial_render_end(); + } + } + + glBindFramebuffer(target, framebuffer); + + // Save this for restore when doing make current + ctx->current_draw_fbo = framebuffer; + + if (target == GL_FRAMEBUFFER) + ctx->current_read_fbo = framebuffer; + } + } + else if (target == GL_READ_FRAMEBUFFER) + { + if (framebuffer==0) + { + if (_evgl_direct_enabled()) + { + glBindFramebuffer(target, 0); + } + else + { + glBindFramebuffer(target, ctx->surface_fbo); + } + ctx->current_read_fbo = 0; + } + else + { + glBindFramebuffer(target, framebuffer); + + // Save this for restore when doing make current + ctx->current_read_fbo = framebuffer; + } } else { - glBindFramebuffer(target, ctx->surface_fbo); + glBindFramebuffer(target, framebuffer); } - ctx->current_fbo = 0; - } - else - { - if (_evgl_direct_enabled()) - { - if (ctx->current_fbo == 0) - { - if (rsc->direct.partial.enabled) - evgl_direct_partial_render_end(); - } - } - - glBindFramebuffer(target, framebuffer); - - // Save this for restore when doing make current - ctx->current_fbo = framebuffer; } } @@ -129,6 +214,61 @@ _evgl_glClearDepthf(GLclampf depth) #endif } +void +_evgl_glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) +{ + EVGL_Context *ctx; + int i; + + ctx = evas_gl_common_current_context_get(); + if (!ctx) + { + ERR("Unable to retrive Current Context"); + return; + } + + if (!framebuffers) + { + glDeleteFramebuffers(n, framebuffers); + return; + } + + if (!_evgl_direct_enabled()) + { + if (ctx->version == EVAS_GL_GLES_2_X) + { + for (i = 0; i < n; i++) + { + if (framebuffers[i] == ctx->current_fbo) + { + glBindFramebuffer(GL_FRAMEBUFFER, ctx->surface_fbo); + ctx->current_fbo = 0; + break; + } + } + } + else if (ctx->version == EVAS_GL_GLES_3_X) + { + for (i = 0; i < n; i++) + { + if (framebuffers[i] == ctx->current_draw_fbo) + { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ctx->surface_fbo); + ctx->current_draw_fbo = 0; + } + + if (framebuffers[i] == ctx->current_read_fbo) + { + glBindFramebuffer(GL_READ_FRAMEBUFFER, ctx->surface_fbo); + ctx->current_read_fbo = 0; + } + } + } + } + + glDeleteFramebuffers(n, framebuffers); +} + void _evgl_glDepthRangef(GLclampf zNear, GLclampf zFar) { @@ -139,6 +279,34 @@ _evgl_glDepthRangef(GLclampf zNear, GLclampf zFar) #endif } +GLenum +_evgl_glGetError(void) +{ + GLenum ret; + EVGL_Context *ctx = evas_gl_common_current_context_get(); + + if (!ctx) + { + ERR("No current context set."); + return GL_NO_ERROR; + } + + if (ctx->gl_error != GL_NO_ERROR) + { + ret = ctx->gl_error; + + //reset error state to GL_NO_ERROR. (EvasGL & Native GL) + ctx->gl_error = GL_NO_ERROR; + glGetError(); + + return ret; + } + else + { + return glGetError(); + } +} + void _evgl_glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) { @@ -364,7 +532,8 @@ _evgl_glClear(GLbitfield mask) if (_evgl_direct_enabled()) { - if (!(rsc->current_ctx->current_fbo)) + if ((!(rsc->current_ctx->current_fbo) && rsc->current_ctx->version == EVAS_GL_GLES_2_X) || + (!(rsc->current_ctx->current_draw_fbo) && rsc->current_ctx->version == EVAS_GL_GLES_3_X)) { /* Skip glClear() if clearing with transparent color * Note: There will be side effects if the object itself is not @@ -471,7 +640,8 @@ _evgl_glEnable(GLenum cap) if (rsc) { - if (!ctx->current_fbo) + if ((!ctx->current_fbo && ctx->version == EVAS_GL_GLES_2_X) || + (!ctx->current_draw_fbo && ctx->version == EVAS_GL_GLES_3_X)) { // Direct rendering to canvas if (!ctx->scissor_updated) @@ -539,7 +709,8 @@ _evgl_glDisable(GLenum cap) if (_evgl_direct_enabled()) { - if (!ctx->current_fbo) + if ((!ctx->current_fbo && ctx->version == EVAS_GL_GLES_2_X) || + (!ctx->current_draw_fbo && ctx->version == EVAS_GL_GLES_3_X)) { // Restore default scissors for direct rendering int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,0}, cc[4] = {0,0,0,0}; @@ -576,73 +747,468 @@ _evgl_glDisable(GLenum cap) glDisable(cap); } +static void +_evgl_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) +{ + EVGL_Resource *rsc; + EVGL_Context *ctx; + + if (!(rsc=_evgl_tls_resource_get())) + { + ERR("Unable to execute GL command. Error retrieving tls"); + return; + } + + if (!rsc->current_eng) + { + ERR("Unable to retrive Current Engine"); + return; + } + + ctx = rsc->current_ctx; + if (!ctx) + { + ERR("Unable to retrive Current Context"); + return; + } + + if (!_evgl_direct_enabled()) + { + if (ctx->version == EVAS_GL_GLES_2_X) + { + if (target == GL_FRAMEBUFFER && ctx->current_fbo == 0) + { + SET_GL_ERROR(GL_INVALID_OPERATION); + return; + } + } + else if (ctx->version == EVAS_GL_GLES_3_X) + { + if (target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER) + { + if (ctx->current_draw_fbo == 0) + { + SET_GL_ERROR(GL_INVALID_OPERATION); + return; + } + } + else if (target == GL_READ_FRAMEBUFFER) + { + if (ctx->current_read_fbo == 0) + { + SET_GL_ERROR(GL_INVALID_OPERATION); + return; + } + } + } + } + + glFramebufferTexture2D(target, attachment, textarget, texture, level); +} + +static void +_evgl_glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) +{ + EVGL_Resource *rsc; + EVGL_Context *ctx; + + if (!(rsc=_evgl_tls_resource_get())) + { + ERR("Unable to execute GL command. Error retrieving tls"); + return; + } + + if (!rsc->current_eng) + { + ERR("Unable to retrive Current Engine"); + return; + } + + ctx = rsc->current_ctx; + if (!ctx) + { + ERR("Unable to retrive Current Context"); + return; + } + + if (!_evgl_direct_enabled()) + { + if(ctx->version == EVAS_GL_GLES_2_X) + { + if (target == GL_FRAMEBUFFER && ctx->current_fbo == 0) + { + SET_GL_ERROR(GL_INVALID_OPERATION); + return; + } + } + else if(ctx->version == EVAS_GL_GLES_3_X) + { + if (target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER) + { + if (ctx->current_draw_fbo == 0) + { + SET_GL_ERROR(GL_INVALID_OPERATION); + return; + } + } + else if (target == GL_READ_FRAMEBUFFER) + { + if (ctx->current_read_fbo == 0) + { + SET_GL_ERROR(GL_INVALID_OPERATION); + return; + } + } + } + } + + glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer); +} + void -_evgl_glGetIntegerv(GLenum pname, GLint* params) +_evgl_glGetFloatv(GLenum pname, GLfloat* params) { EVGL_Resource *rsc; EVGL_Context *ctx; + if (!params) + { + ERR("Invalid Parameter"); + return; + } + + if (!(rsc=_evgl_tls_resource_get())) + { + ERR("Unable to execute GL command. Error retrieving tls"); + return; + } + + ctx = rsc->current_ctx; + if (!ctx) + { + ERR("Unable to retrive Current Context"); + return; + } + if (_evgl_direct_enabled()) { - if (!params) + if (ctx->version == EVAS_GL_GLES_2_X) { - ERR("Invalid Parameter"); - return; - } - - if (!(rsc=_evgl_tls_resource_get())) - { - ERR("Unable to execute GL command. Error retrieving tls"); - return; - } - - ctx = rsc->current_ctx; - if (!ctx) - { - ERR("Unable to retrive Current Context"); - return; - } - - // Only need to handle it if it's directly rendering to the window - if (!(rsc->current_ctx->current_fbo)) - { - if (pname == GL_SCISSOR_BOX) + // Only need to handle it if it's directly rendering to the window + if (!(rsc->current_ctx->current_fbo)) { - if (ctx->scissor_updated) + if (pname == GL_SCISSOR_BOX) { - memcpy(params, ctx->scissor_coord, sizeof(int)*4); + if (ctx->scissor_updated) + { + params[0] = (GLfloat)ctx->scissor_coord[0]; + params[1] = (GLfloat)ctx->scissor_coord[1]; + params[2] = (GLfloat)ctx->scissor_coord[2]; + params[3] = (GLfloat)ctx->scissor_coord[3]; + return; + } + } + else if (pname == GL_VIEWPORT) + { + if (ctx->viewport_updated) + { + memcpy(params, ctx->viewport_coord, sizeof(int)*4); + return; + } + } + + // If it hasn't been initialized yet, return img object size + if ((pname == GL_SCISSOR_BOX) || (pname == GL_VIEWPORT)) + { + params[0] = (GLfloat)0.0; + params[1] = (GLfloat)0.0; + params[2] = (GLfloat)rsc->direct.img.w; + params[3] = (GLfloat)rsc->direct.img.h; return; } } - else if (pname == GL_VIEWPORT) + } + else if (ctx->version == EVAS_GL_GLES_3_X) + { + // Only need to handle it if it's directly rendering to the window + if (!(rsc->current_ctx->current_draw_fbo)) { - if (ctx->viewport_updated) + if (pname == GL_SCISSOR_BOX) { - memcpy(params, ctx->viewport_coord, sizeof(int)*4); + if (ctx->scissor_updated) + { + params[0] = (GLfloat)ctx->scissor_coord[0]; + params[1] = (GLfloat)ctx->scissor_coord[1]; + params[2] = (GLfloat)ctx->scissor_coord[2]; + params[3] = (GLfloat)ctx->scissor_coord[3]; + return; + } + } + else if (pname == GL_VIEWPORT) + { + if (ctx->viewport_updated) + { + memcpy(params, ctx->viewport_coord, sizeof(int)*4); + return; + } + } + // If it hasn't been initialized yet, return img object size + if ((pname == GL_SCISSOR_BOX) )//|| (pname == GL_VIEWPORT)) + { + params[0] = (GLfloat)0.0; + params[1] = (GLfloat)0.0; + params[2] = (GLfloat)rsc->direct.img.w; + params[3] = (GLfloat)rsc->direct.img.h; return; } } - // If it hasn't been initialized yet, return img object size - if ((pname == GL_SCISSOR_BOX) || (pname == GL_VIEWPORT)) + if (pname == GL_NUM_EXTENSIONS) { - params[0] = 0; - params[1] = 0; - params[2] = (GLint)rsc->direct.img.w; - params[3] = (GLint)rsc->direct.img.h; + *params = (GLfloat)evgl_api_ext_num_extensions_get(ctx->version); return; } } } else { - if (pname == GL_FRAMEBUFFER_BINDING) + if (ctx->version == EVAS_GL_GLES_2_X) { - rsc = _evgl_tls_resource_get(); - ctx = rsc ? rsc->current_ctx : NULL; - if (ctx) + if (pname == GL_FRAMEBUFFER_BINDING) { - *params = ctx->current_fbo; + rsc = _evgl_tls_resource_get(); + ctx = rsc ? rsc->current_ctx : NULL; + if (ctx) + { + *params = (GLfloat)ctx->current_fbo; + return; + } + } + } + else if (ctx->version == EVAS_GL_GLES_3_X) + { + if (pname == GL_DRAW_FRAMEBUFFER_BINDING || pname == GL_FRAMEBUFFER_BINDING) + { + *params = (GLfloat)ctx->current_draw_fbo; + return; + } + else if (pname == GL_READ_FRAMEBUFFER_BINDING) + { + *params = (GLfloat)ctx->current_read_fbo; + return; + } + else if (pname == GL_READ_BUFFER) + { + if (ctx->current_read_fbo == 0) + { + glGetFloatv(pname, params); + if (*params == GL_COLOR_ATTACHMENT0) + { + *params = (GLfloat)GL_BACK; + return; + } + } + } + else if (pname == GL_NUM_EXTENSIONS) + { + *params = (GLfloat)evgl_api_ext_num_extensions_get(ctx->version); + return; + } + } + } + + glGetFloatv(pname, params); +} + +void +_evgl_glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) +{ + EVGL_Context *ctx; + + ctx = evas_gl_common_current_context_get(); + + if (!ctx) + { + ERR("Unable to retrive Current Context"); + return; + } + + if (!_evgl_direct_enabled()) + { + if (ctx->version == EVAS_GL_GLES_2_X) + { + if (ctx->current_fbo == 0) + { + SET_GL_ERROR(GL_INVALID_OPERATION); + return; + } + } + else if (ctx->version == EVAS_GL_GLES_3_X) + { + if (target == GL_DRAW_FRAMEBUFFER || target == GL_FRAMEBUFFER) + { + if (ctx->current_draw_fbo == 0 && attachment == GL_BACK) + { + glGetFramebufferAttachmentParameteriv(target, GL_COLOR_ATTACHMENT0, pname, params); + return; + } + } + else if (target == GL_READ_FRAMEBUFFER) + { + if (ctx->current_read_fbo == 0 && attachment == GL_BACK) + { + glGetFramebufferAttachmentParameteriv(target, GL_COLOR_ATTACHMENT0, pname, params); + return; + } + } + } + } + + glGetFramebufferAttachmentParameteriv(target, attachment, pname, params); +} + +void +_evgl_glGetIntegerv(GLenum pname, GLint* params) +{ + EVGL_Resource *rsc; + EVGL_Context *ctx; + + if (!params) + { + ERR("Invalid Parameter"); + return; + } + + if (!(rsc=_evgl_tls_resource_get())) + { + ERR("Unable to execute GL command. Error retrieving tls"); + return; + } + + ctx = rsc->current_ctx; + if (!ctx) + { + ERR("Unable to retrive Current Context"); + return; + } + + if (_evgl_direct_enabled()) + { + if (ctx->version == EVAS_GL_GLES_2_X) + { + // Only need to handle it if it's directly rendering to the window + if (!(rsc->current_ctx->current_fbo)) + { + if (pname == GL_SCISSOR_BOX) + { + if (ctx->scissor_updated) + { + memcpy(params, ctx->scissor_coord, sizeof(int)*4); + return; + } + } + else if (pname == GL_VIEWPORT) + { + if (ctx->viewport_updated) + { + memcpy(params, ctx->viewport_coord, sizeof(int)*4); + return; + } + } + + // If it hasn't been initialized yet, return img object size + if ((pname == GL_SCISSOR_BOX) || (pname == GL_VIEWPORT)) + { + params[0] = 0; + params[1] = 0; + params[2] = (GLint)rsc->direct.img.w; + params[3] = (GLint)rsc->direct.img.h; + return; + } + } + } + else if (ctx->version == EVAS_GL_GLES_3_X) + { + // Only need to handle it if it's directly rendering to the window + if (!(rsc->current_ctx->current_draw_fbo)) + { + if (pname == GL_SCISSOR_BOX) + { + if (ctx->scissor_updated) + { + memcpy(params, ctx->scissor_coord, sizeof(int)*4); + return; + } + } + else if (pname == GL_VIEWPORT) + { + if (ctx->viewport_updated) + { + memcpy(params, ctx->viewport_coord, sizeof(int)*4); + return; + } + } + // If it hasn't been initialized yet, return img object size + if ((pname == GL_SCISSOR_BOX) )//|| (pname == GL_VIEWPORT)) + { + params[0] = 0; + params[1] = 0; + params[2] = (GLint)rsc->direct.img.w; + params[3] = (GLint)rsc->direct.img.h; + return; + } + } + + if (pname == GL_NUM_EXTENSIONS) + { + *params = evgl_api_ext_num_extensions_get(ctx->version); + return; + } + } + } + else + { + if (ctx->version == EVAS_GL_GLES_2_X) + { + if (pname == GL_FRAMEBUFFER_BINDING) + { + rsc = _evgl_tls_resource_get(); + ctx = rsc ? rsc->current_ctx : NULL; + if (ctx) + { + *params = ctx->current_fbo; + return; + } + } + } + else if (ctx->version == EVAS_GL_GLES_3_X) + { + if (pname == GL_DRAW_FRAMEBUFFER_BINDING || pname == GL_FRAMEBUFFER_BINDING) + { + *params = ctx->current_draw_fbo; + return; + } + else if (pname == GL_READ_FRAMEBUFFER_BINDING) + { + *params = ctx->current_read_fbo; + return; + } + else if (pname == GL_READ_BUFFER) + { + if (ctx->current_read_fbo == 0) + { + glGetIntegerv(pname, params); + + if (*params == GL_COLOR_ATTACHMENT0) + { + *params = GL_BACK; + return; + } + } + } + else if (pname == GL_NUM_EXTENSIONS) + { + *params = evgl_api_ext_num_extensions_get(ctx->version); return; } } @@ -748,6 +1314,37 @@ _evgl_glGetString(GLenum name) return glGetString(name); } +static const GLubyte * +_evgl_glGetStringi(GLenum name, GLuint index) +{ + EVGL_Context *ctx; + + ctx = evas_gl_common_current_context_get(); + + if (!ctx) + { + ERR("Unable to retrive Current Context"); + return NULL; + } + + switch (name) + { + case GL_EXTENSIONS: + if (index < evgl_api_ext_num_extensions_get(ctx->version)) + { + return (GLubyte *)evgl_api_ext_stringi_get(index, ctx->version); + } + else + SET_GL_ERROR(GL_INVALID_VALUE); + break; + default: + SET_GL_ERROR(GL_INVALID_ENUM); + break; + } + + return NULL; +} + static void _evgl_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) { @@ -779,7 +1376,8 @@ _evgl_glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum forma if (_evgl_direct_enabled()) { - if (!(rsc->current_ctx->current_fbo)) + if ((!(rsc->current_ctx->current_fbo) && rsc->current_ctx->version == EVAS_GL_GLES_2_X) || + (!(rsc->current_ctx->current_read_fbo) && rsc->current_ctx->version == EVAS_GL_GLES_3_X)) { compute_gl_coordinates(rsc->direct.win_w, rsc->direct.win_h, rsc->direct.rot, 1, @@ -831,7 +1429,8 @@ _evgl_glScissor(GLint x, GLint y, GLsizei width, GLsizei height) if (_evgl_direct_enabled()) { - if (!(rsc->current_ctx->current_fbo)) + if ((!(rsc->current_ctx->current_fbo) && rsc->current_ctx->version == EVAS_GL_GLES_2_X) || + (!(rsc->current_ctx->current_draw_fbo) && rsc->current_ctx->version == EVAS_GL_GLES_3_X)) { // Direct rendering to canvas if ((ctx->direct_scissor) && (!ctx->scissor_enabled)) @@ -918,7 +1517,8 @@ _evgl_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) if (_evgl_direct_enabled()) { - if (!(rsc->current_ctx->current_fbo)) + if ((!(rsc->current_ctx->current_fbo) && rsc->current_ctx->version == EVAS_GL_GLES_2_X) || + (!(rsc->current_ctx->current_draw_fbo) && rsc->current_ctx->version == EVAS_GL_GLES_3_X)) { if ((!ctx->direct_scissor)) { @@ -1002,6 +1602,100 @@ _evgl_glViewport(GLint x, GLint y, GLsizei width, GLsizei height) } } +static void +_evgl_glDrawBuffers(GLsizei n, const GLenum *bufs) +{ + EVGL_Context *ctx; + Eina_Bool target_is_fbo = EINA_FALSE; + unsigned int drawbuffer; + + ctx = evas_gl_common_current_context_get(); + if (!ctx) + { + ERR("Unable to retrive Current Context"); + return; + } + + if (!bufs) + { + glDrawBuffers(n, bufs); + return; + } + + if (!_evgl_direct_enabled()) + { + if (ctx->current_draw_fbo == 0) + target_is_fbo = EINA_TRUE; + } + + if (target_is_fbo) + { + if (n==1) + { + if (*bufs == GL_BACK) + { + drawbuffer = GL_COLOR_ATTACHMENT0; + glDrawBuffers(n, &drawbuffer); + } + else if ((*bufs & GL_COLOR_ATTACHMENT0) == GL_COLOR_ATTACHMENT0) + { + SET_GL_ERROR(GL_INVALID_OPERATION); + } + else + { + glDrawBuffers(n, bufs); + } + } + else + { + SET_GL_ERROR(GL_INVALID_OPERATION); + } + } + else + { + glDrawBuffers(n, bufs); + } +} + +static void +_evgl_glReadBuffer(GLenum src) +{ + EVGL_Context *ctx; + Eina_Bool target_is_fbo = EINA_FALSE; + + ctx = evas_gl_common_current_context_get(); + if (!ctx) + { + ERR("Unable to retrive Current Context"); + return; + } + + if (!_evgl_direct_enabled()) + { + if (ctx->current_read_fbo == 0) + target_is_fbo = EINA_TRUE; + } + + if (target_is_fbo) + { + if (src == GL_BACK) + { + glReadBuffer(GL_COLOR_ATTACHMENT0); + } + else if((src & GL_COLOR_ATTACHMENT0) == GL_COLOR_ATTACHMENT0) + { + SET_GL_ERROR(GL_INVALID_OPERATION); + } + else + { + glReadBuffer(src); + } + } + else + { + glReadBuffer(src); + } +} //-------------------------------------------------------------// // Open GLES 2.0 APIs @@ -1079,6 +1773,20 @@ static void _evgld_##name param1 { \ //-------------------------------------------------------------// // Open GLES 3.0 APIs +#define _EVASGL_FUNCTION_PRIVATE_BEGIN(ret, name, param1, param2) \ +static ret evgl_gles3_##name param1 { \ + EVGL_FUNC_BEGIN(); \ + if (!_gles3_api.name) return (ret)0; \ + return _evgl_##name param2; \ +} + +#define _EVASGL_FUNCTION_PRIVATE_BEGIN_VOID(name, param1, param2) \ +static void evgl_gles3_##name param1 { \ + EVGL_FUNC_BEGIN(); \ + if (!_gles3_api.name) return; \ + _evgl_##name param2; \ +} + #define _EVASGL_FUNCTION_BEGIN(ret, name, param1, param2) \ static ret evgl_gles3_##name param1 { \ EVGL_FUNC_BEGIN(); \ @@ -1095,12 +1803,31 @@ static void evgl_gles3_##name param1 { \ #include "evas_gl_api_gles3_def.h" +#undef _EVASGL_FUNCTION_PRIVATE_BEGIN +#undef _EVASGL_FUNCTION_PRIVATE_BEGIN_VOID #undef _EVASGL_FUNCTION_BEGIN #undef _EVASGL_FUNCTION_BEGIN_VOID //-------------------------------------------------------------// // Open GLES 3.0 APIs DEBUG +#define _EVASGL_FUNCTION_PRIVATE_BEGIN(ret, name, param1, param2) \ +static ret _evgld_##name param1 { \ + EVGLD_FUNC_BEGIN(); \ + if (!_gles3_api.name) return (ret)0; \ + ret _a = _evgl_##name param2; \ + EVGLD_FUNC_END(); \ + return _a; \ +} + +#define _EVASGL_FUNCTION_PRIVATE_BEGIN_VOID(name, param1, param2) \ +static void _evgld_##name param1 { \ + EVGLD_FUNC_BEGIN(); \ + if (!_gles3_api.name) return; \ + _evgl_##name param2; \ + EVGLD_FUNC_END(); \ +} + #define _EVASGL_FUNCTION_BEGIN(ret, name, param1, param2) \ static ret _evgld_##name param1 { \ EVGLD_FUNC_BEGIN(); \ @@ -1120,6 +1847,8 @@ static void _evgld_##name param1 { \ #include "evas_gl_api_gles3_def.h" +#undef _EVASGL_FUNCTION_PRIVATE_BEGIN +#undef _EVASGL_FUNCTION_PRIVATE_BEGIN_VOID #undef _EVASGL_FUNCTION_BEGIN #undef _EVASGL_FUNCTION_BEGIN_VOID diff --git a/src/modules/evas/engines/gl_common/evas_gl_api_def.h b/src/modules/evas/engines/gl_common/evas_gl_api_def.h index 40d5600a75..662fbaca12 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_api_def.h +++ b/src/modules/evas/engines/gl_common/evas_gl_api_def.h @@ -13,6 +13,12 @@ _EVASGL_FUNCTION_PRIVATE_BEGIN(const GLubyte *, glGetString, (GLenum name), (nam _EVASGL_FUNCTION_PRIVATE_BEGIN_VOID( glReadPixels, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels), (x, y, width, height, format, type, pixels)) _EVASGL_FUNCTION_PRIVATE_BEGIN_VOID( glScissor, (GLint x, GLint y, GLsizei width, GLsizei height), (x, y, width, height)) _EVASGL_FUNCTION_PRIVATE_BEGIN_VOID( glViewport, (GLint x, GLint y, GLsizei width, GLsizei height), (x, y, width, height)) +_EVASGL_FUNCTION_PRIVATE_BEGIN_VOID( glDeleteFramebuffers, (GLsizei n, const GLuint* framebuffers), (n, framebuffers)) +_EVASGL_FUNCTION_PRIVATE_BEGIN_VOID( glFramebufferRenderbuffer, (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer), (target, attachment, renderbuffertarget, renderbuffer)) +_EVASGL_FUNCTION_PRIVATE_BEGIN_VOID( glFramebufferTexture2D, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level), (target, attachment, textarget, texture, level)) +_EVASGL_FUNCTION_PRIVATE_BEGIN(GLenum, glGetError, (void), ()) +_EVASGL_FUNCTION_PRIVATE_BEGIN_VOID( glGetFloatv, (GLenum pname, GLfloat* params), (pname, params)) +_EVASGL_FUNCTION_PRIVATE_BEGIN_VOID( glGetFramebufferAttachmentParameteriv, (GLenum target, GLenum attachment, GLenum pname, GLint* params), (target, attachment, pname, params)) _EVASGL_FUNCTION_BEGIN_VOID( glActiveTexture, (GLenum texture), (texture)) _EVASGL_FUNCTION_BEGIN_VOID( glAttachShader, (GLuint program, GLuint shader), (program, shader)) @@ -39,7 +45,6 @@ _EVASGL_FUNCTION_BEGIN(GLuint, glCreateProgram, (void), ()) _EVASGL_FUNCTION_BEGIN(GLuint, glCreateShader, (GLenum type), (type)) _EVASGL_FUNCTION_BEGIN_VOID( glCullFace, (GLenum mode), (mode)) _EVASGL_FUNCTION_BEGIN_VOID( glDeleteBuffers, (GLsizei n, const GLuint* buffers), (n, buffers)) -_EVASGL_FUNCTION_BEGIN_VOID( glDeleteFramebuffers, (GLsizei n, const GLuint* framebuffers), (n, framebuffers)) _EVASGL_FUNCTION_BEGIN_VOID( glDeleteProgram, (GLuint program), (program)) _EVASGL_FUNCTION_BEGIN_VOID( glDeleteRenderbuffers, (GLsizei n, const GLuint* renderbuffers), (n, renderbuffers)) _EVASGL_FUNCTION_BEGIN_VOID( glDeleteShader, (GLuint shader), (shader)) @@ -53,8 +58,6 @@ _EVASGL_FUNCTION_BEGIN_VOID( glDrawElements, (GLenum mode, GLsizei count, GLenum _EVASGL_FUNCTION_BEGIN_VOID( glEnableVertexAttribArray, (GLuint index), (index)) _EVASGL_FUNCTION_BEGIN_VOID( glFinish, (void), ()) _EVASGL_FUNCTION_BEGIN_VOID( glFlush, (void), ()) -_EVASGL_FUNCTION_BEGIN_VOID( glFramebufferRenderbuffer, (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer), (target, attachment, renderbuffertarget, renderbuffer)) -_EVASGL_FUNCTION_BEGIN_VOID( glFramebufferTexture2D, (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level), (target, attachment, textarget, texture, level)) _EVASGL_FUNCTION_BEGIN_VOID( glFrontFace, (GLenum mode), (mode)) _EVASGL_FUNCTION_BEGIN_VOID( glGenBuffers, (GLsizei n, GLuint* buffers), (n, buffers)) _EVASGL_FUNCTION_BEGIN_VOID( glGenerateMipmap, (GLenum target), (target)) @@ -67,9 +70,6 @@ _EVASGL_FUNCTION_BEGIN_VOID( glGetAttachedShaders, (GLuint program, GLsizei maxc _EVASGL_FUNCTION_BEGIN(int, glGetAttribLocation, (GLuint program, const char* name), (program, name)) _EVASGL_FUNCTION_BEGIN_VOID( glGetBooleanv, (GLenum pname, GLboolean* params), (pname, params)) _EVASGL_FUNCTION_BEGIN_VOID( glGetBufferParameteriv, (GLenum target, GLenum pname, GLint* params), (target, pname, params)) -_EVASGL_FUNCTION_BEGIN(GLenum, glGetError, (void), ()) -_EVASGL_FUNCTION_BEGIN_VOID( glGetFloatv, (GLenum pname, GLfloat* params), (pname, params)) -_EVASGL_FUNCTION_BEGIN_VOID( glGetFramebufferAttachmentParameteriv, (GLenum target, GLenum attachment, GLenum pname, GLint* params), (target, attachment, pname, params)) _EVASGL_FUNCTION_BEGIN_VOID( glGetProgramiv, (GLuint program, GLenum pname, GLint* params), (program, pname, params)) _EVASGL_FUNCTION_BEGIN_VOID( glGetProgramInfoLog, (GLuint program, GLsizei bufsize, GLsizei* length, char* infolog), (program, bufsize, length, infolog)) _EVASGL_FUNCTION_BEGIN_VOID( glGetRenderbufferParameteriv, (GLenum target, GLenum pname, GLint* params), (target, pname, params)) diff --git a/src/modules/evas/engines/gl_common/evas_gl_api_ext.c b/src/modules/evas/engines/gl_common/evas_gl_api_ext.c index eb6f1564e7..fd6cb55bb3 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_api_ext.c +++ b/src/modules/evas/engines/gl_common/evas_gl_api_ext.c @@ -19,6 +19,8 @@ static char *_gles1_ext_string_official = NULL; // list of gles 3.1 exts by official name static char *_gles3_ext_string = NULL; static char *_gles3_ext_string_official = NULL; +// indexed pointer list of each extension of gles 3 +Eina_Array *_gles3_ext_plist = NULL; typedef void (*_getproc_fn) (void); typedef _getproc_fn (*fp_getproc)(const char *); @@ -1236,6 +1238,7 @@ _evgl_api_gles3_ext_init(void *getproc, const char *glueexts) } #endif + _gles3_ext_plist = eina_array_new(1); gles3_funcs = _evgl_api_gles3_internal_get(); if (!gles3_funcs || !gles3_funcs->glGetString) { @@ -1352,7 +1355,10 @@ _evgl_api_gles3_ext_init(void *getproc, const char *glueexts) { \ eina_strbuf_append(sb, name" "); \ if ((strncmp(name, "GL_", 3) == 0) && (strstr(eina_strbuf_string_get(sboff), name) == NULL)) \ - eina_strbuf_append(sboff, name" "); \ + { \ + eina_strbuf_append(sboff, name" "); \ + eina_array_push(_gles3_ext_plist, name); \ + } \ } #define _EVASGL_EXT_DRVNAME(name) \ if (_curext_supported) \ @@ -1506,3 +1512,32 @@ evgl_api_ext_string_get(Eina_Bool official, int version) return (official?_gl_ext_string_official:_gl_ext_string); } + +const char * +evgl_api_ext_stringi_get(GLuint index, int version) +{ + if (_evgl_api_ext_status < 1) + { + ERR("EVGL extension is not yet initialized."); + return NULL; + } + + if (version == EVAS_GL_GLES_3_X) + { + if (index < evgl_api_ext_num_extensions_get(version)) + { + return eina_array_data_get(_gles3_ext_plist, index); + } + } + + return NULL; +} + +GLuint +evgl_api_ext_num_extensions_get(int version) +{ + if (version == EVAS_GL_GLES_3_X) + return eina_array_count_get(_gles3_ext_plist); + + return 0; +} diff --git a/src/modules/evas/engines/gl_common/evas_gl_api_ext.h b/src/modules/evas/engines/gl_common/evas_gl_api_ext.h index df128dad1b..118e409cf3 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_api_ext.h +++ b/src/modules/evas/engines/gl_common/evas_gl_api_ext.h @@ -108,6 +108,8 @@ extern void evgl_api_gles1_ext_get(Evas_GL_API *gl_funcs, void *getproc, const c extern void evgl_api_gles3_ext_get(Evas_GL_API *gl_funcs, void *getproc, const char *glueexts); extern const char *evgl_api_ext_egl_string_get(void); extern const char *evgl_api_ext_string_get(Eina_Bool official, int version); +extern const char *evgl_api_ext_stringi_get(GLuint index, int version); +extern GLuint evgl_api_ext_num_extensions_get(int version); #endif //_EVAS_GL_API_EXT_H diff --git a/src/modules/evas/engines/gl_common/evas_gl_api_gles3_def.h b/src/modules/evas/engines/gl_common/evas_gl_api_gles3_def.h index c421b8cea4..f28285784c 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_api_gles3_def.h +++ b/src/modules/evas/engines/gl_common/evas_gl_api_gles3_def.h @@ -1,3 +1,7 @@ +_EVASGL_FUNCTION_PRIVATE_BEGIN_VOID( glDrawBuffers, (GLsizei n, const GLenum *bufs), (n, bufs)) +_EVASGL_FUNCTION_PRIVATE_BEGIN(const GLubyte *, glGetStringi, (GLenum name, GLuint index), (name, index)) +_EVASGL_FUNCTION_PRIVATE_BEGIN_VOID( glReadBuffer, (GLenum src), (src)) + _EVASGL_FUNCTION_BEGIN_VOID( glBeginQuery, (GLenum target, GLuint id), (target, id)) _EVASGL_FUNCTION_BEGIN_VOID( glBeginTransformFeedback, (GLenum primitiveMode), (primitiveMode)) _EVASGL_FUNCTION_BEGIN_VOID( glBindBufferBase, (GLenum target, GLuint index, GLuint buffer), (target, index, buffer)) @@ -21,7 +25,6 @@ _EVASGL_FUNCTION_BEGIN_VOID( glDeleteSync, (GLsync sync), (sync)) _EVASGL_FUNCTION_BEGIN_VOID( glDeleteTransformFeedbacks, (GLsizei n, const GLuint *ids), (n, ids)) _EVASGL_FUNCTION_BEGIN_VOID( glDeleteVertexArrays, (GLsizei n, const GLuint *arrays), (n, arrays)) _EVASGL_FUNCTION_BEGIN_VOID( glDrawArraysInstanced, (GLenum mode, GLint first, GLsizei count, GLsizei primcount), (mode, first, count, primcount)) -_EVASGL_FUNCTION_BEGIN_VOID( glDrawBuffers, (GLsizei n, const GLenum *bufs), (n, bufs)) _EVASGL_FUNCTION_BEGIN_VOID( glDrawElementsInstanced, (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei primcount), (mode, count, type, indices, primcount)) _EVASGL_FUNCTION_BEGIN_VOID( glDrawRangeElements, (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices), (mode, start, end, count, type, indices)) _EVASGL_FUNCTION_BEGIN_VOID( glEndQuery, (GLenum target), (target)) @@ -48,7 +51,6 @@ _EVASGL_FUNCTION_BEGIN_VOID( glGetQueryiv, (GLenum target, GLenum pname, GLint * _EVASGL_FUNCTION_BEGIN_VOID( glGetQueryObjectuiv, (GLuint id, GLenum pname, GLuint * params), (id, pname, params)) _EVASGL_FUNCTION_BEGIN_VOID( glGetSamplerParameterfv, (GLuint sampler, GLenum pname, GLfloat * params), (sampler, pname, params)) _EVASGL_FUNCTION_BEGIN_VOID( glGetSamplerParameteriv, (GLuint sampler, GLenum pname, GLint * params), (sampler, pname, params)) -_EVASGL_FUNCTION_BEGIN(const GLubyte *, glGetStringi, (GLenum name, GLuint index), (name, index)) _EVASGL_FUNCTION_BEGIN_VOID( glGetSynciv, (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values), (sync, pname, bufSize, length, values)) _EVASGL_FUNCTION_BEGIN_VOID( glGetTransformFeedbackVarying, (GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, char * name), (program, index, bufSize, length, size, type, name)) _EVASGL_FUNCTION_BEGIN(GLuint, glGetUniformBlockIndex, (GLuint program, const GLchar *uniformBlockName), (program, uniformBlockName)) @@ -67,7 +69,6 @@ _EVASGL_FUNCTION_BEGIN(void *, glMapBufferRange, (GLenum target, GLintptr offset _EVASGL_FUNCTION_BEGIN_VOID( glPauseTransformFeedback, (void), ()) _EVASGL_FUNCTION_BEGIN_VOID( glProgramBinary, (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length), (program, binaryFormat, binary, length)) _EVASGL_FUNCTION_BEGIN_VOID( glProgramParameteri, (GLuint program, GLenum pname, GLint value), (program, pname, value)) -_EVASGL_FUNCTION_BEGIN_VOID( glReadBuffer, (GLenum src), (src)) _EVASGL_FUNCTION_BEGIN_VOID( glRenderbufferStorageMultisample, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height), (target, samples, internalformat, width, height)) _EVASGL_FUNCTION_BEGIN_VOID( glResumeTransformFeedback, (void), ()) _EVASGL_FUNCTION_BEGIN_VOID( glSamplerParameterf, (GLuint sampler, GLenum pname, GLfloat param), (sampler, pname, param)) diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index 307aa6af6e..845aa3f5e1 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -32,6 +32,8 @@ # ifdef GL_GLES # include # include +# include +# include # else # include # include diff --git a/src/modules/evas/engines/gl_common/evas_gl_core.c b/src/modules/evas/engines/gl_common/evas_gl_core.c index ef012cf3c5..2a0787dba4 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_core.c +++ b/src/modules/evas/engines/gl_common/evas_gl_core.c @@ -204,7 +204,7 @@ _texture_destroy(GLuint *tex) // Attach 2D texture with the given format to already bound FBO // *NOTE: attach2 here is used for depth_stencil attachment in GLES env. static void -_texture_attach_2d(GLuint tex, GLenum attach, GLenum attach2, int samples, Eina_Bool use_extension) +_texture_attach_2d(GLuint tex, GLenum attach, GLenum attach2, int samples, Evas_GL_Context_Version version) { if (samples) { @@ -224,7 +224,7 @@ _texture_attach_2d(GLuint tex, GLenum attach, GLenum attach2, int samples, Eina_ ERR("MSAA not supported. Should not have come in here...!"); #endif } - else if (use_extension) + else if (version == EVAS_GL_GLES_1_X) { if (EXT_FUNC_GLES1(glFramebufferTexture2DOES)) EXT_FUNC_GLES1(glFramebufferTexture2DOES)(GL_FRAMEBUFFER, attach, GL_TEXTURE_2D, tex, 0); @@ -302,9 +302,9 @@ _egl_image_destroy(void *image) } static void -_framebuffer_create(GLuint *buf, Eina_Bool use_extension) +_framebuffer_create(GLuint *buf, Evas_GL_Context_Version version) { - if (use_extension) + if (version == EVAS_GL_GLES_1_X) { if (EXT_FUNC_GLES1(glGenFramebuffersOES)) EXT_FUNC_GLES1(glGenFramebuffersOES)(1, buf); @@ -316,9 +316,9 @@ _framebuffer_create(GLuint *buf, Eina_Bool use_extension) } static void -_framebuffer_bind(GLuint buf, Eina_Bool use_extension) +_framebuffer_bind(GLuint buf, Evas_GL_Context_Version version) { - if (use_extension) + if (version == EVAS_GL_GLES_1_X) { if (EXT_FUNC_GLES1(glBindFramebufferOES)) EXT_FUNC_GLES1(glBindFramebufferOES)(GL_FRAMEBUFFER, buf); @@ -329,11 +329,27 @@ _framebuffer_bind(GLuint buf, Eina_Bool use_extension) } } +static void +_framebuffer_draw_bind(GLuint buf, Evas_GL_Context_Version version) +{ + if (version == EVAS_GL_GLES_3_X) + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, buf); +} + +//This function is not needed in EvasGL backend engine with GLES 2.0. +//But It is useful when EvasGL backend works with GLES 3.X and use read buffers. +static void +_framebuffer_read_bind(GLuint buf, Evas_GL_Context_Version version) +{ + if (version == EVAS_GL_GLES_3_X) + glBindFramebuffer(GL_READ_FRAMEBUFFER, buf); +} + static GLenum -_framebuffer_check(Eina_Bool use_extension) +_framebuffer_check(Evas_GL_Context_Version version) { GLenum ret = 0; - if (use_extension) + if (version == EVAS_GL_GLES_1_X) { if (EXT_FUNC_GLES1(glCheckFramebufferStatusOES)) ret = EXT_FUNC_GLES1(glCheckFramebufferStatusOES)(GL_FRAMEBUFFER); @@ -384,9 +400,9 @@ _renderbuffer_destroy(GLuint *buf) // Attach a renderbuffer with the given format to already bound FBO static void -_renderbuffer_attach(GLuint buf, GLenum attach, Eina_Bool use_extension) +_renderbuffer_attach(GLuint buf, GLenum attach, Evas_GL_Context_Version version) { - if (use_extension) + if (version == EVAS_GL_GLES_1_X) { if (EXT_FUNC_GLES1(glFramebufferRenderbufferOES)) EXT_FUNC_GLES1(glFramebufferRenderbufferOES)(GL_FRAMEBUFFER, attach, GL_RENDERBUFFER, buf); @@ -398,6 +414,7 @@ _renderbuffer_attach(GLuint buf, GLenum attach, Eina_Bool use_extension) } // Check whether the given FBO surface config is supported by the driver +// TODO - we also should test with GLES3's formats. static int _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt, GLenum depth_fmt, GLenum stencil_fmt, int mult_samples) @@ -420,7 +437,7 @@ _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt, { _texture_create(&color_buf); _texture_allocate_2d(color_buf, color_ifmt, color_fmt, GL_UNSIGNED_BYTE, w, h); - _texture_attach_2d(color_buf, GL_COLOR_ATTACHMENT0, 0, mult_samples, EINA_FALSE); + _texture_attach_2d(color_buf, GL_COLOR_ATTACHMENT0, 0, mult_samples, EVAS_GL_GLES_2_X); } // Check Depth_Stencil Format First @@ -431,7 +448,7 @@ _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt, _texture_allocate_2d(depth_stencil_buf, depth_fmt, depth_fmt, GL_UNSIGNED_INT_24_8_OES, w, h); _texture_attach_2d(depth_stencil_buf, GL_DEPTH_ATTACHMENT, - GL_STENCIL_ATTACHMENT, mult_samples, EINA_FALSE); + GL_STENCIL_ATTACHMENT, mult_samples, EVAS_GL_GLES_2_X); depth_stencil = 1; } #else @@ -449,7 +466,7 @@ _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt, { _renderbuffer_create(&depth_buf); _renderbuffer_allocate(depth_buf, depth_fmt, w, h, mult_samples); - _renderbuffer_attach(depth_buf, GL_DEPTH_ATTACHMENT, EINA_FALSE); + _renderbuffer_attach(depth_buf, GL_DEPTH_ATTACHMENT, EVAS_GL_GLES_2_X); } // Stencil Attachment @@ -457,7 +474,7 @@ _fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt, { _renderbuffer_create(&stencil_buf); _renderbuffer_allocate(stencil_buf, stencil_fmt, w, h, mult_samples); - _renderbuffer_attach(stencil_buf, GL_STENCIL_ATTACHMENT, EINA_FALSE); + _renderbuffer_attach(stencil_buf, GL_STENCIL_ATTACHMENT, EVAS_GL_GLES_2_X); } // Check FBO for completeness @@ -1087,47 +1104,47 @@ _surface_context_list_print() // Start from here..... //--------------------------------------------------------// static int -_surface_buffers_fbo_set(EVGL_Surface *sfc, GLuint fbo, Eina_Bool use_extension) +_surface_buffers_fbo_set(EVGL_Surface *sfc, GLuint fbo, Evas_GL_Context_Version version) { int status; - _framebuffer_bind(fbo, use_extension); + _framebuffer_bind(fbo, version); // Detach any previously attached buffers - _texture_attach_2d(0, GL_COLOR_ATTACHMENT0, 0, 0, use_extension); - _renderbuffer_attach(0, GL_DEPTH_ATTACHMENT, use_extension); - _renderbuffer_attach(0, GL_STENCIL_ATTACHMENT, use_extension); + _texture_attach_2d(0, GL_COLOR_ATTACHMENT0, 0, 0, version); + _renderbuffer_attach(0, GL_DEPTH_ATTACHMENT, version); + _renderbuffer_attach(0, GL_STENCIL_ATTACHMENT, version); #ifdef GL_GLES - _texture_attach_2d(0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT, 0, use_extension); + _texture_attach_2d(0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT, 0, version); #else - _renderbuffer_attach(0, GL_DEPTH_STENCIL_ATTACHMENT, use_extension); + _renderbuffer_attach(0, GL_DEPTH_STENCIL_ATTACHMENT, version); #endif // Render Target Texture if (sfc->color_buf) - _texture_attach_2d(sfc->color_buf, GL_COLOR_ATTACHMENT0, 0, sfc->msaa_samples, use_extension); + _texture_attach_2d(sfc->color_buf, GL_COLOR_ATTACHMENT0, 0, sfc->msaa_samples, version); // Depth Stencil RenderBuffer - Attach it to FBO if (sfc->depth_stencil_buf) { #ifdef GL_GLES _texture_attach_2d(sfc->depth_stencil_buf, GL_DEPTH_ATTACHMENT, - GL_STENCIL_ATTACHMENT, sfc->msaa_samples, use_extension); + GL_STENCIL_ATTACHMENT, sfc->msaa_samples, version); #else - _renderbuffer_attach(sfc->depth_stencil_buf, GL_DEPTH_STENCIL_ATTACHMENT, use_extension); + _renderbuffer_attach(sfc->depth_stencil_buf, GL_DEPTH_STENCIL_ATTACHMENT, version); #endif } // Depth RenderBuffer - Attach it to FBO if (sfc->depth_buf) - _renderbuffer_attach(sfc->depth_buf, GL_DEPTH_ATTACHMENT, use_extension); + _renderbuffer_attach(sfc->depth_buf, GL_DEPTH_ATTACHMENT, version); // Stencil RenderBuffer - Attach it to FBO if (sfc->stencil_buf) - _renderbuffer_attach(sfc->stencil_buf, GL_STENCIL_ATTACHMENT, use_extension); + _renderbuffer_attach(sfc->stencil_buf, GL_STENCIL_ATTACHMENT, version); // Check FBO for completeness - status = _framebuffer_check(use_extension); + status = _framebuffer_check(version); if (status != GL_FRAMEBUFFER_COMPLETE) { ERR("FBO not complete. Error Code: %x!", status); @@ -1173,7 +1190,7 @@ _surface_buffers_create(EVGL_Surface *sfc) static int -_surface_buffers_allocate(void *eng_data, EVGL_Surface *sfc, int w, int h, int mc) +_surface_buffers_allocate(void *eng_data, EVGL_Surface *sfc, int w, int h, int mc, Evas_GL_Context_Version version) { // Set the context current with resource context/surface if (mc) @@ -1203,9 +1220,18 @@ _surface_buffers_allocate(void *eng_data, EVGL_Surface *sfc, int w, int h, int m if (sfc->depth_stencil_fmt) { #ifdef GL_GLES - _texture_allocate_2d(sfc->depth_stencil_buf, sfc->depth_stencil_fmt, - sfc->depth_stencil_fmt, GL_UNSIGNED_INT_24_8_OES, - w, h); + if (version == EVAS_GL_GLES_3_X) + { + _texture_allocate_2d(sfc->depth_stencil_buf, GL_DEPTH24_STENCIL8_OES, + sfc->depth_stencil_fmt, GL_UNSIGNED_INT_24_8_OES, + w, h); + } + else + { + _texture_allocate_2d(sfc->depth_stencil_buf, sfc->depth_stencil_fmt, + sfc->depth_stencil_fmt, GL_UNSIGNED_INT_24_8_OES, + w, h); + } #else _renderbuffer_allocate(sfc->depth_stencil_buf, sfc->depth_stencil_fmt, w, h, sfc->msaa_samples); @@ -2133,6 +2159,7 @@ evgl_context_create(void *eng_data, EVGL_Context *share_ctx, ctx->scissor_coord[1] = 0; ctx->scissor_coord[2] = evgl_engine->caps.max_w; ctx->scissor_coord[3] = evgl_engine->caps.max_h; + ctx->gl_error = GL_NO_ERROR; // Call engine create context if (share_ctx) @@ -2242,7 +2269,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) { Eina_Bool dbg = EINA_FALSE; EVGL_Resource *rsc; - int curr_fbo = 0; + int curr_fbo = 0, curr_draw_fbo = 0, curr_read_fbo = 0; // Check the input validity. If either sfc or ctx is NULL, it's also error. if ( (!evgl_engine) || @@ -2276,14 +2303,30 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) if (rsc->direct.partial.enabled) evgl_direct_partial_render_end(); - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo); - if ((rsc->current_ctx->surface_fbo == (GLuint) curr_fbo) || - (rsc->current_ctx->current_sfc && - rsc->current_ctx->current_sfc->color_buf == (GLuint) curr_fbo)) + if (rsc->current_ctx->version == EVAS_GL_GLES_3_X) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - rsc->current_ctx->current_fbo = 0; + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &curr_draw_fbo); + if ((rsc->current_ctx->surface_fbo == (GLuint) curr_draw_fbo) || + (rsc->current_ctx->current_sfc && + rsc->current_ctx->current_sfc->color_buf == (GLuint) curr_draw_fbo)) + { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + rsc->current_ctx->current_draw_fbo = 0; + rsc->current_ctx->current_read_fbo = 0; + } } + else + { + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo); + if ((rsc->current_ctx->surface_fbo == (GLuint) curr_fbo) || + (rsc->current_ctx->current_sfc && + rsc->current_ctx->current_sfc->color_buf == (GLuint) curr_fbo)) + { + glBindFramebuffer(GL_FRAMEBUFFER, 0); + rsc->current_ctx->current_fbo = 0; + } + } + } if (dbg) DBG("Calling make_current(NULL, NULL)"); @@ -2370,7 +2413,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) // Destroy created resources if (sfc->buffers_allocated) { - if (!_surface_buffers_allocate(eng_data, sfc, 0, 0, 0)) + if (!_surface_buffers_allocate(eng_data, sfc, 0, 0, 0, ctx->version)) { ERR("Unable to destroy surface buffers!"); evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC); @@ -2391,7 +2434,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) if (!sfc->buffers_allocated) { if (dbg) DBG("Allocating buffers for sfc %p", sfc); - if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 0)) + if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 1, ctx->version)) { ERR("Unable Create Specificed Surfaces. Unsupported format!"); evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC); @@ -2406,7 +2449,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) { if (!sfc->buffers_allocated) { - if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 0)) + if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 0, ctx->version)) { ERR("Unable Create Allocate Memory for Surface."); evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC); @@ -2459,53 +2502,100 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) glViewport(ctx->viewport_coord[0], ctx->viewport_coord[1], ctx->viewport_coord[2], ctx->viewport_coord[3]); if ((ctx->direct_scissor) && (!ctx->scissor_enabled)) glDisable(GL_SCISSOR_TEST); + } + + if (ctx->version == EVAS_GL_GLES_3_X) + { + ctx->current_draw_fbo = 0; + ctx->current_read_fbo = 0; + } + else + { + ctx->current_fbo = 0; } - ctx->current_fbo = 0; rsc->direct.rendered = 0; } } else { - Eina_Bool use_extension = EINA_FALSE; -#ifdef GL_GLES - if ((ctx->version == EVAS_GL_GLES_1_X) && (gles1_funcs)) - use_extension = EINA_TRUE; -#endif - // Normal FBO Rendering // Create FBO if it hasn't been created if (!ctx->surface_fbo) - _framebuffer_create(&ctx->surface_fbo, use_extension); + _framebuffer_create(&ctx->surface_fbo, ctx->version); // Direct Rendering if (_evgl_direct_renderable(rsc, sfc)) { if (dbg) DBG("sfc %p is direct renderable.", sfc); - // This is to transition from FBO rendering to direct rendering - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo); - if (ctx->surface_fbo == (GLuint)curr_fbo) + if (ctx->version == EVAS_GL_GLES_3_X) { - _framebuffer_bind(0, use_extension); - ctx->current_fbo = 0; - } - else if (ctx->current_sfc && (ctx->current_sfc->pbuffer.is_pbuffer)) - { - // Using the same context, we were rendering on a pbuffer - _framebuffer_bind(0, use_extension); - ctx->current_fbo = 0; - } - - if (ctx->current_fbo == 0) - { - // If master clip is set and clip is greater than 0, do partial render - if (rsc->direct.partial.enabled) + // This is to transition from FBO rendering to direct rendering + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &curr_draw_fbo); + if (ctx->surface_fbo == (GLuint)curr_draw_fbo) { - if (!ctx->partial_render) + _framebuffer_draw_bind(0, ctx->version); + ctx->current_draw_fbo = 0; + } + else if (ctx->current_sfc && (ctx->current_sfc->pbuffer.is_pbuffer)) + { + // Using the same context, we were rendering on a pbuffer + _framebuffer_draw_bind(0, ctx->version); + ctx->current_draw_fbo = 0; + } + + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &curr_read_fbo); + if (ctx->surface_fbo == (GLuint)curr_read_fbo) + { + _framebuffer_read_bind(0, ctx->version); + ctx->current_read_fbo = 0; + } + else if (ctx->current_sfc && (ctx->current_sfc->pbuffer.is_pbuffer)) + { + _framebuffer_read_bind(0, ctx->version); + ctx->current_read_fbo = 0; + } + + if (ctx->current_read_fbo == 0) + { + // If master clip is set and clip is greater than 0, do partial render + if (rsc->direct.partial.enabled) { - evgl_direct_partial_render_start(); - ctx->partial_render = 1; + if (!ctx->partial_render) + { + evgl_direct_partial_render_start(); + ctx->partial_render = 1; + } + } + } + } + else + { + // This is to transition from FBO rendering to direct rendering + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curr_fbo); + if (ctx->surface_fbo == (GLuint)curr_fbo) + { + _framebuffer_bind(0, ctx->version); + ctx->current_fbo = 0; + } + else if (ctx->current_sfc && (ctx->current_sfc->pbuffer.is_pbuffer)) + { + // Using the same context, we were rendering on a pbuffer + _framebuffer_bind(0, ctx->version); + ctx->current_fbo = 0; + } + + if (ctx->current_fbo == 0) + { + // If master clip is set and clip is greater than 0, do partial render + if (rsc->direct.partial.enabled) + { + if (!ctx->partial_render) + { + evgl_direct_partial_render_start(); + ctx->partial_render = 1; + } } } } @@ -2522,7 +2612,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) if (sfc->color_buf) { - if (!_surface_buffers_fbo_set(sfc, sfc->color_buf, use_extension)) + if (!_surface_buffers_fbo_set(sfc, sfc->color_buf, ctx->version)) ERR("Could not detach current FBO"); } @@ -2531,8 +2621,20 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) ctx->context, EINA_TRUE); // Bind to the previously bound buffer (may be 0) - if (ctx->current_fbo) - _framebuffer_bind(ctx->current_fbo, use_extension); + if (ctx->version == EVAS_GL_GLES_3_X) + { + if (ctx->current_draw_fbo) + { + _framebuffer_draw_bind(ctx->current_draw_fbo, ctx->version); + } + } + else + { + if (ctx->current_fbo) + { + _framebuffer_bind(ctx->current_fbo, ctx->version); + } + } rsc->direct.rendered = 0; } @@ -2555,7 +2657,7 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) if (rsc->direct.partial.enabled) evgl_direct_partial_render_end(); - if (!_surface_buffers_fbo_set(sfc, ctx->surface_fbo, use_extension)) + if (!_surface_buffers_fbo_set(sfc, ctx->surface_fbo, ctx->version)) { ERR("Attaching buffers to context fbo failed. Engine: %p Surface: %p Context FBO: %u", evgl_engine, sfc, ctx->surface_fbo); evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT); @@ -2564,8 +2666,20 @@ evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx) } // Bind to the previously bound buffer - if (ctx->current_fbo) - _framebuffer_bind(ctx->current_fbo, use_extension); + + if (ctx->version == EVAS_GL_GLES_3_X) + { + if (ctx->current_draw_fbo) + _framebuffer_draw_bind(ctx->current_draw_fbo, ctx->version); + + if (ctx->current_read_fbo) + _framebuffer_read_bind(ctx->current_read_fbo, ctx->version); + } + else + { + if (ctx->current_fbo) + _framebuffer_bind(ctx->current_fbo, ctx->version); + } } rsc->direct.rendered = 0; } diff --git a/src/modules/evas/engines/gl_common/evas_gl_core_private.h b/src/modules/evas/engines/gl_common/evas_gl_core_private.h index 87c74d245a..41151d52d2 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_core_private.h +++ b/src/modules/evas/engines/gl_common/evas_gl_core_private.h @@ -169,6 +169,8 @@ struct _EVGL_Context // Current FBO GLuint current_fbo; + GLuint current_draw_fbo; //for GLES3 + GLuint current_read_fbo; //for GLES3 // Direct Rendering Related unsigned scissor_enabled : 1; @@ -190,6 +192,9 @@ struct _EVGL_Context int partial_render; EVGL_Surface *current_sfc; + + //glGetError + GLenum gl_error; }; typedef enum _EVGL_Color_Bit