Evas GL: implement GLES2/GLES3 wrapper functions
authorDaeKwang Ryu <dkdk.ryu@samsung.com>
Wed, 11 Nov 2015 02:36:42 +0000 (11:36 +0900)
committerJean-Philippe Andre <jp.andre@samsung.com>
Wed, 11 Nov 2015 05:35:50 +0000 (14:35 +0900)
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

src/modules/evas/engines/gl_common/evas_gl_api.c
src/modules/evas/engines/gl_common/evas_gl_api_def.h
src/modules/evas/engines/gl_common/evas_gl_api_ext.c
src/modules/evas/engines/gl_common/evas_gl_api_ext.h
src/modules/evas/engines/gl_common/evas_gl_api_gles3_def.h
src/modules/evas/engines/gl_common/evas_gl_common.h
src/modules/evas/engines/gl_common/evas_gl_core.c
src/modules/evas/engines/gl_common/evas_gl_core_private.h

index a97204e..44a87cc 100644 (file)
 #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
           {
-             glBindFramebuffer(target, ctx->surface_fbo);
+             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;
           }
-        ctx->current_fbo = 0;
      }
-   else
+   else if (ctx->version == EVAS_GL_GLES_3_X)
      {
-        if (_evgl_direct_enabled())
+        if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER)
           {
-             if (ctx->current_fbo == 0)
+             if (framebuffer==0)
                {
-                  if (rsc->direct.partial.enabled)
-                     evgl_direct_partial_render_end();
+                  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);
 
-        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_fbo = framebuffer;
+                 // Save this for restore when doing make current
+                 ctx->current_read_fbo = framebuffer;
+               }
+          }
+        else
+          {
+             glBindFramebuffer(target, framebuffer);
+          }
      }
 }
 
@@ -130,6 +215,61 @@ _evgl_glClearDepthf(GLclampf depth)
 }
 
 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)
 {
 #ifdef GL_GLES
@@ -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;
+             // 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)
+                         {
+                            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 (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)
+                         {
+                            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 (!(rsc=_evgl_tls_resource_get()))
+             if (pname == GL_NUM_EXTENSIONS)
+               {
+                  *params = (GLfloat)evgl_api_ext_num_extensions_get(ctx->version);
+                  return;
+               }
+          }
+     }
+   else
+     {
+        if (ctx->version == EVAS_GL_GLES_2_X)
           {
-             ERR("Unable to execute GL command. Error retrieving tls");
-             return;
+             if (pname == GL_FRAMEBUFFER_BINDING)
+               {
+                  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;
+     }
 
-        ctx = rsc->current_ctx;
-        if (!ctx)
+   if (!_evgl_direct_enabled())
+     {
+        if (ctx->version == EVAS_GL_GLES_2_X)
           {
-             ERR("Unable to retrive Current Context");
-             return;
+             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;
+     }
 
-        // Only need to handle it if it's directly rendering to the window
-        if (!(rsc->current_ctx->current_fbo))
+   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)
           {
-             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)
+                         {
+                            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 (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)
+                    {
+                       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))
                     {
-                       memcpy(params, ctx->viewport_coord, sizeof(int)*4);
+                       params[0] = 0;
+                       params[1] = 0;
+                       params[2] = (GLint)rsc->direct.img.w;
+                       params[3] = (GLint)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 = evgl_api_ext_num_extensions_get(ctx->version);
                   return;
                }
           }
      }
    else
      {
-        if (pname == GL_FRAMEBUFFER_BINDING)
+        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)
           {
-             rsc = _evgl_tls_resource_get();
-             ctx = rsc ? rsc->current_ctx : NULL;
-             if (ctx)
+             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 = ctx->current_fbo;
+                  *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
 
index 40d5600..662fbac 100644 (file)
@@ -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))
index eb6f156..fd6cb55 100644 (file)
@@ -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;
+}
index df128da..118e409 100644 (file)
@@ -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
 
index c421b8c..f282857 100644 (file)
@@ -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))
index 307aa6a..845aa3f 100644 (file)
@@ -32,6 +32,8 @@
 #  ifdef GL_GLES
 #   include <GLES2/gl2.h>
 #   include <GLES2/gl2ext.h>
+#   include <GLES3/gl3.h>
+#   include <GLES3/gl3ext.h>
 #  else
 #   include <GL/gl.h>
 #   include <GL/glext.h>
index ef012cf..2a0787d 100644 (file)
@@ -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;
+                  // 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)
+                    {
+                       _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)
+                         {
+                            if (!ctx->partial_render)
+                              {
+                                 evgl_direct_partial_render_start();
+                                 ctx->partial_render = 1;
+                              }
+                         }
+                    }
                }
-             else if (ctx->current_sfc && (ctx->current_sfc->pbuffer.is_pbuffer))
+             else
                {
-                  // Using the same context, we were rendering on a pbuffer
-                  _framebuffer_bind(0, use_extension);
-                  ctx->current_fbo = 0;
-               }
+                  // 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->current_fbo == 0)
                     {
-                       if (!ctx->partial_render)
+                       // 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;
+                              }
                          }
                     }
                }
@@ -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;
           }
index 87c74d2..41151d5 100644 (file)
@@ -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