forked from enlightenment/efl
3522 lines
99 KiB
C
3522 lines
99 KiB
C
#define GL_ERRORS_NODEF 1
|
|
#include "evas_gl_core_private.h"
|
|
#include "evas_gl_api_ext.h"
|
|
|
|
#ifndef _WIN32
|
|
# include <dlfcn.h>
|
|
#endif
|
|
|
|
#define EVGL_FUNC_BEGIN() if (UNLIKELY(_need_context_restore)) _context_restore()
|
|
|
|
#define EVGLD_FUNC_BEGIN() \
|
|
{ \
|
|
EVGL_FUNC_BEGIN(); \
|
|
_func_begin_debug(__FUNCTION__); \
|
|
}
|
|
|
|
#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;
|
|
//---------------------------------------//
|
|
// API Debug Error Checking Code
|
|
static
|
|
void _make_current_check(const char* api)
|
|
{
|
|
EVGL_Context *ctx = NULL;
|
|
|
|
ctx = evas_gl_common_current_context_get();
|
|
|
|
if (!ctx)
|
|
CRI("\e[1;33m%s\e[m: Current Context NOT SET: GL Call Should NOT Be Called without MakeCurrent!!!", api);
|
|
else if ((ctx->version != EVAS_GL_GLES_2_X) && (ctx->version != EVAS_GL_GLES_3_X))
|
|
CRI("\e[1;33m%s\e[m: This API is being called with the wrong context (invalid version).", api);
|
|
}
|
|
|
|
static
|
|
void _direct_rendering_check(const char *api)
|
|
{
|
|
EVGL_Context *ctx = NULL;
|
|
|
|
ctx = evas_gl_common_current_context_get();
|
|
if (!ctx)
|
|
{
|
|
ERR("Current Context Not Set");
|
|
return;
|
|
}
|
|
|
|
if (_evgl_not_in_pixel_get())
|
|
{
|
|
CRI("\e[1;33m%s\e[m: This API is being called outside Pixel Get Callback Function.", api);
|
|
}
|
|
}
|
|
|
|
static
|
|
void _func_begin_debug(const char *api)
|
|
{
|
|
_make_current_check(api);
|
|
_direct_rendering_check(api);
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
// GL to GLES Compatibility Functions
|
|
//-------------------------------------------------------------//
|
|
void
|
|
_evgl_glBindFramebuffer(GLenum target, GLuint framebuffer)
|
|
{
|
|
EVGL_Context *ctx = NULL;
|
|
EVGL_Resource *rsc;
|
|
|
|
rsc = _evgl_tls_resource_get();
|
|
ctx = evas_gl_common_current_context_get();
|
|
|
|
if (!ctx)
|
|
{
|
|
ERR("No current context set.");
|
|
return;
|
|
}
|
|
if (!rsc)
|
|
{
|
|
ERR("No current TLS resource.");
|
|
return;
|
|
}
|
|
|
|
// Take care of BindFramebuffer 0 issue
|
|
if (ctx->version == EVAS_GL_GLES_2_X)
|
|
{
|
|
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_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, framebuffer);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
_evgl_glClearDepthf(GLclampf depth)
|
|
{
|
|
#ifdef GL_GLES
|
|
glClearDepthf(depth);
|
|
#else
|
|
glClearDepth(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 retrieve 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
|
|
glDepthRangef(zNear, zFar);
|
|
#else
|
|
glDepthRange(zNear, 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)
|
|
{
|
|
#ifdef GL_GLES
|
|
glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
|
|
#else
|
|
if (range)
|
|
{
|
|
range[0] = -126; // floor(log2(FLT_MIN))
|
|
range[1] = 127; // floor(log2(FLT_MAX))
|
|
}
|
|
if (precision)
|
|
{
|
|
precision[0] = 24; // floor(-log2((1.0/16777218.0)));
|
|
}
|
|
return;
|
|
if (shadertype) shadertype = precisiontype = 0;
|
|
#endif
|
|
}
|
|
|
|
void
|
|
_evgl_glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length)
|
|
{
|
|
#ifdef GL_GLES
|
|
glShaderBinary(n, shaders, binaryformat, binary, length);
|
|
#else
|
|
// FIXME: need to dlsym/getprocaddress for this
|
|
ERR("Binary Shader is not supported here yet.");
|
|
(void)n;
|
|
(void)shaders;
|
|
(void)binaryformat;
|
|
(void)binary;
|
|
(void)length;
|
|
#endif
|
|
}
|
|
|
|
void
|
|
_evgl_glReleaseShaderCompiler(void)
|
|
{
|
|
#ifdef GL_GLES
|
|
glReleaseShaderCompiler();
|
|
#else
|
|
#endif
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------//
|
|
// Calls related to Evas GL Direct Rendering
|
|
//-------------------------------------------------------------//
|
|
// Transform from Evas Coordinat to GL Coordinate
|
|
// returns: imgc[4] (oc[4]) original image object dimension in gl coord
|
|
// returns: objc[4] (nc[4]) tranformed (x, y, width, heigth) in gl coord
|
|
// returns: cc[4] cliped coordinate in original coordinate
|
|
void
|
|
compute_gl_coordinates(int win_w, int win_h, int rot, int clip_image,
|
|
int x, int y, int width, int height,
|
|
int img_x, int img_y, int img_w, int img_h,
|
|
int clip_x, int clip_y, int clip_w, int clip_h,
|
|
int imgc[4], int objc[4], int cc[4])
|
|
{
|
|
if (rot == 0)
|
|
{
|
|
// oringinal image object coordinate in gl coordinate
|
|
imgc[0] = img_x;
|
|
imgc[1] = win_h - img_y - img_h;
|
|
imgc[2] = imgc[0] + img_w;
|
|
imgc[3] = imgc[1] + img_h;
|
|
|
|
// clip coordinates in gl coordinate
|
|
cc[0] = clip_x;
|
|
cc[1] = win_h - clip_y - clip_h;
|
|
cc[2] = cc[0] + clip_w;
|
|
cc[3] = cc[1] + clip_h;
|
|
|
|
// transformed (x,y,width,height) in gl coordinate
|
|
objc[0] = imgc[0] + x;
|
|
objc[1] = imgc[1] + y;
|
|
objc[2] = objc[0] + width;
|
|
objc[3] = objc[1] + height;
|
|
}
|
|
else if (rot == 180)
|
|
{
|
|
// oringinal image object coordinate in gl coordinate
|
|
imgc[0] = win_w - img_x - img_w;
|
|
imgc[1] = img_y;
|
|
imgc[2] = imgc[0] + img_w;
|
|
imgc[3] = imgc[1] + img_h;
|
|
|
|
// clip coordinates in gl coordinate
|
|
cc[0] = win_w - clip_x - clip_w;
|
|
cc[1] = clip_y;
|
|
cc[2] = cc[0] + clip_w;
|
|
cc[3] = cc[1] + clip_h;
|
|
|
|
// transformed (x,y,width,height) in gl coordinate
|
|
objc[0] = imgc[0] + img_w - x - width;
|
|
objc[1] = imgc[1] + img_h - y - height;
|
|
objc[2] = objc[0] + width;
|
|
objc[3] = objc[1] + height;
|
|
|
|
}
|
|
else if (rot == 90)
|
|
{
|
|
// oringinal image object coordinate in gl coordinate
|
|
imgc[0] = img_y;
|
|
imgc[1] = img_x;
|
|
imgc[2] = imgc[0] + img_h;
|
|
imgc[3] = imgc[1] + img_w;
|
|
|
|
// clip coordinates in gl coordinate
|
|
cc[0] = clip_y;
|
|
cc[1] = clip_x;
|
|
cc[2] = cc[0] + clip_h;
|
|
cc[3] = cc[1] + clip_w;
|
|
|
|
// transformed (x,y,width,height) in gl coordinate
|
|
objc[0] = imgc[0] + img_h - y - height;
|
|
objc[1] = imgc[1] + x;
|
|
objc[2] = objc[0] + height;
|
|
objc[3] = objc[1] + width;
|
|
}
|
|
else if (rot == 270)
|
|
{
|
|
// oringinal image object coordinate in gl coordinate
|
|
imgc[0] = win_h - img_y - img_h;
|
|
imgc[1] = win_w - img_x - img_w;
|
|
imgc[2] = imgc[0] + img_h;
|
|
imgc[3] = imgc[1] + img_w;
|
|
|
|
// clip coordinates in gl coordinate
|
|
cc[0] = win_h - clip_y - clip_h;
|
|
cc[1] = win_w - clip_x - clip_w;
|
|
cc[2] = cc[0] + clip_h;
|
|
cc[3] = cc[1] + clip_w;
|
|
|
|
// transformed (x,y,width,height) in gl coordinate
|
|
objc[0] = imgc[0] + y;
|
|
objc[1] = imgc[1] + img_w - x - width;
|
|
objc[2] = objc[0] + height;
|
|
objc[3] = objc[1] + width;
|
|
}
|
|
else
|
|
{
|
|
ERR("Invalid rotation angle %d.", rot);
|
|
return;
|
|
}
|
|
|
|
if (clip_image)
|
|
{
|
|
// Clip against original image object
|
|
if (objc[0] < imgc[0]) objc[0] = imgc[0];
|
|
if (objc[0] > imgc[2]) objc[0] = imgc[2];
|
|
|
|
if (objc[1] < imgc[1]) objc[1] = imgc[1];
|
|
if (objc[1] > imgc[3]) objc[1] = imgc[3];
|
|
|
|
if (objc[2] < imgc[0]) objc[2] = imgc[0];
|
|
if (objc[2] > imgc[2]) objc[2] = imgc[2];
|
|
|
|
if (objc[3] < imgc[1]) objc[3] = imgc[1];
|
|
if (objc[3] > imgc[3]) objc[3] = imgc[3];
|
|
}
|
|
|
|
imgc[2] = imgc[2]-imgc[0]; // width
|
|
imgc[3] = imgc[3]-imgc[1]; // height
|
|
|
|
objc[2] = objc[2]-objc[0]; // width
|
|
objc[3] = objc[3]-objc[1]; // height
|
|
|
|
cc[2] = cc[2]-cc[0]; // width
|
|
cc[3] = cc[3]-cc[1]; // height
|
|
|
|
//DBG( "\e[1;32m Img[%d %d %d %d] Original [%d %d %d %d] Transformed[%d %d %d %d] Clip[%d %d %d %d] Clipped[%d %d %d %d] \e[m", img_x, img_y, img_w, img_h, imgc[0], imgc[1], imgc[2], imgc[3], objc[0], objc[1], objc[2], objc[3], clip[0], clip[1], clip[2], clip[3], cc[0], cc[1], cc[2], cc[3]);
|
|
}
|
|
|
|
static void
|
|
_evgl_glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
|
|
{
|
|
EVGL_Resource *rsc;
|
|
|
|
if (!(rsc=_evgl_tls_resource_get()))
|
|
{
|
|
ERR("Unable to execute GL command. Error retrieving tls");
|
|
return;
|
|
}
|
|
|
|
if (_evgl_direct_enabled())
|
|
{
|
|
rsc->clear_color.a = alpha;
|
|
rsc->clear_color.r = red;
|
|
rsc->clear_color.g = green;
|
|
rsc->clear_color.b = blue;
|
|
}
|
|
glClearColor(red, green, blue, alpha);
|
|
}
|
|
|
|
static void
|
|
_evgl_glClear(GLbitfield mask)
|
|
{
|
|
EVGL_Resource *rsc;
|
|
EVGL_Context *ctx;
|
|
int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,0};
|
|
int cc[4] = {0,0,0,0};
|
|
|
|
if (!(rsc=_evgl_tls_resource_get()))
|
|
{
|
|
ERR("Unable to execute GL command. Error retrieving tls");
|
|
return;
|
|
}
|
|
|
|
if (!rsc->current_eng)
|
|
{
|
|
ERR("Unable to retrieve Current Engine");
|
|
return;
|
|
}
|
|
|
|
ctx = rsc->current_ctx;
|
|
if (!ctx)
|
|
{
|
|
ERR("Unable to retrieve Current Context");
|
|
return;
|
|
}
|
|
|
|
if (_evgl_direct_enabled())
|
|
{
|
|
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
|
|
* marked as having an alpha channel!
|
|
* COPY mode forces the normal behaviour of glClear().
|
|
*/
|
|
if (ctx->current_sfc->alpha && !rsc->direct.render_op_copy &&
|
|
(mask & GL_COLOR_BUFFER_BIT))
|
|
{
|
|
if ((rsc->clear_color.a == 0) &&
|
|
(rsc->clear_color.r == 0) &&
|
|
(rsc->clear_color.g == 0) &&
|
|
(rsc->clear_color.b == 0))
|
|
{
|
|
// Skip clear color as we don't want to write black
|
|
mask &= ~GL_COLOR_BUFFER_BIT;
|
|
}
|
|
else if (rsc->clear_color.a != 1.0)
|
|
{
|
|
// TODO: Draw a rectangle? This will never be the perfect solution though.
|
|
WRN("glClear() used with a semi-transparent color and direct rendering. "
|
|
"This will erase the previous contents of the evas!");
|
|
}
|
|
if (!mask) return;
|
|
}
|
|
|
|
if ((!ctx->direct_scissor))
|
|
{
|
|
glEnable(GL_SCISSOR_TEST);
|
|
ctx->direct_scissor = 1;
|
|
}
|
|
|
|
if ((ctx->scissor_updated) && (ctx->scissor_enabled))
|
|
{
|
|
compute_gl_coordinates(rsc->direct.win_w, rsc->direct.win_h,
|
|
rsc->direct.rot, 1,
|
|
ctx->scissor_coord[0], ctx->scissor_coord[1],
|
|
ctx->scissor_coord[2], ctx->scissor_coord[3],
|
|
rsc->direct.img.x, rsc->direct.img.y,
|
|
rsc->direct.img.w, rsc->direct.img.h,
|
|
rsc->direct.clip.x, rsc->direct.clip.y,
|
|
rsc->direct.clip.w, rsc->direct.clip.h,
|
|
oc, nc, cc);
|
|
|
|
RECTS_CLIP_TO_RECT(nc[0], nc[1], nc[2], nc[3], cc[0], cc[1], cc[2], cc[3]);
|
|
glScissor(nc[0], nc[1], nc[2], nc[3]);
|
|
ctx->direct_scissor = 0;
|
|
}
|
|
else
|
|
{
|
|
compute_gl_coordinates(rsc->direct.win_w, rsc->direct.win_h,
|
|
rsc->direct.rot, 0,
|
|
0, 0, 0, 0,
|
|
rsc->direct.img.x, rsc->direct.img.y,
|
|
rsc->direct.img.w, rsc->direct.img.h,
|
|
rsc->direct.clip.x, rsc->direct.clip.y,
|
|
rsc->direct.clip.w, rsc->direct.clip.h,
|
|
oc, nc, cc);
|
|
glScissor(cc[0], cc[1], cc[2], cc[3]);
|
|
}
|
|
|
|
glClear(mask);
|
|
|
|
// TODO/FIXME: Restore previous client-side scissors.
|
|
}
|
|
else
|
|
{
|
|
if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
|
|
{
|
|
glDisable(GL_SCISSOR_TEST);
|
|
ctx->direct_scissor = 0;
|
|
}
|
|
|
|
glClear(mask);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
|
|
{
|
|
glDisable(GL_SCISSOR_TEST);
|
|
ctx->direct_scissor = 0;
|
|
}
|
|
|
|
glClear(mask);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_evgl_glEnable(GLenum cap)
|
|
{
|
|
EVGL_Context *ctx;
|
|
|
|
ctx = evas_gl_common_current_context_get();
|
|
|
|
if (ctx && (cap == GL_SCISSOR_TEST))
|
|
{
|
|
ctx->scissor_enabled = 1;
|
|
|
|
if (_evgl_direct_enabled())
|
|
{
|
|
EVGL_Resource *rsc = _evgl_tls_resource_get();
|
|
int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,0}, cc[4] = {0,0,0,0};
|
|
|
|
if (rsc)
|
|
{
|
|
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)
|
|
{
|
|
compute_gl_coordinates(rsc->direct.win_w, rsc->direct.win_h,
|
|
rsc->direct.rot, 0,
|
|
0, 0, 0, 0,
|
|
rsc->direct.img.x, rsc->direct.img.y,
|
|
rsc->direct.img.w, rsc->direct.img.h,
|
|
rsc->direct.clip.x, rsc->direct.clip.y,
|
|
rsc->direct.clip.w, rsc->direct.clip.h,
|
|
oc, nc, cc);
|
|
glScissor(cc[0], cc[1], cc[2], cc[3]);
|
|
}
|
|
else
|
|
{
|
|
compute_gl_coordinates(rsc->direct.win_w, rsc->direct.win_h,
|
|
rsc->direct.rot, 1,
|
|
ctx->scissor_coord[0], ctx->scissor_coord[1],
|
|
ctx->scissor_coord[2], ctx->scissor_coord[3],
|
|
rsc->direct.img.x, rsc->direct.img.y,
|
|
rsc->direct.img.w, rsc->direct.img.h,
|
|
rsc->direct.clip.x, rsc->direct.clip.y,
|
|
rsc->direct.clip.w, rsc->direct.clip.h,
|
|
oc, nc, cc);
|
|
glScissor(nc[0], nc[1], nc[2], nc[3]);
|
|
}
|
|
ctx->direct_scissor = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Bound to an FBO, reset scissors to user data
|
|
if (ctx->scissor_updated)
|
|
{
|
|
glScissor(ctx->scissor_coord[0], ctx->scissor_coord[1],
|
|
ctx->scissor_coord[2], ctx->scissor_coord[3]);
|
|
}
|
|
else if (ctx->direct_scissor)
|
|
{
|
|
// Back to the default scissors (here: max texture size)
|
|
glScissor(0, 0, evgl_engine->caps.max_w, evgl_engine->caps.max_h);
|
|
}
|
|
ctx->direct_scissor = 0;
|
|
}
|
|
|
|
glEnable(GL_SCISSOR_TEST);
|
|
return;
|
|
}
|
|
}
|
|
|
|
glEnable(cap);
|
|
}
|
|
|
|
static void
|
|
_evgl_glDisable(GLenum cap)
|
|
{
|
|
EVGL_Context *ctx;
|
|
|
|
ctx = evas_gl_common_current_context_get();
|
|
|
|
if (ctx && (cap == GL_SCISSOR_TEST))
|
|
{
|
|
ctx->scissor_enabled = 0;
|
|
|
|
if (_evgl_direct_enabled())
|
|
{
|
|
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};
|
|
EVGL_Resource *rsc = _evgl_tls_resource_get();
|
|
|
|
if (rsc)
|
|
{
|
|
compute_gl_coordinates(rsc->direct.win_w, rsc->direct.win_h,
|
|
rsc->direct.rot, 1,
|
|
0, 0, rsc->direct.img.w, rsc->direct.img.h,
|
|
rsc->direct.img.x, rsc->direct.img.y,
|
|
rsc->direct.img.w, rsc->direct.img.h,
|
|
rsc->direct.clip.x, rsc->direct.clip.y,
|
|
rsc->direct.clip.w, rsc->direct.clip.h,
|
|
oc, nc, cc);
|
|
|
|
RECTS_CLIP_TO_RECT(nc[0], nc[1], nc[2], nc[3], cc[0], cc[1], cc[2], cc[3]);
|
|
glScissor(nc[0], nc[1], nc[2], nc[3]);
|
|
|
|
ctx->direct_scissor = 1;
|
|
glEnable(GL_SCISSOR_TEST);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Bound to an FBO, disable scissors for real
|
|
ctx->direct_scissor = 0;
|
|
glDisable(GL_SCISSOR_TEST);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
glDisable(cap);
|
|
}
|
|
|
|
void
|
|
_evgl_glFramebufferParameteri(GLenum target, GLenum pname, GLint param)
|
|
{
|
|
EVGL_Resource *rsc;
|
|
EVGL_Context *ctx;
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(_gles3_api.glFramebufferParameteri);
|
|
|
|
if (!(rsc=_evgl_tls_resource_get()))
|
|
{
|
|
ERR("Unable to execute GL command. Error retrieving tls");
|
|
return;
|
|
}
|
|
|
|
if (!rsc->current_eng)
|
|
{
|
|
ERR("Unable to retrieve Current Engine");
|
|
return;
|
|
}
|
|
|
|
ctx = rsc->current_ctx;
|
|
if (!ctx)
|
|
{
|
|
ERR("Unable to retrieve Current Context");
|
|
return;
|
|
}
|
|
|
|
if (!_evgl_direct_enabled())
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
_gles3_api.glFramebufferParameteri(target, pname, param);
|
|
}
|
|
|
|
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 retrieve Current Engine");
|
|
return;
|
|
}
|
|
|
|
ctx = rsc->current_ctx;
|
|
if (!ctx)
|
|
{
|
|
ERR("Unable to retrieve 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 retrieve Current Engine");
|
|
return;
|
|
}
|
|
|
|
ctx = rsc->current_ctx;
|
|
if (!ctx)
|
|
{
|
|
ERR("Unable to retrieve 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_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 retrieve 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)
|
|
{
|
|
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 (pname == GL_NUM_EXTENSIONS)
|
|
{
|
|
*params = (GLfloat)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 = (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 retrieve 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_glGetFramebufferParameteriv(GLenum target, GLenum pname, GLint* params)
|
|
{
|
|
EVGL_Resource *rsc;
|
|
EVGL_Context *ctx;
|
|
|
|
EINA_SAFETY_ON_NULL_RETURN(_gles3_api.glGetFramebufferParameteriv);
|
|
|
|
if (!(rsc=_evgl_tls_resource_get()))
|
|
{
|
|
ERR("Unable to execute GL command. Error retrieving tls");
|
|
return;
|
|
}
|
|
|
|
if (!rsc->current_eng)
|
|
{
|
|
ERR("Unable to retrieve Current Engine");
|
|
return;
|
|
}
|
|
|
|
ctx = rsc->current_ctx;
|
|
if (!ctx)
|
|
{
|
|
ERR("Unable to retrieve Current Context");
|
|
return;
|
|
}
|
|
|
|
if (!_evgl_direct_enabled())
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
_gles3_api.glGetFramebufferParameteriv(target, 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 retrieve 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
glGetIntegerv(pname, params);
|
|
}
|
|
|
|
static const GLubyte *
|
|
_evgl_glGetString(GLenum name)
|
|
{
|
|
static char _version[128] = {0};
|
|
static char _glsl[128] = {0};
|
|
const char *ret, *version_extra;
|
|
EVGL_Resource *rsc;
|
|
EVGL_Context *ctx;
|
|
|
|
/* We wrap two values here:
|
|
*
|
|
* VERSION: Since OpenGL ES 3 is not supported yet*, we return OpenGL ES 2.0
|
|
* The string is not modified on desktop GL (eg. 4.4.0 NVIDIA 343.22)
|
|
* GLES 3 support is not exposed because apps can't use GLES 3 core
|
|
* functions yet.
|
|
*
|
|
* EXTENSIONS: This should return only the list of GL extensions supported
|
|
* by Evas GL. This means as many extensions as possible should be
|
|
* added to the whitelist.
|
|
*
|
|
* *: GLES 3.0/3.1 is not fully supported... we also have buggy drivers!
|
|
*/
|
|
|
|
/*
|
|
* Note from Khronos: "If an error is generated, glGetString returns 0."
|
|
* I decided not to call glGetString if there is no context as this is
|
|
* known to cause crashes on certain GL drivers (eg. Nvidia binary blob).
|
|
* --> crash moved to app side if they blindly call strstr()
|
|
*/
|
|
|
|
/* NOTE: Please modify software_generic/evas_engine.c as well if you change
|
|
* this function!
|
|
*/
|
|
|
|
if ((!(rsc = _evgl_tls_resource_get())) || !rsc->current_ctx)
|
|
{
|
|
ERR("Current context is NULL, not calling glGetString");
|
|
// This sets evas_gl_error_get instead of eglGetError...
|
|
evas_gl_common_error_set(EVAS_GL_BAD_CONTEXT);
|
|
return NULL;
|
|
}
|
|
|
|
ctx = rsc->current_ctx;
|
|
switch (name)
|
|
{
|
|
case GL_VENDOR:
|
|
case GL_RENDERER:
|
|
// Keep these as-is.
|
|
break;
|
|
|
|
case GL_SHADING_LANGUAGE_VERSION:
|
|
ret = (const char *) glGetString(GL_SHADING_LANGUAGE_VERSION);
|
|
if (!ret) return NULL;
|
|
#ifdef GL_GLES
|
|
// FIXME: We probably shouldn't wrap anything for EGL
|
|
if (ret[18] != '1')
|
|
{
|
|
// We try not to remove the vendor fluff
|
|
snprintf(_glsl, sizeof(_glsl), "OpenGL ES GLSL ES 1.00 Evas GL (%s)", ret + 18);
|
|
_glsl[sizeof(_glsl) - 1] = '\0';
|
|
return (const GLubyte *) _glsl;
|
|
}
|
|
return (const GLubyte *) ret;
|
|
#else
|
|
// Desktop GL, we still keep the official name
|
|
snprintf(_glsl, sizeof(_glsl), "OpenGL ES GLSL ES 1.00 Evas GL (%s)", (char *) ret);
|
|
_version[sizeof(_glsl) - 1] = '\0';
|
|
return (const GLubyte *) _glsl;
|
|
#endif
|
|
|
|
case GL_VERSION:
|
|
ret = (const char *) glGetString(GL_VERSION);
|
|
if (!ret) return NULL;
|
|
#ifdef GL_GLES
|
|
version_extra = ret + 10;
|
|
#else
|
|
version_extra = ret;
|
|
#endif
|
|
snprintf(_version, sizeof(_version), "OpenGL ES %d.%d Evas GL (%s)",
|
|
(int) ctx->version, ctx->version_minor, version_extra);
|
|
_version[sizeof(_version) - 1] = '\0';
|
|
return (const GLubyte *) _version;
|
|
|
|
case GL_EXTENSIONS:
|
|
// Passing the version - GLESv2/GLESv3.
|
|
return (GLubyte *) evgl_api_ext_string_get(EINA_TRUE, rsc->current_ctx->version);
|
|
|
|
default:
|
|
// GL_INVALID_ENUM is generated if name is not an accepted value.
|
|
WRN("Unknown string requested: %x", (unsigned int) name);
|
|
break;
|
|
}
|
|
|
|
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 retrieve 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)
|
|
{
|
|
EVGL_Resource *rsc;
|
|
EVGL_Context *ctx;
|
|
int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,0};
|
|
int cc[4] = {0,0,0,0};
|
|
|
|
|
|
if (!(rsc=_evgl_tls_resource_get()))
|
|
{
|
|
ERR("Unable to execute GL command. Error retrieving tls");
|
|
return;
|
|
}
|
|
|
|
if (!rsc->current_eng)
|
|
{
|
|
ERR("Unable to retrieve Current Engine");
|
|
return;
|
|
}
|
|
|
|
ctx = rsc->current_ctx;
|
|
if (!ctx)
|
|
{
|
|
ERR("Unable to retrieve Current Context");
|
|
return;
|
|
}
|
|
|
|
if (_evgl_direct_enabled())
|
|
{
|
|
|
|
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,
|
|
x, y, width, height,
|
|
rsc->direct.img.x, rsc->direct.img.y,
|
|
rsc->direct.img.w, rsc->direct.img.h,
|
|
rsc->direct.clip.x, rsc->direct.clip.y,
|
|
rsc->direct.clip.w, rsc->direct.clip.h,
|
|
oc, nc, cc);
|
|
glReadPixels(nc[0], nc[1], nc[2], nc[3], format, type, pixels);
|
|
}
|
|
else
|
|
{
|
|
glReadPixels(x, y, width, height, format, type, pixels);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
glReadPixels(x, y, width, height, format, type, pixels);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_evgl_glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
|
|
{
|
|
EVGL_Resource *rsc;
|
|
EVGL_Context *ctx;
|
|
int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,0};
|
|
int cc[4] = {0,0,0,0};
|
|
|
|
if (!(rsc=_evgl_tls_resource_get()))
|
|
{
|
|
ERR("Unable to execute GL command. Error retrieving tls");
|
|
return;
|
|
}
|
|
|
|
if (!rsc->current_eng)
|
|
{
|
|
ERR("Unable to retrieve Current Engine");
|
|
return;
|
|
}
|
|
|
|
ctx = rsc->current_ctx;
|
|
if (!ctx)
|
|
{
|
|
ERR("Unable to retrieve Current Context");
|
|
return;
|
|
}
|
|
|
|
if (_evgl_direct_enabled())
|
|
{
|
|
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))
|
|
{
|
|
glDisable(GL_SCISSOR_TEST);
|
|
}
|
|
|
|
compute_gl_coordinates(rsc->direct.win_w, rsc->direct.win_h,
|
|
rsc->direct.rot, 1,
|
|
x, y, width, height,
|
|
rsc->direct.img.x, rsc->direct.img.y,
|
|
rsc->direct.img.w, rsc->direct.img.h,
|
|
rsc->direct.clip.x, rsc->direct.clip.y,
|
|
rsc->direct.clip.w, rsc->direct.clip.h,
|
|
oc, nc, cc);
|
|
|
|
// Keep a copy of the original coordinates
|
|
ctx->scissor_coord[0] = x;
|
|
ctx->scissor_coord[1] = y;
|
|
ctx->scissor_coord[2] = width;
|
|
ctx->scissor_coord[3] = height;
|
|
|
|
RECTS_CLIP_TO_RECT(nc[0], nc[1], nc[2], nc[3], cc[0], cc[1], cc[2], cc[3]);
|
|
glScissor(nc[0], nc[1], nc[2], nc[3]);
|
|
|
|
ctx->direct_scissor = 0;
|
|
|
|
// Mark user scissor_coord as valid
|
|
ctx->scissor_updated = 1;
|
|
}
|
|
else
|
|
{
|
|
// Bound to an FBO, use these new scissors
|
|
if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
|
|
{
|
|
glDisable(GL_SCISSOR_TEST);
|
|
ctx->direct_scissor = 0;
|
|
}
|
|
|
|
glScissor(x, y, width, height);
|
|
|
|
// Why did we set this flag to 0???
|
|
//ctx->scissor_updated = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
|
|
{
|
|
glDisable(GL_SCISSOR_TEST);
|
|
ctx->direct_scissor = 0;
|
|
}
|
|
|
|
glScissor(x, y, width, height);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_evgl_glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
|
|
{
|
|
EVGL_Resource *rsc;
|
|
EVGL_Context *ctx;
|
|
int oc[4] = {0,0,0,0}, nc[4] = {0,0,0,0};
|
|
int cc[4] = {0,0,0,0};
|
|
|
|
if (!(rsc=_evgl_tls_resource_get()))
|
|
{
|
|
ERR("Unable to execute GL command. Error retrieving tls");
|
|
return;
|
|
}
|
|
|
|
if (!rsc->current_eng)
|
|
{
|
|
ERR("Unable to retrieve Current Engine");
|
|
return;
|
|
}
|
|
|
|
ctx = rsc->current_ctx;
|
|
if (!ctx)
|
|
{
|
|
ERR("Unable to retrieve Current Context");
|
|
return;
|
|
}
|
|
|
|
if (_evgl_direct_enabled())
|
|
{
|
|
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))
|
|
{
|
|
glEnable(GL_SCISSOR_TEST);
|
|
ctx->direct_scissor = 1;
|
|
}
|
|
|
|
if ((ctx->scissor_updated) && (ctx->scissor_enabled))
|
|
{
|
|
// Recompute the scissor coordinates
|
|
compute_gl_coordinates(rsc->direct.win_w, rsc->direct.win_h,
|
|
rsc->direct.rot, 1,
|
|
ctx->scissor_coord[0], ctx->scissor_coord[1],
|
|
ctx->scissor_coord[2], ctx->scissor_coord[3],
|
|
rsc->direct.img.x, rsc->direct.img.y,
|
|
rsc->direct.img.w, rsc->direct.img.h,
|
|
rsc->direct.clip.x, rsc->direct.clip.y,
|
|
rsc->direct.clip.w, rsc->direct.clip.h,
|
|
oc, nc, cc);
|
|
|
|
RECTS_CLIP_TO_RECT(nc[0], nc[1], nc[2], nc[3], cc[0], cc[1], cc[2], cc[3]);
|
|
glScissor(nc[0], nc[1], nc[2], nc[3]);
|
|
|
|
ctx->direct_scissor = 0;
|
|
|
|
// Compute the viewport coordinate
|
|
compute_gl_coordinates(rsc->direct.win_w, rsc->direct.win_h,
|
|
rsc->direct.rot, 0,
|
|
x, y, width, height,
|
|
rsc->direct.img.x, rsc->direct.img.y,
|
|
rsc->direct.img.w, rsc->direct.img.h,
|
|
rsc->direct.clip.x, rsc->direct.clip.y,
|
|
rsc->direct.clip.w, rsc->direct.clip.h,
|
|
oc, nc, cc);
|
|
glViewport(nc[0], nc[1], nc[2], nc[3]);
|
|
}
|
|
else
|
|
{
|
|
|
|
compute_gl_coordinates(rsc->direct.win_w, rsc->direct.win_h,
|
|
rsc->direct.rot, 0,
|
|
x, y, width, height,
|
|
rsc->direct.img.x, rsc->direct.img.y,
|
|
rsc->direct.img.w, rsc->direct.img.h,
|
|
rsc->direct.clip.x, rsc->direct.clip.y,
|
|
rsc->direct.clip.w, rsc->direct.clip.h,
|
|
oc, nc, cc);
|
|
glScissor(cc[0], cc[1], cc[2], cc[3]);
|
|
|
|
glViewport(nc[0], nc[1], nc[2], nc[3]);
|
|
}
|
|
|
|
ctx->viewport_direct[0] = nc[0];
|
|
ctx->viewport_direct[1] = nc[1];
|
|
ctx->viewport_direct[2] = nc[2];
|
|
ctx->viewport_direct[3] = nc[3];
|
|
|
|
// Keep a copy of the original coordinates
|
|
ctx->viewport_coord[0] = x;
|
|
ctx->viewport_coord[1] = y;
|
|
ctx->viewport_coord[2] = width;
|
|
ctx->viewport_coord[3] = height;
|
|
|
|
ctx->viewport_updated = 1;
|
|
}
|
|
else
|
|
{
|
|
if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
|
|
{
|
|
glDisable(GL_SCISSOR_TEST);
|
|
ctx->direct_scissor = 0;
|
|
}
|
|
|
|
glViewport(x, y, width, height);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
|
|
{
|
|
glDisable(GL_SCISSOR_TEST);
|
|
ctx->direct_scissor = 0;
|
|
}
|
|
|
|
glViewport(x, y, width, height);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_evgl_glDrawBuffers(GLsizei n, const GLenum *bufs)
|
|
{
|
|
EVGL_Context *ctx;
|
|
Eina_Bool target_is_fbo = EINA_FALSE;
|
|
unsigned int drawbuffer;
|
|
|
|
if (!_gles3_api.glDrawBuffers) return;
|
|
|
|
ctx = evas_gl_common_current_context_get();
|
|
if (!ctx)
|
|
{
|
|
ERR("Unable to retrieve Current Context");
|
|
return;
|
|
}
|
|
|
|
if (!bufs)
|
|
{
|
|
_gles3_api.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;
|
|
_gles3_api.glDrawBuffers(n, &drawbuffer);
|
|
}
|
|
else if ((*bufs & GL_COLOR_ATTACHMENT0) == GL_COLOR_ATTACHMENT0)
|
|
{
|
|
SET_GL_ERROR(GL_INVALID_OPERATION);
|
|
}
|
|
else
|
|
{
|
|
_gles3_api.glDrawBuffers(n, bufs);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
SET_GL_ERROR(GL_INVALID_OPERATION);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_gles3_api.glDrawBuffers(n, bufs);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_evgl_glReadBuffer(GLenum src)
|
|
{
|
|
EVGL_Context *ctx;
|
|
Eina_Bool target_is_fbo = EINA_FALSE;
|
|
|
|
if (!_gles3_api.glReadBuffer) return;
|
|
|
|
ctx = evas_gl_common_current_context_get();
|
|
if (!ctx)
|
|
{
|
|
ERR("Unable to retrieve 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)
|
|
{
|
|
_gles3_api.glReadBuffer(GL_COLOR_ATTACHMENT0);
|
|
}
|
|
else if((src & GL_COLOR_ATTACHMENT0) == GL_COLOR_ATTACHMENT0)
|
|
{
|
|
SET_GL_ERROR(GL_INVALID_OPERATION);
|
|
}
|
|
else
|
|
{
|
|
_gles3_api.glReadBuffer(src);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_gles3_api.glReadBuffer(src);
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------//
|
|
// Open GLES 2.0 APIs
|
|
#define _EVASGL_FUNCTION_PRIVATE_BEGIN(ret, name, param1, param2) \
|
|
static ret evgl_##name param1 { \
|
|
EVGL_FUNC_BEGIN(); \
|
|
return _evgl_##name param2; \
|
|
}
|
|
|
|
#define _EVASGL_FUNCTION_PRIVATE_BEGIN_VOID(name, param1, param2) \
|
|
static void evgl_##name param1 { \
|
|
EVGL_FUNC_BEGIN(); \
|
|
_evgl_##name param2; \
|
|
}
|
|
|
|
#define _EVASGL_FUNCTION_BEGIN(ret, name, param1, param2) \
|
|
static ret evgl_##name param1 { \
|
|
EVGL_FUNC_BEGIN(); \
|
|
return name param2; \
|
|
}
|
|
|
|
#define _EVASGL_FUNCTION_BEGIN_VOID(name, param1, param2) \
|
|
static void evgl_##name param1 { \
|
|
EVGL_FUNC_BEGIN(); \
|
|
name param2; \
|
|
}
|
|
|
|
#include "evas_gl_api_def.h"
|
|
|
|
#undef _EVASGL_FUNCTION_PRIVATE_BEGIN
|
|
#undef _EVASGL_FUNCTION_PRIVATE_BEGIN_VOID
|
|
#undef _EVASGL_FUNCTION_BEGIN
|
|
#undef _EVASGL_FUNCTION_BEGIN_VOID
|
|
|
|
|
|
//-------------------------------------------------------------//
|
|
// Open GLES 2.0 APIs DEBUG
|
|
#define _EVASGL_FUNCTION_PRIVATE_BEGIN(ret, name, param1, param2) \
|
|
static ret _evgld_##name param1 { \
|
|
EVGLD_FUNC_BEGIN(); \
|
|
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(); \
|
|
_evgl_##name param2; \
|
|
EVGLD_FUNC_END(); \
|
|
}
|
|
|
|
#define _EVASGL_FUNCTION_BEGIN(ret, name, param1, param2) \
|
|
static ret _evgld_##name param1 { \
|
|
EVGLD_FUNC_BEGIN(); \
|
|
ret _a = name param2; \
|
|
EVGLD_FUNC_END(); \
|
|
return _a; \
|
|
}
|
|
|
|
#define _EVASGL_FUNCTION_BEGIN_VOID(name, param1, param2) \
|
|
static void _evgld_##name param1 { \
|
|
EVGLD_FUNC_BEGIN(); \
|
|
name param2; \
|
|
EVGLD_FUNC_END(); \
|
|
}
|
|
|
|
#include "evas_gl_api_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
|
|
#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(); \
|
|
if (!_gles3_api.name) return (ret)0; \
|
|
return _gles3_api.name param2; \
|
|
}
|
|
|
|
#define _EVASGL_FUNCTION_BEGIN_VOID(name, param1, param2) \
|
|
static void evgl_gles3_##name param1 { \
|
|
EVGL_FUNC_BEGIN(); \
|
|
if (!_gles3_api.name) return; \
|
|
_gles3_api.name param2; \
|
|
}
|
|
|
|
#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(); \
|
|
if (!_gles3_api.name) return (ret)0; \
|
|
ret _a = _gles3_api.name param2; \
|
|
EVGLD_FUNC_END(); \
|
|
return _a; \
|
|
}
|
|
|
|
#define _EVASGL_FUNCTION_BEGIN_VOID(name, param1, param2) \
|
|
static void _evgld_##name param1 { \
|
|
EVGLD_FUNC_BEGIN(); \
|
|
if (!_gles3_api.name) return; \
|
|
_gles3_api.name param2; \
|
|
EVGLD_FUNC_END(); \
|
|
}
|
|
|
|
#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
|
|
|
|
//-------------------------------------------------------------//
|
|
// Calls for stripping precision string in the shader
|
|
#if 0
|
|
|
|
static const char *
|
|
opengl_strtok(const char *s, int *n, char **saveptr, char *prevbuf)
|
|
{
|
|
char *start;
|
|
char *ret;
|
|
char *p;
|
|
int retlen;
|
|
static const char *delim = " \t\n\r/";
|
|
|
|
if (prevbuf)
|
|
free(prevbuf);
|
|
|
|
if (s)
|
|
{
|
|
*saveptr = s;
|
|
}
|
|
else
|
|
{
|
|
if (!(*saveptr) || !(*n))
|
|
return NULL;
|
|
s = *saveptr;
|
|
}
|
|
|
|
for (; *n && strchr(delim, *s); s++, (*n)--)
|
|
{
|
|
if (*s == '/' && *n > 1)
|
|
{
|
|
if (s[1] == '/')
|
|
{
|
|
do {
|
|
s++, (*n)--;
|
|
} while (*n > 1 && s[1] != '\n' && s[1] != '\r');
|
|
}
|
|
else if (s[1] == '*')
|
|
{
|
|
do {
|
|
s++, (*n)--;
|
|
} while (*n > 2 && (s[1] != '*' || s[2] != '/'));
|
|
s++, (*n)--;
|
|
s++, (*n)--;
|
|
if (*n == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
start = s;
|
|
for (; *n && *s && !strchr(delim, *s); s++, (*n)--);
|
|
if (*n > 0)
|
|
s++, (*n)--;
|
|
|
|
*saveptr = s;
|
|
|
|
retlen = s - start;
|
|
ret = malloc(retlen + 1);
|
|
p = ret;
|
|
|
|
if (retlen == 0)
|
|
{
|
|
*p = 0;
|
|
return;
|
|
}
|
|
|
|
while (retlen > 0)
|
|
{
|
|
if (*start == '/' && retlen > 1)
|
|
{
|
|
if (start[1] == '/')
|
|
{
|
|
do {
|
|
start++, retlen--;
|
|
} while (retlen > 1 && start[1] != '\n' && start[1] != '\r');
|
|
start++, retlen--;
|
|
continue;
|
|
} else if (start[1] == '*')
|
|
{
|
|
do {
|
|
start++, retlen--;
|
|
} while (retlen > 2 && (start[1] != '*' || start[2] != '/'));
|
|
start += 3, retlen -= 3;
|
|
continue;
|
|
}
|
|
}
|
|
*(p++) = *(start++), retlen--;
|
|
}
|
|
|
|
*p = 0;
|
|
return ret;
|
|
}
|
|
|
|
static char *
|
|
do_eglShaderPatch(const char *source, int length, int *patched_len)
|
|
{
|
|
char *saveptr = NULL;
|
|
char *sp;
|
|
char *p = NULL;
|
|
|
|
if (!length) length = strlen(source);
|
|
|
|
*patched_len = 0;
|
|
int patched_size = length;
|
|
char *patched = malloc(patched_size + 1);
|
|
|
|
if (!patched) return NULL;
|
|
|
|
p = opengl_strtok(source, &length, &saveptr, NULL);
|
|
|
|
for (; p; p = opengl_strtok(0, &length, &saveptr, p))
|
|
{
|
|
if (!strncmp(p, "lowp", 4) || !strncmp(p, "mediump", 7) || !strncmp(p, "highp", 5))
|
|
{
|
|
continue;
|
|
}
|
|
else if (!strncmp(p, "precision", 9))
|
|
{
|
|
while ((p = opengl_strtok(0, &length, &saveptr, p)) && !strchr(p, ';'));
|
|
}
|
|
else
|
|
{
|
|
if (!strncmp(p, "gl_MaxVertexUniformVectors", 26))
|
|
{
|
|
free(p);
|
|
p = strdup("(gl_MaxVertexUniformComponents / 4)");
|
|
}
|
|
else if (!strncmp(p, "gl_MaxFragmentUniformVectors", 28))
|
|
{
|
|
free(p);
|
|
p = strdup("(gl_MaxFragmentUniformComponents / 4)");
|
|
}
|
|
else if (!strncmp(p, "gl_MaxVaryingVectors", 20))
|
|
{
|
|
free(p);
|
|
p = strdup("(gl_MaxVaryingFloats / 4)");
|
|
}
|
|
|
|
int new_len = strlen(p);
|
|
if (*patched_len + new_len > patched_size)
|
|
{
|
|
char *tmp;
|
|
|
|
patched_size *= 2;
|
|
tmp = realloc(patched, patched_size + 1);
|
|
if (!tmp)
|
|
{
|
|
free(patched);
|
|
free(p);
|
|
return NULL;
|
|
}
|
|
patched = tmp;
|
|
}
|
|
|
|
memcpy(patched + *patched_len, p, new_len);
|
|
*patched_len += new_len;
|
|
}
|
|
}
|
|
|
|
patched[*patched_len] = 0;
|
|
/* check that we don't leave dummy preprocessor lines */
|
|
for (sp = patched; *sp;)
|
|
{
|
|
for (; *sp == ' ' || *sp == '\t'; sp++);
|
|
if (!strncmp(sp, "#define", 7))
|
|
{
|
|
for (p = sp + 7; *p == ' ' || *p == '\t'; p++);
|
|
if (*p == '\n' || *p == '\r' || *p == '/')
|
|
{
|
|
memset(sp, 0x20, 7);
|
|
}
|
|
}
|
|
for (; *sp && *sp != '\n' && *sp != '\r'; sp++);
|
|
for (; *sp == '\n' || *sp == '\r'; sp++);
|
|
}
|
|
return patched;
|
|
}
|
|
|
|
static int
|
|
shadersrc_gles_to_gl(GLsizei count, const char** string, char **s, const GLint* length, GLint *l)
|
|
{
|
|
int i;
|
|
|
|
for(i = 0; i < count; ++i) {
|
|
GLint len;
|
|
if(length) {
|
|
len = length[i];
|
|
if (len < 0)
|
|
len = string[i] ? strlen(string[i]) : 0;
|
|
} else
|
|
len = string[i] ? strlen(string[i]) : 0;
|
|
|
|
if(string[i]) {
|
|
s[i] = do_eglShaderPatch(string[i], len, &l[i]);
|
|
if(!s[i]) {
|
|
while(i)
|
|
free(s[--i]);
|
|
|
|
free(l);
|
|
free(s);
|
|
return -1;
|
|
}
|
|
} else {
|
|
s[i] = NULL;
|
|
l[i] = 0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void
|
|
_evgld_glShaderSource(GLuint shader, GLsizei count, const char* const* string, const GLint* length)
|
|
{
|
|
EVGLD_FUNC_BEGIN();
|
|
|
|
#ifdef GL_GLES
|
|
glShaderSource(shader, count, string, length);
|
|
goto finish;
|
|
#else
|
|
//GET_EXT_PTR(void, glShaderSource, (int, int, char **, void *));
|
|
int size = count;
|
|
int i;
|
|
int acc_length = 0;
|
|
GLchar **tab_prog = malloc(size * sizeof(GLchar *));
|
|
int *tab_length = (int *) length;
|
|
|
|
char **tab_prog_new;
|
|
GLint *tab_length_new;
|
|
|
|
tab_prog_new = malloc(count* sizeof(char*));
|
|
tab_length_new = malloc(count* sizeof(GLint));
|
|
|
|
memset(tab_prog_new, 0, count * sizeof(char*));
|
|
memset(tab_length_new, 0, count * sizeof(GLint));
|
|
|
|
for (i = 0; i < size; i++) {
|
|
tab_prog[i] = ((GLchar *) string) + acc_length;
|
|
acc_length += tab_length[i];
|
|
}
|
|
|
|
shadersrc_gles_to_gl(count, tab_prog, tab_prog_new, tab_length, tab_length_new);
|
|
|
|
if (!tab_prog_new || !tab_length_new)
|
|
ERR("Error allocating memory for shader string manipulation.");
|
|
|
|
glShaderSource(shader, count, tab_prog_new, tab_length_new);
|
|
|
|
for (i = 0; i < count; i++)
|
|
free(tab_prog_new[i]);
|
|
free(tab_prog_new);
|
|
free(tab_length_new);
|
|
|
|
free(tab_prog);
|
|
#endif
|
|
|
|
finish:
|
|
EVGLD_FUNC_END();
|
|
}
|
|
#endif
|
|
|
|
//-------------------------------------------------------------//
|
|
|
|
static void
|
|
_normal_gles2_api_get(Evas_GL_API *funcs)
|
|
{
|
|
funcs->version = EVAS_GL_API_VERSION;
|
|
|
|
#define ORD(f) EVAS_API_OVERRIDE(f, funcs, evgl_)
|
|
// GLES 2.0
|
|
ORD(glActiveTexture);
|
|
ORD(glAttachShader);
|
|
ORD(glBindAttribLocation);
|
|
ORD(glBindBuffer);
|
|
ORD(glBindTexture);
|
|
ORD(glBlendColor);
|
|
ORD(glBlendEquation);
|
|
ORD(glBlendEquationSeparate);
|
|
ORD(glBlendFunc);
|
|
ORD(glBlendFuncSeparate);
|
|
ORD(glBufferData);
|
|
ORD(glBufferSubData);
|
|
ORD(glCheckFramebufferStatus);
|
|
ORD(glClear);
|
|
ORD(glClearColor);
|
|
ORD(glClearDepthf);
|
|
ORD(glClearStencil);
|
|
ORD(glColorMask);
|
|
ORD(glCompileShader);
|
|
ORD(glCompressedTexImage2D);
|
|
ORD(glCompressedTexSubImage2D);
|
|
ORD(glCopyTexImage2D);
|
|
ORD(glCopyTexSubImage2D);
|
|
ORD(glCreateProgram);
|
|
ORD(glCreateShader);
|
|
ORD(glCullFace);
|
|
ORD(glDeleteBuffers);
|
|
ORD(glDeleteFramebuffers);
|
|
ORD(glDeleteProgram);
|
|
ORD(glDeleteRenderbuffers);
|
|
ORD(glDeleteShader);
|
|
ORD(glDeleteTextures);
|
|
ORD(glDepthFunc);
|
|
ORD(glDepthMask);
|
|
ORD(glDepthRangef);
|
|
ORD(glDetachShader);
|
|
ORD(glDisable);
|
|
ORD(glDisableVertexAttribArray);
|
|
ORD(glDrawArrays);
|
|
ORD(glDrawElements);
|
|
ORD(glEnable);
|
|
ORD(glEnableVertexAttribArray);
|
|
ORD(glFinish);
|
|
ORD(glFlush);
|
|
ORD(glFramebufferRenderbuffer);
|
|
ORD(glFramebufferTexture2D);
|
|
ORD(glFrontFace);
|
|
ORD(glGenBuffers);
|
|
ORD(glGenerateMipmap);
|
|
ORD(glGenFramebuffers);
|
|
ORD(glGenRenderbuffers);
|
|
ORD(glGenTextures);
|
|
ORD(glGetActiveAttrib);
|
|
ORD(glGetActiveUniform);
|
|
ORD(glGetAttachedShaders);
|
|
ORD(glGetAttribLocation);
|
|
ORD(glGetBooleanv);
|
|
ORD(glGetBufferParameteriv);
|
|
ORD(glGetError);
|
|
ORD(glGetFloatv);
|
|
ORD(glGetFramebufferAttachmentParameteriv);
|
|
ORD(glGetIntegerv);
|
|
ORD(glGetProgramiv);
|
|
ORD(glGetProgramInfoLog);
|
|
ORD(glGetRenderbufferParameteriv);
|
|
ORD(glGetShaderiv);
|
|
ORD(glGetShaderInfoLog);
|
|
ORD(glGetShaderPrecisionFormat);
|
|
ORD(glGetShaderSource);
|
|
ORD(glGetString);
|
|
ORD(glGetTexParameterfv);
|
|
ORD(glGetTexParameteriv);
|
|
ORD(glGetUniformfv);
|
|
ORD(glGetUniformiv);
|
|
ORD(glGetUniformLocation);
|
|
ORD(glGetVertexAttribfv);
|
|
ORD(glGetVertexAttribiv);
|
|
ORD(glGetVertexAttribPointerv);
|
|
ORD(glHint);
|
|
ORD(glIsBuffer);
|
|
ORD(glIsEnabled);
|
|
ORD(glIsFramebuffer);
|
|
ORD(glIsProgram);
|
|
ORD(glIsRenderbuffer);
|
|
ORD(glIsShader);
|
|
ORD(glIsTexture);
|
|
ORD(glLineWidth);
|
|
ORD(glLinkProgram);
|
|
ORD(glPixelStorei);
|
|
ORD(glPolygonOffset);
|
|
ORD(glReadPixels);
|
|
ORD(glReleaseShaderCompiler);
|
|
ORD(glRenderbufferStorage);
|
|
ORD(glSampleCoverage);
|
|
ORD(glScissor);
|
|
ORD(glShaderBinary);
|
|
ORD(glShaderSource);
|
|
ORD(glStencilFunc);
|
|
ORD(glStencilFuncSeparate);
|
|
ORD(glStencilMask);
|
|
ORD(glStencilMaskSeparate);
|
|
ORD(glStencilOp);
|
|
ORD(glStencilOpSeparate);
|
|
ORD(glTexImage2D);
|
|
ORD(glTexParameterf);
|
|
ORD(glTexParameterfv);
|
|
ORD(glTexParameteri);
|
|
ORD(glTexParameteriv);
|
|
ORD(glTexSubImage2D);
|
|
ORD(glUniform1f);
|
|
ORD(glUniform1fv);
|
|
ORD(glUniform1i);
|
|
ORD(glUniform1iv);
|
|
ORD(glUniform2f);
|
|
ORD(glUniform2fv);
|
|
ORD(glUniform2i);
|
|
ORD(glUniform2iv);
|
|
ORD(glUniform3f);
|
|
ORD(glUniform3fv);
|
|
ORD(glUniform3i);
|
|
ORD(glUniform3iv);
|
|
ORD(glUniform4f);
|
|
ORD(glUniform4fv);
|
|
ORD(glUniform4i);
|
|
ORD(glUniform4iv);
|
|
ORD(glUniformMatrix2fv);
|
|
ORD(glUniformMatrix3fv);
|
|
ORD(glUniformMatrix4fv);
|
|
ORD(glUseProgram);
|
|
ORD(glValidateProgram);
|
|
ORD(glVertexAttrib1f);
|
|
ORD(glVertexAttrib1fv);
|
|
ORD(glVertexAttrib2f);
|
|
ORD(glVertexAttrib2fv);
|
|
ORD(glVertexAttrib3f);
|
|
ORD(glVertexAttrib3fv);
|
|
ORD(glVertexAttrib4f);
|
|
ORD(glVertexAttrib4fv);
|
|
ORD(glVertexAttribPointer);
|
|
ORD(glViewport);
|
|
|
|
ORD(glBindFramebuffer);
|
|
ORD(glBindRenderbuffer);
|
|
#undef ORD
|
|
}
|
|
|
|
static void
|
|
_direct_scissor_off_api_get(Evas_GL_API *funcs)
|
|
{
|
|
|
|
#define ORD(f) EVAS_API_OVERRIDE(f, funcs,)
|
|
// For Direct Rendering
|
|
ORD(glClear);
|
|
ORD(glClearColor);
|
|
ORD(glDisable);
|
|
ORD(glEnable);
|
|
ORD(glGetIntegerv);
|
|
ORD(glReadPixels);
|
|
ORD(glScissor);
|
|
ORD(glViewport);
|
|
#undef ORD
|
|
}
|
|
|
|
|
|
static void
|
|
_debug_gles2_api_get(Evas_GL_API *funcs)
|
|
{
|
|
funcs->version = EVAS_GL_API_VERSION;
|
|
|
|
#define ORD(f) EVAS_API_OVERRIDE(f, funcs, _evgld_)
|
|
// GLES 2.0
|
|
ORD(glActiveTexture);
|
|
ORD(glAttachShader);
|
|
ORD(glBindAttribLocation);
|
|
ORD(glBindBuffer);
|
|
ORD(glBindTexture);
|
|
ORD(glBlendColor);
|
|
ORD(glBlendEquation);
|
|
ORD(glBlendEquationSeparate);
|
|
ORD(glBlendFunc);
|
|
ORD(glBlendFuncSeparate);
|
|
ORD(glBufferData);
|
|
ORD(glBufferSubData);
|
|
ORD(glCheckFramebufferStatus);
|
|
ORD(glClear);
|
|
ORD(glClearColor);
|
|
ORD(glClearDepthf);
|
|
ORD(glClearStencil);
|
|
ORD(glColorMask);
|
|
ORD(glCompileShader);
|
|
ORD(glCompressedTexImage2D);
|
|
ORD(glCompressedTexSubImage2D);
|
|
ORD(glCopyTexImage2D);
|
|
ORD(glCopyTexSubImage2D);
|
|
ORD(glCreateProgram);
|
|
ORD(glCreateShader);
|
|
ORD(glCullFace);
|
|
ORD(glDeleteBuffers);
|
|
ORD(glDeleteFramebuffers);
|
|
ORD(glDeleteProgram);
|
|
ORD(glDeleteRenderbuffers);
|
|
ORD(glDeleteShader);
|
|
ORD(glDeleteTextures);
|
|
ORD(glDepthFunc);
|
|
ORD(glDepthMask);
|
|
ORD(glDepthRangef);
|
|
ORD(glDetachShader);
|
|
ORD(glDisable);
|
|
ORD(glDisableVertexAttribArray);
|
|
ORD(glDrawArrays);
|
|
ORD(glDrawElements);
|
|
ORD(glEnable);
|
|
ORD(glEnableVertexAttribArray);
|
|
ORD(glFinish);
|
|
ORD(glFlush);
|
|
ORD(glFramebufferRenderbuffer);
|
|
ORD(glFramebufferTexture2D);
|
|
ORD(glFrontFace);
|
|
ORD(glGenBuffers);
|
|
ORD(glGenerateMipmap);
|
|
ORD(glGenFramebuffers);
|
|
ORD(glGenRenderbuffers);
|
|
ORD(glGenTextures);
|
|
ORD(glGetActiveAttrib);
|
|
ORD(glGetActiveUniform);
|
|
ORD(glGetAttachedShaders);
|
|
ORD(glGetAttribLocation);
|
|
ORD(glGetBooleanv);
|
|
ORD(glGetBufferParameteriv);
|
|
ORD(glGetError);
|
|
ORD(glGetFloatv);
|
|
ORD(glGetFramebufferAttachmentParameteriv);
|
|
ORD(glGetIntegerv);
|
|
ORD(glGetProgramiv);
|
|
ORD(glGetProgramInfoLog);
|
|
ORD(glGetRenderbufferParameteriv);
|
|
ORD(glGetShaderiv);
|
|
ORD(glGetShaderInfoLog);
|
|
ORD(glGetShaderPrecisionFormat);
|
|
ORD(glGetShaderSource);
|
|
ORD(glGetString);
|
|
ORD(glGetTexParameterfv);
|
|
ORD(glGetTexParameteriv);
|
|
ORD(glGetUniformfv);
|
|
ORD(glGetUniformiv);
|
|
ORD(glGetUniformLocation);
|
|
ORD(glGetVertexAttribfv);
|
|
ORD(glGetVertexAttribiv);
|
|
ORD(glGetVertexAttribPointerv);
|
|
ORD(glHint);
|
|
ORD(glIsBuffer);
|
|
ORD(glIsEnabled);
|
|
ORD(glIsFramebuffer);
|
|
ORD(glIsProgram);
|
|
ORD(glIsRenderbuffer);
|
|
ORD(glIsShader);
|
|
ORD(glIsTexture);
|
|
ORD(glLineWidth);
|
|
ORD(glLinkProgram);
|
|
ORD(glPixelStorei);
|
|
ORD(glPolygonOffset);
|
|
ORD(glReadPixels);
|
|
ORD(glReleaseShaderCompiler);
|
|
ORD(glRenderbufferStorage);
|
|
ORD(glSampleCoverage);
|
|
ORD(glScissor);
|
|
ORD(glShaderBinary);
|
|
ORD(glShaderSource);
|
|
ORD(glStencilFunc);
|
|
ORD(glStencilFuncSeparate);
|
|
ORD(glStencilMask);
|
|
ORD(glStencilMaskSeparate);
|
|
ORD(glStencilOp);
|
|
ORD(glStencilOpSeparate);
|
|
ORD(glTexImage2D);
|
|
ORD(glTexParameterf);
|
|
ORD(glTexParameterfv);
|
|
ORD(glTexParameteri);
|
|
ORD(glTexParameteriv);
|
|
ORD(glTexSubImage2D);
|
|
ORD(glUniform1f);
|
|
ORD(glUniform1fv);
|
|
ORD(glUniform1i);
|
|
ORD(glUniform1iv);
|
|
ORD(glUniform2f);
|
|
ORD(glUniform2fv);
|
|
ORD(glUniform2i);
|
|
ORD(glUniform2iv);
|
|
ORD(glUniform3f);
|
|
ORD(glUniform3fv);
|
|
ORD(glUniform3i);
|
|
ORD(glUniform3iv);
|
|
ORD(glUniform4f);
|
|
ORD(glUniform4fv);
|
|
ORD(glUniform4i);
|
|
ORD(glUniform4iv);
|
|
ORD(glUniformMatrix2fv);
|
|
ORD(glUniformMatrix3fv);
|
|
ORD(glUniformMatrix4fv);
|
|
ORD(glUseProgram);
|
|
ORD(glValidateProgram);
|
|
ORD(glVertexAttrib1f);
|
|
ORD(glVertexAttrib1fv);
|
|
ORD(glVertexAttrib2f);
|
|
ORD(glVertexAttrib2fv);
|
|
ORD(glVertexAttrib3f);
|
|
ORD(glVertexAttrib3fv);
|
|
ORD(glVertexAttrib4f);
|
|
ORD(glVertexAttrib4fv);
|
|
ORD(glVertexAttribPointer);
|
|
ORD(glViewport);
|
|
|
|
ORD(glBindFramebuffer);
|
|
ORD(glBindRenderbuffer);
|
|
#undef ORD
|
|
}
|
|
|
|
void
|
|
_evgl_api_gles2_get(Evas_GL_API *funcs, Eina_Bool debug)
|
|
{
|
|
if (debug)
|
|
_debug_gles2_api_get(funcs);
|
|
else
|
|
_normal_gles2_api_get(funcs);
|
|
|
|
if (evgl_engine->direct_scissor_off)
|
|
_direct_scissor_off_api_get(funcs);
|
|
}
|
|
|
|
static void
|
|
_normal_gles3_api_get(Evas_GL_API *funcs, int minor_version)
|
|
{
|
|
if (!funcs) return;
|
|
funcs->version = EVAS_GL_API_VERSION;
|
|
|
|
#define ORD(f) EVAS_API_OVERRIDE(f, funcs, evgl_)
|
|
// GLES 3.0 APIs that are same as GLES 2.0
|
|
ORD(glActiveTexture);
|
|
ORD(glAttachShader);
|
|
ORD(glBindAttribLocation);
|
|
ORD(glBindBuffer);
|
|
ORD(glBindTexture);
|
|
ORD(glBlendColor);
|
|
ORD(glBlendEquation);
|
|
ORD(glBlendEquationSeparate);
|
|
ORD(glBlendFunc);
|
|
ORD(glBlendFuncSeparate);
|
|
ORD(glBufferData);
|
|
ORD(glBufferSubData);
|
|
ORD(glCheckFramebufferStatus);
|
|
ORD(glClear);
|
|
ORD(glClearColor);
|
|
ORD(glClearDepthf);
|
|
ORD(glClearStencil);
|
|
ORD(glColorMask);
|
|
ORD(glCompileShader);
|
|
ORD(glCompressedTexImage2D);
|
|
ORD(glCompressedTexSubImage2D);
|
|
ORD(glCopyTexImage2D);
|
|
ORD(glCopyTexSubImage2D);
|
|
ORD(glCreateProgram);
|
|
ORD(glCreateShader);
|
|
ORD(glCullFace);
|
|
ORD(glDeleteBuffers);
|
|
ORD(glDeleteFramebuffers);
|
|
ORD(glDeleteProgram);
|
|
ORD(glDeleteRenderbuffers);
|
|
ORD(glDeleteShader);
|
|
ORD(glDeleteTextures);
|
|
ORD(glDepthFunc);
|
|
ORD(glDepthMask);
|
|
ORD(glDepthRangef);
|
|
ORD(glDetachShader);
|
|
ORD(glDisable);
|
|
ORD(glDisableVertexAttribArray);
|
|
ORD(glDrawArrays);
|
|
ORD(glDrawElements);
|
|
ORD(glEnable);
|
|
ORD(glEnableVertexAttribArray);
|
|
ORD(glFinish);
|
|
ORD(glFlush);
|
|
ORD(glFramebufferRenderbuffer);
|
|
ORD(glFramebufferTexture2D);
|
|
ORD(glFrontFace);
|
|
ORD(glGenBuffers);
|
|
ORD(glGenerateMipmap);
|
|
ORD(glGenFramebuffers);
|
|
ORD(glGenRenderbuffers);
|
|
ORD(glGenTextures);
|
|
ORD(glGetActiveAttrib);
|
|
ORD(glGetActiveUniform);
|
|
ORD(glGetAttachedShaders);
|
|
ORD(glGetAttribLocation);
|
|
ORD(glGetBooleanv);
|
|
ORD(glGetBufferParameteriv);
|
|
ORD(glGetError);
|
|
ORD(glGetFloatv);
|
|
ORD(glGetFramebufferAttachmentParameteriv);
|
|
ORD(glGetIntegerv);
|
|
ORD(glGetProgramiv);
|
|
ORD(glGetProgramInfoLog);
|
|
ORD(glGetRenderbufferParameteriv);
|
|
ORD(glGetShaderiv);
|
|
ORD(glGetShaderInfoLog);
|
|
ORD(glGetShaderPrecisionFormat);
|
|
ORD(glGetShaderSource);
|
|
ORD(glGetString);
|
|
ORD(glGetTexParameterfv);
|
|
ORD(glGetTexParameteriv);
|
|
ORD(glGetUniformfv);
|
|
ORD(glGetUniformiv);
|
|
ORD(glGetUniformLocation);
|
|
ORD(glGetVertexAttribfv);
|
|
ORD(glGetVertexAttribiv);
|
|
ORD(glGetVertexAttribPointerv);
|
|
ORD(glHint);
|
|
ORD(glIsBuffer);
|
|
ORD(glIsEnabled);
|
|
ORD(glIsFramebuffer);
|
|
ORD(glIsProgram);
|
|
ORD(glIsRenderbuffer);
|
|
ORD(glIsShader);
|
|
ORD(glIsTexture);
|
|
ORD(glLineWidth);
|
|
ORD(glLinkProgram);
|
|
ORD(glPixelStorei);
|
|
ORD(glPolygonOffset);
|
|
ORD(glReadPixels);
|
|
ORD(glReleaseShaderCompiler);
|
|
ORD(glRenderbufferStorage);
|
|
ORD(glSampleCoverage);
|
|
ORD(glScissor);
|
|
ORD(glShaderBinary);
|
|
ORD(glShaderSource);
|
|
ORD(glStencilFunc);
|
|
ORD(glStencilFuncSeparate);
|
|
ORD(glStencilMask);
|
|
ORD(glStencilMaskSeparate);
|
|
ORD(glStencilOp);
|
|
ORD(glStencilOpSeparate);
|
|
ORD(glTexImage2D);
|
|
ORD(glTexParameterf);
|
|
ORD(glTexParameterfv);
|
|
ORD(glTexParameteri);
|
|
ORD(glTexParameteriv);
|
|
ORD(glTexSubImage2D);
|
|
ORD(glUniform1f);
|
|
ORD(glUniform1fv);
|
|
ORD(glUniform1i);
|
|
ORD(glUniform1iv);
|
|
ORD(glUniform2f);
|
|
ORD(glUniform2fv);
|
|
ORD(glUniform2i);
|
|
ORD(glUniform2iv);
|
|
ORD(glUniform3f);
|
|
ORD(glUniform3fv);
|
|
ORD(glUniform3i);
|
|
ORD(glUniform3iv);
|
|
ORD(glUniform4f);
|
|
ORD(glUniform4fv);
|
|
ORD(glUniform4i);
|
|
ORD(glUniform4iv);
|
|
ORD(glUniformMatrix2fv);
|
|
ORD(glUniformMatrix3fv);
|
|
ORD(glUniformMatrix4fv);
|
|
ORD(glUseProgram);
|
|
ORD(glValidateProgram);
|
|
ORD(glVertexAttrib1f);
|
|
ORD(glVertexAttrib1fv);
|
|
ORD(glVertexAttrib2f);
|
|
ORD(glVertexAttrib2fv);
|
|
ORD(glVertexAttrib3f);
|
|
ORD(glVertexAttrib3fv);
|
|
ORD(glVertexAttrib4f);
|
|
ORD(glVertexAttrib4fv);
|
|
ORD(glVertexAttribPointer);
|
|
ORD(glViewport);
|
|
|
|
ORD(glBindFramebuffer);
|
|
ORD(glBindRenderbuffer);
|
|
#undef ORD
|
|
|
|
// GLES 3.0 NEW APIs
|
|
#define ORD(name) EVAS_API_OVERRIDE(name, funcs, evgl_gles3_)
|
|
ORD(glBeginQuery);
|
|
ORD(glBeginTransformFeedback);
|
|
ORD(glBindBufferBase);
|
|
ORD(glBindBufferRange);
|
|
ORD(glBindSampler);
|
|
ORD(glBindTransformFeedback);
|
|
ORD(glBindVertexArray);
|
|
ORD(glBlitFramebuffer);
|
|
ORD(glClearBufferfi);
|
|
ORD(glClearBufferfv);
|
|
ORD(glClearBufferiv);
|
|
ORD(glClearBufferuiv);
|
|
ORD(glClientWaitSync);
|
|
ORD(glCompressedTexImage3D);
|
|
ORD(glCompressedTexSubImage3D);
|
|
ORD(glCopyBufferSubData);
|
|
ORD(glCopyTexSubImage3D);
|
|
ORD(glDeleteQueries);
|
|
ORD(glDeleteSamplers);
|
|
ORD(glDeleteSync);
|
|
ORD(glDeleteTransformFeedbacks);
|
|
ORD(glDeleteVertexArrays);
|
|
ORD(glDrawArraysInstanced);
|
|
ORD(glDrawBuffers);
|
|
ORD(glDrawElementsInstanced);
|
|
ORD(glDrawRangeElements);
|
|
ORD(glEndQuery);
|
|
ORD(glEndTransformFeedback);
|
|
ORD(glFenceSync);
|
|
ORD(glFlushMappedBufferRange);
|
|
ORD(glFramebufferTextureLayer);
|
|
ORD(glGenQueries);
|
|
ORD(glGenSamplers);
|
|
ORD(glGenTransformFeedbacks);
|
|
ORD(glGenVertexArrays);
|
|
ORD(glGetActiveUniformBlockiv);
|
|
ORD(glGetActiveUniformBlockName);
|
|
ORD(glGetActiveUniformsiv);
|
|
ORD(glGetBufferParameteri64v);
|
|
ORD(glGetBufferPointerv);
|
|
ORD(glGetFragDataLocation);
|
|
ORD(glGetInteger64i_v);
|
|
ORD(glGetInteger64v);
|
|
ORD(glGetIntegeri_v);
|
|
ORD(glGetInternalformativ);
|
|
ORD(glGetProgramBinary);
|
|
ORD(glGetQueryiv);
|
|
ORD(glGetQueryObjectuiv);
|
|
ORD(glGetSamplerParameterfv);
|
|
ORD(glGetSamplerParameteriv);
|
|
ORD(glGetStringi);
|
|
ORD(glGetSynciv);
|
|
ORD(glGetTransformFeedbackVarying);
|
|
ORD(glGetUniformBlockIndex);
|
|
ORD(glGetUniformIndices);
|
|
ORD(glGetUniformuiv);
|
|
ORD(glGetVertexAttribIiv);
|
|
ORD(glGetVertexAttribIuiv);
|
|
ORD(glInvalidateFramebuffer);
|
|
ORD(glInvalidateSubFramebuffer);
|
|
ORD(glIsQuery);
|
|
ORD(glIsSampler);
|
|
ORD(glIsSync);
|
|
ORD(glIsTransformFeedback);
|
|
ORD(glIsVertexArray);
|
|
ORD(glMapBufferRange);
|
|
ORD(glPauseTransformFeedback);
|
|
ORD(glProgramBinary);
|
|
ORD(glProgramParameteri);
|
|
ORD(glReadBuffer);
|
|
ORD(glRenderbufferStorageMultisample);
|
|
ORD(glResumeTransformFeedback);
|
|
ORD(glSamplerParameterf);
|
|
ORD(glSamplerParameterfv);
|
|
ORD(glSamplerParameteri);
|
|
ORD(glSamplerParameteriv);
|
|
ORD(glTexImage3D);
|
|
ORD(glTexStorage2D);
|
|
ORD(glTexStorage3D);
|
|
ORD(glTexSubImage3D);
|
|
ORD(glTransformFeedbackVaryings);
|
|
ORD(glUniform1ui);
|
|
ORD(glUniform1uiv);
|
|
ORD(glUniform2ui);
|
|
ORD(glUniform2uiv);
|
|
ORD(glUniform3ui);
|
|
ORD(glUniform3uiv);
|
|
ORD(glUniform4ui);
|
|
ORD(glUniform4uiv);
|
|
ORD(glUniformBlockBinding);
|
|
ORD(glUniformMatrix2x3fv);
|
|
ORD(glUniformMatrix3x2fv);
|
|
ORD(glUniformMatrix2x4fv);
|
|
ORD(glUniformMatrix4x2fv);
|
|
ORD(glUniformMatrix3x4fv);
|
|
ORD(glUniformMatrix4x3fv);
|
|
ORD(glUnmapBuffer);
|
|
ORD(glVertexAttribDivisor);
|
|
ORD(glVertexAttribI4i);
|
|
ORD(glVertexAttribI4iv);
|
|
ORD(glVertexAttribI4ui);
|
|
ORD(glVertexAttribI4uiv);
|
|
ORD(glVertexAttribIPointer);
|
|
ORD(glWaitSync);
|
|
|
|
if (minor_version > 0)
|
|
{
|
|
//GLES 3.1
|
|
ORD(glDispatchCompute);
|
|
ORD(glDispatchComputeIndirect);
|
|
ORD(glDrawArraysIndirect);
|
|
ORD(glDrawElementsIndirect);
|
|
ORD(glFramebufferParameteri);
|
|
ORD(glGetFramebufferParameteriv);
|
|
ORD(glGetProgramInterfaceiv);
|
|
ORD(glGetProgramResourceIndex);
|
|
ORD(glGetProgramResourceName);
|
|
ORD(glGetProgramResourceiv);
|
|
ORD(glGetProgramResourceLocation);
|
|
ORD(glUseProgramStages);
|
|
ORD(glActiveShaderProgram);
|
|
ORD(glCreateShaderProgramv);
|
|
ORD(glBindProgramPipeline);
|
|
ORD(glDeleteProgramPipelines);
|
|
ORD(glGenProgramPipelines);
|
|
ORD(glIsProgramPipeline);
|
|
ORD(glGetProgramPipelineiv);
|
|
ORD(glProgramUniform1i);
|
|
ORD(glProgramUniform2i);
|
|
ORD(glProgramUniform3i);
|
|
ORD(glProgramUniform4i);
|
|
ORD(glProgramUniform1ui);
|
|
ORD(glProgramUniform2ui);
|
|
ORD(glProgramUniform3ui);
|
|
ORD(glProgramUniform4ui);
|
|
ORD(glProgramUniform1f);
|
|
ORD(glProgramUniform2f);
|
|
ORD(glProgramUniform3f);
|
|
ORD(glProgramUniform4f);
|
|
ORD(glProgramUniform1iv);
|
|
ORD(glProgramUniform2iv);
|
|
ORD(glProgramUniform3iv);
|
|
ORD(glProgramUniform4iv);
|
|
ORD(glProgramUniform1uiv);
|
|
ORD(glProgramUniform2uiv);
|
|
ORD(glProgramUniform3uiv);
|
|
ORD(glProgramUniform4uiv);
|
|
ORD(glProgramUniform1fv);
|
|
ORD(glProgramUniform2fv);
|
|
ORD(glProgramUniform3fv);
|
|
ORD(glProgramUniform4fv);
|
|
ORD(glProgramUniformMatrix2fv);
|
|
ORD(glProgramUniformMatrix3fv);
|
|
ORD(glProgramUniformMatrix4fv);
|
|
ORD(glProgramUniformMatrix2x3fv);
|
|
ORD(glProgramUniformMatrix3x2fv);
|
|
ORD(glProgramUniformMatrix2x4fv);
|
|
ORD(glProgramUniformMatrix4x2fv);
|
|
ORD(glProgramUniformMatrix3x4fv);
|
|
ORD(glProgramUniformMatrix4x3fv);
|
|
ORD(glValidateProgramPipeline);
|
|
ORD(glGetProgramPipelineInfoLog);
|
|
ORD(glBindImageTexture);
|
|
ORD(glGetBooleani_v);
|
|
ORD(glMemoryBarrier);
|
|
ORD(glMemoryBarrierByRegion);
|
|
ORD(glTexStorage2DMultisample);
|
|
ORD(glGetMultisamplefv);
|
|
ORD(glSampleMaski);
|
|
ORD(glGetTexLevelParameteriv);
|
|
ORD(glGetTexLevelParameterfv);
|
|
ORD(glBindVertexBuffer);
|
|
ORD(glVertexAttribFormat);
|
|
ORD(glVertexAttribIFormat);
|
|
ORD(glVertexAttribBinding);
|
|
ORD(glVertexBindingDivisor);
|
|
}
|
|
|
|
#undef ORD
|
|
}
|
|
|
|
static void
|
|
_debug_gles3_api_get(Evas_GL_API *funcs, int minor_version)
|
|
{
|
|
if (!funcs) return;
|
|
funcs->version = EVAS_GL_API_VERSION;
|
|
|
|
#define ORD(f) EVAS_API_OVERRIDE(f, funcs, _evgld_)
|
|
// GLES 3.0 APIs that are same as GLES 2.0
|
|
ORD(glActiveTexture);
|
|
ORD(glAttachShader);
|
|
ORD(glBindAttribLocation);
|
|
ORD(glBindBuffer);
|
|
ORD(glBindTexture);
|
|
ORD(glBlendColor);
|
|
ORD(glBlendEquation);
|
|
ORD(glBlendEquationSeparate);
|
|
ORD(glBlendFunc);
|
|
ORD(glBlendFuncSeparate);
|
|
ORD(glBufferData);
|
|
ORD(glBufferSubData);
|
|
ORD(glCheckFramebufferStatus);
|
|
ORD(glClear);
|
|
ORD(glClearColor);
|
|
ORD(glClearDepthf);
|
|
ORD(glClearStencil);
|
|
ORD(glColorMask);
|
|
ORD(glCompileShader);
|
|
ORD(glCompressedTexImage2D);
|
|
ORD(glCompressedTexSubImage2D);
|
|
ORD(glCopyTexImage2D);
|
|
ORD(glCopyTexSubImage2D);
|
|
ORD(glCreateProgram);
|
|
ORD(glCreateShader);
|
|
ORD(glCullFace);
|
|
ORD(glDeleteBuffers);
|
|
ORD(glDeleteFramebuffers);
|
|
ORD(glDeleteProgram);
|
|
ORD(glDeleteRenderbuffers);
|
|
ORD(glDeleteShader);
|
|
ORD(glDeleteTextures);
|
|
ORD(glDepthFunc);
|
|
ORD(glDepthMask);
|
|
ORD(glDepthRangef);
|
|
ORD(glDetachShader);
|
|
ORD(glDisable);
|
|
ORD(glDisableVertexAttribArray);
|
|
ORD(glDrawArrays);
|
|
ORD(glDrawElements);
|
|
ORD(glEnable);
|
|
ORD(glEnableVertexAttribArray);
|
|
ORD(glFinish);
|
|
ORD(glFlush);
|
|
ORD(glFramebufferRenderbuffer);
|
|
ORD(glFramebufferTexture2D);
|
|
ORD(glFrontFace);
|
|
ORD(glGenBuffers);
|
|
ORD(glGenerateMipmap);
|
|
ORD(glGenFramebuffers);
|
|
ORD(glGenRenderbuffers);
|
|
ORD(glGenTextures);
|
|
ORD(glGetActiveAttrib);
|
|
ORD(glGetActiveUniform);
|
|
ORD(glGetAttachedShaders);
|
|
ORD(glGetAttribLocation);
|
|
ORD(glGetBooleanv);
|
|
ORD(glGetBufferParameteriv);
|
|
ORD(glGetError);
|
|
ORD(glGetFloatv);
|
|
ORD(glGetFramebufferAttachmentParameteriv);
|
|
ORD(glGetIntegerv);
|
|
ORD(glGetProgramiv);
|
|
ORD(glGetProgramInfoLog);
|
|
ORD(glGetRenderbufferParameteriv);
|
|
ORD(glGetShaderiv);
|
|
ORD(glGetShaderInfoLog);
|
|
ORD(glGetShaderPrecisionFormat);
|
|
ORD(glGetShaderSource);
|
|
ORD(glGetString);
|
|
ORD(glGetTexParameterfv);
|
|
ORD(glGetTexParameteriv);
|
|
ORD(glGetUniformfv);
|
|
ORD(glGetUniformiv);
|
|
ORD(glGetUniformLocation);
|
|
ORD(glGetVertexAttribfv);
|
|
ORD(glGetVertexAttribiv);
|
|
ORD(glGetVertexAttribPointerv);
|
|
ORD(glHint);
|
|
ORD(glIsBuffer);
|
|
ORD(glIsEnabled);
|
|
ORD(glIsFramebuffer);
|
|
ORD(glIsProgram);
|
|
ORD(glIsRenderbuffer);
|
|
ORD(glIsShader);
|
|
ORD(glIsTexture);
|
|
ORD(glLineWidth);
|
|
ORD(glLinkProgram);
|
|
ORD(glPixelStorei);
|
|
ORD(glPolygonOffset);
|
|
ORD(glReadPixels);
|
|
ORD(glReleaseShaderCompiler);
|
|
ORD(glRenderbufferStorage);
|
|
ORD(glSampleCoverage);
|
|
ORD(glScissor);
|
|
ORD(glShaderBinary);
|
|
ORD(glShaderSource);
|
|
ORD(glStencilFunc);
|
|
ORD(glStencilFuncSeparate);
|
|
ORD(glStencilMask);
|
|
ORD(glStencilMaskSeparate);
|
|
ORD(glStencilOp);
|
|
ORD(glStencilOpSeparate);
|
|
ORD(glTexImage2D);
|
|
ORD(glTexParameterf);
|
|
ORD(glTexParameterfv);
|
|
ORD(glTexParameteri);
|
|
ORD(glTexParameteriv);
|
|
ORD(glTexSubImage2D);
|
|
ORD(glUniform1f);
|
|
ORD(glUniform1fv);
|
|
ORD(glUniform1i);
|
|
ORD(glUniform1iv);
|
|
ORD(glUniform2f);
|
|
ORD(glUniform2fv);
|
|
ORD(glUniform2i);
|
|
ORD(glUniform2iv);
|
|
ORD(glUniform3f);
|
|
ORD(glUniform3fv);
|
|
ORD(glUniform3i);
|
|
ORD(glUniform3iv);
|
|
ORD(glUniform4f);
|
|
ORD(glUniform4fv);
|
|
ORD(glUniform4i);
|
|
ORD(glUniform4iv);
|
|
ORD(glUniformMatrix2fv);
|
|
ORD(glUniformMatrix3fv);
|
|
ORD(glUniformMatrix4fv);
|
|
ORD(glUseProgram);
|
|
ORD(glValidateProgram);
|
|
ORD(glVertexAttrib1f);
|
|
ORD(glVertexAttrib1fv);
|
|
ORD(glVertexAttrib2f);
|
|
ORD(glVertexAttrib2fv);
|
|
ORD(glVertexAttrib3f);
|
|
ORD(glVertexAttrib3fv);
|
|
ORD(glVertexAttrib4f);
|
|
ORD(glVertexAttrib4fv);
|
|
ORD(glVertexAttribPointer);
|
|
ORD(glViewport);
|
|
|
|
ORD(glBindFramebuffer);
|
|
ORD(glBindRenderbuffer);
|
|
|
|
// GLES 3.0 new APIs
|
|
ORD(glBeginQuery);
|
|
ORD(glBeginTransformFeedback);
|
|
ORD(glBindBufferBase);
|
|
ORD(glBindBufferRange);
|
|
ORD(glBindSampler);
|
|
ORD(glBindTransformFeedback);
|
|
ORD(glBindVertexArray);
|
|
ORD(glBlitFramebuffer);
|
|
ORD(glClearBufferfi);
|
|
ORD(glClearBufferfv);
|
|
ORD(glClearBufferiv);
|
|
ORD(glClearBufferuiv);
|
|
ORD(glClientWaitSync);
|
|
ORD(glCompressedTexImage3D);
|
|
ORD(glCompressedTexSubImage3D);
|
|
ORD(glCopyBufferSubData);
|
|
ORD(glCopyTexSubImage3D);
|
|
ORD(glDeleteQueries);
|
|
ORD(glDeleteSamplers);
|
|
ORD(glDeleteSync);
|
|
ORD(glDeleteTransformFeedbacks);
|
|
ORD(glDeleteVertexArrays);
|
|
ORD(glDrawArraysInstanced);
|
|
ORD(glDrawBuffers);
|
|
ORD(glDrawElementsInstanced);
|
|
ORD(glDrawRangeElements);
|
|
ORD(glEndQuery);
|
|
ORD(glEndTransformFeedback);
|
|
ORD(glFenceSync);
|
|
ORD(glFlushMappedBufferRange);
|
|
ORD(glFramebufferTextureLayer);
|
|
ORD(glGenQueries);
|
|
ORD(glGenSamplers);
|
|
ORD(glGenTransformFeedbacks);
|
|
ORD(glGenVertexArrays);
|
|
ORD(glGetActiveUniformBlockiv);
|
|
ORD(glGetActiveUniformBlockName);
|
|
ORD(glGetActiveUniformsiv);
|
|
ORD(glGetBufferParameteri64v);
|
|
ORD(glGetBufferPointerv);
|
|
ORD(glGetFragDataLocation);
|
|
ORD(glGetInteger64i_v);
|
|
ORD(glGetInteger64v);
|
|
ORD(glGetIntegeri_v);
|
|
ORD(glGetInternalformativ);
|
|
ORD(glGetProgramBinary);
|
|
ORD(glGetQueryiv);
|
|
ORD(glGetQueryObjectuiv);
|
|
ORD(glGetSamplerParameterfv);
|
|
ORD(glGetSamplerParameteriv);
|
|
ORD(glGetStringi);
|
|
ORD(glGetSynciv);
|
|
ORD(glGetTransformFeedbackVarying);
|
|
ORD(glGetUniformBlockIndex);
|
|
ORD(glGetUniformIndices);
|
|
ORD(glGetUniformuiv);
|
|
ORD(glGetVertexAttribIiv);
|
|
ORD(glGetVertexAttribIuiv);
|
|
ORD(glInvalidateFramebuffer);
|
|
ORD(glInvalidateSubFramebuffer);
|
|
ORD(glIsQuery);
|
|
ORD(glIsSampler);
|
|
ORD(glIsSync);
|
|
ORD(glIsTransformFeedback);
|
|
ORD(glIsVertexArray);
|
|
ORD(glMapBufferRange);
|
|
ORD(glPauseTransformFeedback);
|
|
ORD(glProgramBinary);
|
|
ORD(glProgramParameteri);
|
|
ORD(glReadBuffer);
|
|
ORD(glRenderbufferStorageMultisample);
|
|
ORD(glResumeTransformFeedback);
|
|
ORD(glSamplerParameterf);
|
|
ORD(glSamplerParameterfv);
|
|
ORD(glSamplerParameteri);
|
|
ORD(glSamplerParameteriv);
|
|
ORD(glTexImage3D);
|
|
ORD(glTexStorage2D);
|
|
ORD(glTexStorage3D);
|
|
ORD(glTexSubImage3D);
|
|
ORD(glTransformFeedbackVaryings);
|
|
ORD(glUniform1ui);
|
|
ORD(glUniform1uiv);
|
|
ORD(glUniform2ui);
|
|
ORD(glUniform2uiv);
|
|
ORD(glUniform3ui);
|
|
ORD(glUniform3uiv);
|
|
ORD(glUniform4ui);
|
|
ORD(glUniform4uiv);
|
|
ORD(glUniformBlockBinding);
|
|
ORD(glUniformMatrix2x3fv);
|
|
ORD(glUniformMatrix3x2fv);
|
|
ORD(glUniformMatrix2x4fv);
|
|
ORD(glUniformMatrix4x2fv);
|
|
ORD(glUniformMatrix3x4fv);
|
|
ORD(glUniformMatrix4x3fv);
|
|
ORD(glUnmapBuffer);
|
|
ORD(glVertexAttribDivisor);
|
|
ORD(glVertexAttribI4i);
|
|
ORD(glVertexAttribI4iv);
|
|
ORD(glVertexAttribI4ui);
|
|
ORD(glVertexAttribI4uiv);
|
|
ORD(glVertexAttribIPointer);
|
|
ORD(glWaitSync);
|
|
|
|
if (minor_version > 0)
|
|
{
|
|
//GLES 3.1
|
|
ORD(glDispatchCompute);
|
|
ORD(glDispatchComputeIndirect);
|
|
ORD(glDrawArraysIndirect);
|
|
ORD(glDrawElementsIndirect);
|
|
ORD(glFramebufferParameteri);
|
|
ORD(glGetFramebufferParameteriv);
|
|
ORD(glGetProgramInterfaceiv);
|
|
ORD(glGetProgramResourceIndex);
|
|
ORD(glGetProgramResourceName);
|
|
ORD(glGetProgramResourceiv);
|
|
ORD(glGetProgramResourceLocation);
|
|
ORD(glUseProgramStages);
|
|
ORD(glActiveShaderProgram);
|
|
ORD(glCreateShaderProgramv);
|
|
ORD(glBindProgramPipeline);
|
|
ORD(glDeleteProgramPipelines);
|
|
ORD(glGenProgramPipelines);
|
|
ORD(glIsProgramPipeline);
|
|
ORD(glGetProgramPipelineiv);
|
|
ORD(glProgramUniform1i);
|
|
ORD(glProgramUniform2i);
|
|
ORD(glProgramUniform3i);
|
|
ORD(glProgramUniform4i);
|
|
ORD(glProgramUniform1ui);
|
|
ORD(glProgramUniform2ui);
|
|
ORD(glProgramUniform3ui);
|
|
ORD(glProgramUniform4ui);
|
|
ORD(glProgramUniform1f);
|
|
ORD(glProgramUniform2f);
|
|
ORD(glProgramUniform3f);
|
|
ORD(glProgramUniform4f);
|
|
ORD(glProgramUniform1iv);
|
|
ORD(glProgramUniform2iv);
|
|
ORD(glProgramUniform3iv);
|
|
ORD(glProgramUniform4iv);
|
|
ORD(glProgramUniform1uiv);
|
|
ORD(glProgramUniform2uiv);
|
|
ORD(glProgramUniform3uiv);
|
|
ORD(glProgramUniform4uiv);
|
|
ORD(glProgramUniform1fv);
|
|
ORD(glProgramUniform2fv);
|
|
ORD(glProgramUniform3fv);
|
|
ORD(glProgramUniform4fv);
|
|
ORD(glProgramUniformMatrix2fv);
|
|
ORD(glProgramUniformMatrix3fv);
|
|
ORD(glProgramUniformMatrix4fv);
|
|
ORD(glProgramUniformMatrix2x3fv);
|
|
ORD(glProgramUniformMatrix3x2fv);
|
|
ORD(glProgramUniformMatrix2x4fv);
|
|
ORD(glProgramUniformMatrix4x2fv);
|
|
ORD(glProgramUniformMatrix3x4fv);
|
|
ORD(glProgramUniformMatrix4x3fv);
|
|
ORD(glValidateProgramPipeline);
|
|
ORD(glGetProgramPipelineInfoLog);
|
|
ORD(glBindImageTexture);
|
|
ORD(glGetBooleani_v);
|
|
ORD(glMemoryBarrier);
|
|
ORD(glMemoryBarrierByRegion);
|
|
ORD(glTexStorage2DMultisample);
|
|
ORD(glGetMultisamplefv);
|
|
ORD(glSampleMaski);
|
|
ORD(glGetTexLevelParameteriv);
|
|
ORD(glGetTexLevelParameterfv);
|
|
ORD(glBindVertexBuffer);
|
|
ORD(glVertexAttribFormat);
|
|
ORD(glVertexAttribIFormat);
|
|
ORD(glVertexAttribBinding);
|
|
ORD(glVertexBindingDivisor);
|
|
}
|
|
|
|
#undef ORD
|
|
}
|
|
|
|
|
|
static Eina_Bool
|
|
_evgl_load_gles3_apis(void *dl_handle, Evas_GL_API *funcs, int minor_version,
|
|
void *(*get_proc_address)(const char *))
|
|
{
|
|
if (!dl_handle) return EINA_FALSE;
|
|
Eina_Bool ret_value = EINA_FALSE;
|
|
|
|
#define ORD(name) do { \
|
|
funcs->name = dlsym(dl_handle, #name); \
|
|
if (!funcs->name && get_proc_address) \
|
|
funcs->name = get_proc_address(#name); \
|
|
if (!funcs->name) { \
|
|
WRN("%s symbol not found", #name); \
|
|
return ret_value; \
|
|
} } while (0)
|
|
|
|
// Used to update extensions
|
|
ORD(glGetString);
|
|
|
|
// GLES 3.0 new APIs
|
|
ORD(glBeginQuery);
|
|
ORD(glBeginTransformFeedback);
|
|
ORD(glBindBufferBase);
|
|
ORD(glBindBufferRange);
|
|
ORD(glBindSampler);
|
|
ORD(glBindTransformFeedback);
|
|
ORD(glBindVertexArray);
|
|
ORD(glBlitFramebuffer);
|
|
ORD(glClearBufferfi);
|
|
ORD(glClearBufferfv);
|
|
ORD(glClearBufferiv);
|
|
ORD(glClearBufferuiv);
|
|
ORD(glClientWaitSync);
|
|
ORD(glCompressedTexImage3D);
|
|
ORD(glCompressedTexSubImage3D);
|
|
ORD(glCopyBufferSubData);
|
|
ORD(glCopyTexSubImage3D);
|
|
ORD(glDeleteQueries);
|
|
ORD(glDeleteSamplers);
|
|
ORD(glDeleteSync);
|
|
ORD(glDeleteTransformFeedbacks);
|
|
ORD(glDeleteVertexArrays);
|
|
ORD(glDrawArraysInstanced);
|
|
ORD(glDrawBuffers);
|
|
ORD(glDrawElementsInstanced);
|
|
ORD(glDrawRangeElements);
|
|
ORD(glEndQuery);
|
|
ORD(glEndTransformFeedback);
|
|
ORD(glFenceSync);
|
|
ORD(glFlushMappedBufferRange);
|
|
ORD(glFramebufferTextureLayer);
|
|
ORD(glGenQueries);
|
|
ORD(glGenSamplers);
|
|
ORD(glGenTransformFeedbacks);
|
|
ORD(glGenVertexArrays);
|
|
ORD(glGetActiveUniformBlockiv);
|
|
ORD(glGetActiveUniformBlockName);
|
|
ORD(glGetActiveUniformsiv);
|
|
ORD(glGetBufferParameteri64v);
|
|
ORD(glGetBufferPointerv);
|
|
ORD(glGetFragDataLocation);
|
|
ORD(glGetInteger64i_v);
|
|
ORD(glGetInteger64v);
|
|
ORD(glGetIntegeri_v);
|
|
ORD(glGetInternalformativ);
|
|
ORD(glGetProgramBinary);
|
|
ORD(glGetQueryiv);
|
|
ORD(glGetQueryObjectuiv);
|
|
ORD(glGetSamplerParameterfv);
|
|
ORD(glGetSamplerParameteriv);
|
|
ORD(glGetStringi);
|
|
ORD(glGetSynciv);
|
|
ORD(glGetTransformFeedbackVarying);
|
|
ORD(glGetUniformBlockIndex);
|
|
ORD(glGetUniformIndices);
|
|
ORD(glGetUniformuiv);
|
|
ORD(glGetVertexAttribIiv);
|
|
ORD(glGetVertexAttribIuiv);
|
|
ORD(glInvalidateFramebuffer);
|
|
ORD(glInvalidateSubFramebuffer);
|
|
ORD(glIsQuery);
|
|
ORD(glIsSampler);
|
|
ORD(glIsSync);
|
|
ORD(glIsTransformFeedback);
|
|
ORD(glIsVertexArray);
|
|
ORD(glMapBufferRange);
|
|
ORD(glPauseTransformFeedback);
|
|
ORD(glProgramBinary);
|
|
ORD(glProgramParameteri);
|
|
ORD(glReadBuffer);
|
|
ORD(glRenderbufferStorageMultisample);
|
|
ORD(glResumeTransformFeedback);
|
|
ORD(glSamplerParameterf);
|
|
ORD(glSamplerParameterfv);
|
|
ORD(glSamplerParameteri);
|
|
ORD(glSamplerParameteriv);
|
|
ORD(glTexImage3D);
|
|
ORD(glTexStorage2D);
|
|
ORD(glTexStorage3D);
|
|
ORD(glTexSubImage3D);
|
|
ORD(glTransformFeedbackVaryings);
|
|
ORD(glUniform1ui);
|
|
ORD(glUniform1uiv);
|
|
ORD(glUniform2ui);
|
|
ORD(glUniform2uiv);
|
|
ORD(glUniform3ui);
|
|
ORD(glUniform3uiv);
|
|
ORD(glUniform4ui);
|
|
ORD(glUniform4uiv);
|
|
ORD(glUniformBlockBinding);
|
|
ORD(glUniformMatrix2x3fv);
|
|
ORD(glUniformMatrix3x2fv);
|
|
ORD(glUniformMatrix2x4fv);
|
|
ORD(glUniformMatrix4x2fv);
|
|
ORD(glUniformMatrix3x4fv);
|
|
ORD(glUniformMatrix4x3fv);
|
|
ORD(glUnmapBuffer);
|
|
ORD(glVertexAttribDivisor);
|
|
ORD(glVertexAttribI4i);
|
|
ORD(glVertexAttribI4iv);
|
|
ORD(glVertexAttribI4ui);
|
|
ORD(glVertexAttribI4uiv);
|
|
ORD(glVertexAttribIPointer);
|
|
ORD(glWaitSync);
|
|
|
|
if (minor_version > 0)
|
|
{
|
|
// OpenGL ES 3.0 is supported, return true even if 3.1 isn't there
|
|
ret_value = EINA_TRUE;
|
|
|
|
// OpenGL ES 3.1
|
|
ORD(glDispatchCompute);
|
|
ORD(glDispatchComputeIndirect);
|
|
ORD(glDrawArraysIndirect);
|
|
ORD(glDrawElementsIndirect);
|
|
ORD(glFramebufferParameteri);
|
|
ORD(glGetFramebufferParameteriv);
|
|
ORD(glGetProgramInterfaceiv);
|
|
ORD(glGetProgramResourceIndex);
|
|
ORD(glGetProgramResourceName);
|
|
ORD(glGetProgramResourceiv);
|
|
ORD(glGetProgramResourceLocation);
|
|
ORD(glUseProgramStages);
|
|
ORD(glActiveShaderProgram);
|
|
ORD(glCreateShaderProgramv);
|
|
ORD(glBindProgramPipeline);
|
|
ORD(glDeleteProgramPipelines);
|
|
ORD(glGenProgramPipelines);
|
|
ORD(glIsProgramPipeline);
|
|
ORD(glGetProgramPipelineiv);
|
|
ORD(glProgramUniform1i);
|
|
ORD(glProgramUniform2i);
|
|
ORD(glProgramUniform3i);
|
|
ORD(glProgramUniform4i);
|
|
ORD(glProgramUniform1ui);
|
|
ORD(glProgramUniform2ui);
|
|
ORD(glProgramUniform3ui);
|
|
ORD(glProgramUniform4ui);
|
|
ORD(glProgramUniform1f);
|
|
ORD(glProgramUniform2f);
|
|
ORD(glProgramUniform3f);
|
|
ORD(glProgramUniform4f);
|
|
ORD(glProgramUniform1iv);
|
|
ORD(glProgramUniform2iv);
|
|
ORD(glProgramUniform3iv);
|
|
ORD(glProgramUniform4iv);
|
|
ORD(glProgramUniform1uiv);
|
|
ORD(glProgramUniform2uiv);
|
|
ORD(glProgramUniform3uiv);
|
|
ORD(glProgramUniform4uiv);
|
|
ORD(glProgramUniform1fv);
|
|
ORD(glProgramUniform2fv);
|
|
ORD(glProgramUniform3fv);
|
|
ORD(glProgramUniform4fv);
|
|
ORD(glProgramUniformMatrix2fv);
|
|
ORD(glProgramUniformMatrix3fv);
|
|
ORD(glProgramUniformMatrix4fv);
|
|
ORD(glProgramUniformMatrix2x3fv);
|
|
ORD(glProgramUniformMatrix3x2fv);
|
|
ORD(glProgramUniformMatrix2x4fv);
|
|
ORD(glProgramUniformMatrix4x2fv);
|
|
ORD(glProgramUniformMatrix3x4fv);
|
|
ORD(glProgramUniformMatrix4x3fv);
|
|
ORD(glValidateProgramPipeline);
|
|
ORD(glGetProgramPipelineInfoLog);
|
|
ORD(glBindImageTexture);
|
|
ORD(glGetBooleani_v);
|
|
ORD(glMemoryBarrier);
|
|
ORD(glMemoryBarrierByRegion);
|
|
ORD(glTexStorage2DMultisample);
|
|
ORD(glGetMultisamplefv);
|
|
ORD(glSampleMaski);
|
|
ORD(glGetTexLevelParameteriv);
|
|
ORD(glGetTexLevelParameterfv);
|
|
ORD(glBindVertexBuffer);
|
|
ORD(glVertexAttribFormat);
|
|
ORD(glVertexAttribIFormat);
|
|
ORD(glVertexAttribBinding);
|
|
ORD(glVertexBindingDivisor);
|
|
}
|
|
#undef ORD
|
|
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
|
|
|
|
static Eina_Bool
|
|
_evgl_gles3_api_init(int minor_version, void *(*get_proc_address)(const char *))
|
|
{
|
|
static Eina_Bool _initialized = EINA_FALSE;
|
|
if (_initialized) return EINA_TRUE;
|
|
|
|
memset(&_gles3_api, 0, sizeof(_gles3_api));
|
|
|
|
#ifdef GL_GLES
|
|
_gles3_handle = dlopen("libGLESv2.so", RTLD_NOW);
|
|
if (!_gles3_handle) _gles3_handle = dlopen("libGLESv2.so.2.0", RTLD_NOW);
|
|
if (!_gles3_handle) _gles3_handle = dlopen("libGLESv2.so.2", RTLD_NOW);
|
|
#else
|
|
_gles3_handle = dlopen("libGL.so", RTLD_NOW);
|
|
if (!_gles3_handle) _gles3_handle = dlopen("libGL.so.4", RTLD_NOW);
|
|
if (!_gles3_handle) _gles3_handle = dlopen("libGL.so.3", RTLD_NOW);
|
|
if (!_gles3_handle) _gles3_handle = dlopen("libGL.so.2", RTLD_NOW);
|
|
if (!_gles3_handle) _gles3_handle = dlopen("libGL.so.1", RTLD_NOW);
|
|
if (!_gles3_handle) _gles3_handle = dlopen("libGL.so.0", RTLD_NOW);
|
|
#endif
|
|
|
|
if (!_gles3_handle)
|
|
{
|
|
WRN("OpenGL ES 3 was not found on this system. Evas GL will not support GLES 3 contexts.");
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
if (!dlsym(_gles3_handle, "glBeginQuery"))
|
|
{
|
|
WRN("OpenGL ES 3 was not found on this system. Evas GL will not support GLES 3 contexts.");
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
if (!_evgl_load_gles3_apis(_gles3_handle, &_gles3_api, minor_version, get_proc_address))
|
|
{
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
_initialized = EINA_TRUE;
|
|
return EINA_TRUE;
|
|
}
|
|
|
|
void
|
|
_evgl_api_gles3_get(Evas_GL_API *funcs, void *(*get_proc_address)(const char *),
|
|
Eina_Bool debug, int minor_version)
|
|
{
|
|
int effective_minor = minor_version;
|
|
|
|
if (!_evgl_gles3_api_init(minor_version, get_proc_address))
|
|
return;
|
|
|
|
// Hack for NVIDIA. See also evas_gl_core.c:_context_ext_check()
|
|
if (!_gles3_api.glVertexBindingDivisor)
|
|
effective_minor = 0;
|
|
|
|
if (debug)
|
|
_debug_gles3_api_get(funcs, effective_minor);
|
|
else
|
|
_normal_gles3_api_get(funcs, effective_minor);
|
|
|
|
if (evgl_engine->direct_scissor_off)
|
|
_direct_scissor_off_api_get(funcs);
|
|
|
|
return;
|
|
}
|
|
|
|
Evas_GL_API *
|
|
_evgl_api_gles3_internal_get(void)
|
|
{
|
|
return &_gles3_api;
|
|
}
|
|
|