2012-09-24 00:41:27 -07:00
|
|
|
#include "evas_gl_core_private.h"
|
|
|
|
#include <dlfcn.h>
|
|
|
|
|
|
|
|
// EVGL GL Format Pair
|
|
|
|
typedef struct _GL_Format
|
|
|
|
{
|
|
|
|
int bit;
|
|
|
|
GLenum fmt;
|
|
|
|
} GL_Format;
|
|
|
|
|
2014-12-02 18:44:09 -08:00
|
|
|
// Extended struct size based on the 314 functions found in gl31.h
|
|
|
|
#define EVAS_GL_API_STRUCT_SIZE (sizeof(Evas_GL_API) + 300 * sizeof(void*))
|
|
|
|
static Evas_GL_API *gl_funcs = NULL;
|
|
|
|
static Evas_GL_API *gles1_funcs = NULL;
|
2015-03-04 22:36:35 -08:00
|
|
|
static Evas_GL_API *gles3_funcs = NULL;
|
2014-12-02 18:44:09 -08:00
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
EVGL_Engine *evgl_engine = NULL;
|
2013-01-21 23:00:12 -08:00
|
|
|
int _evas_gl_log_dom = -1;
|
|
|
|
int _evas_gl_log_level = -1;
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2014-09-19 01:44:56 -07:00
|
|
|
typedef void *(*glsym_func_void_ptr) ();
|
|
|
|
glsym_func_void_ptr glsym_evas_gl_native_context_get = NULL;
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
static void _surface_cap_print(int error);
|
|
|
|
static void _surface_context_list_print();
|
|
|
|
static void _internal_resources_destroy(void *eng_data, EVGL_Resource *rsc);
|
2013-01-21 23:00:12 -08:00
|
|
|
|
2015-02-24 02:05:39 -08:00
|
|
|
// NOTE: These constants are "hidden", kinda non public API. They should not
|
|
|
|
// be used unless you know exactly what you are doing.
|
|
|
|
// These vars replace environment variables.
|
|
|
|
#define EVAS_GL_OPTIONS_DIRECT_MEMORY_OPTIMIZE 0x1000
|
|
|
|
#define EVAS_GL_OPTIONS_DIRECT_OVERRIDE 0x2000
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
//---------------------------------------------------------------//
|
2013-01-06 22:16:18 -08:00
|
|
|
// Internal Resources:
|
2012-09-24 00:41:27 -07:00
|
|
|
// - Surface and Context used for internal buffer creation
|
|
|
|
//---------------------------------------------------------------//
|
|
|
|
static void *
|
2013-05-02 03:06:10 -07:00
|
|
|
_internal_resources_create(void *eng_data)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
EVGL_Resource *rsc = NULL;
|
|
|
|
|
|
|
|
// Check if engine is valid
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!evgl_engine)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("EVGL Engine not initialized!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate resource
|
|
|
|
rsc = calloc(1, sizeof(EVGL_Resource));
|
|
|
|
if (!rsc)
|
|
|
|
{
|
|
|
|
ERR("Error allocating EVGL_Resource");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-03-09 01:25:20 -07:00
|
|
|
// Get display
|
|
|
|
rsc->display = evgl_engine->funcs->display_get(eng_data);
|
|
|
|
if (!rsc->display)
|
|
|
|
{
|
|
|
|
ERR("Error getting display");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Create resource surface
|
2013-05-02 03:06:10 -07:00
|
|
|
rsc->window = evgl_engine->funcs->native_window_create(eng_data);
|
|
|
|
if (!rsc->window)
|
2013-03-04 03:23:49 -08:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
ERR("Error creating native window");
|
|
|
|
goto error;
|
|
|
|
}
|
2013-03-04 03:23:49 -08:00
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
rsc->surface = evgl_engine->funcs->surface_create(eng_data, rsc->window);
|
|
|
|
if (!rsc->surface)
|
|
|
|
{
|
|
|
|
ERR("Error creating native surface");
|
|
|
|
goto error;
|
2013-03-04 03:23:49 -08:00
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Create a resource context
|
2014-09-22 03:15:37 -07:00
|
|
|
rsc->context = evgl_engine->funcs->context_create(eng_data, NULL, EVAS_GL_GLES_2_X);
|
2012-09-24 00:41:27 -07:00
|
|
|
if (!rsc->context)
|
|
|
|
{
|
2015-03-09 01:25:20 -07:00
|
|
|
ERR("Internal resource context creation failed.");
|
2012-09-24 00:41:27 -07:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2014-09-01 02:11:53 -07:00
|
|
|
rsc->error_state = EVAS_GL_SUCCESS;
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
return rsc;
|
|
|
|
|
|
|
|
error:
|
2013-05-02 03:06:10 -07:00
|
|
|
_internal_resources_destroy(eng_data, rsc);
|
2012-09-24 00:41:27 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
static void
|
|
|
|
_internal_resources_destroy(void *eng_data, EVGL_Resource *rsc)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
if ((!eng_data) || (!rsc)) return;
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
if (rsc->context)
|
2013-09-09 21:53:56 -07:00
|
|
|
evgl_engine->funcs->context_destroy(eng_data, rsc->context);
|
2013-05-02 03:06:10 -07:00
|
|
|
if (rsc->surface)
|
|
|
|
evgl_engine->funcs->surface_destroy(eng_data, rsc->surface);
|
|
|
|
if (rsc->window)
|
|
|
|
evgl_engine->funcs->native_window_destroy(eng_data, rsc->window);
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
free(rsc);
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-05-02 03:06:10 -07:00
|
|
|
_internal_resource_make_current(void *eng_data, EVGL_Context *ctx)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
EVGL_Resource *rsc = NULL;
|
|
|
|
void *surface = NULL;
|
|
|
|
void *context = NULL;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
// Retrieve the resource object
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!(rsc = _evgl_tls_resource_get()))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!(rsc = _evgl_tls_resource_create(eng_data)))
|
|
|
|
{
|
|
|
|
ERR("Error creting resources in tls.");
|
|
|
|
return 0;
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Set context from input or from resource
|
|
|
|
if (ctx)
|
|
|
|
context = ctx->context;
|
|
|
|
else
|
|
|
|
context = (void*)rsc->context;
|
|
|
|
|
2013-09-09 21:53:56 -07:00
|
|
|
// Set the surface to evas surface if it's there
|
|
|
|
if (rsc->id == evgl_engine->main_tid)
|
2013-10-24 01:37:22 -07:00
|
|
|
rsc->direct.surface = evgl_engine->funcs->evas_surface_get(eng_data);
|
2013-09-09 21:53:56 -07:00
|
|
|
|
2013-10-24 01:37:22 -07:00
|
|
|
if (rsc->direct.surface)
|
|
|
|
surface = (void*)rsc->direct.surface;
|
2013-09-09 21:53:56 -07:00
|
|
|
else
|
|
|
|
surface = (void*)rsc->surface;
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Do the make current
|
2014-11-18 00:37:25 -08:00
|
|
|
if (evgl_engine->api_debug_mode)
|
|
|
|
DBG("Calling make_current(%p, %p)", surface, context);
|
2013-05-02 03:06:10 -07:00
|
|
|
ret = evgl_engine->funcs->make_current(eng_data, surface, context, 1);
|
2012-09-24 00:41:27 -07:00
|
|
|
if (!ret)
|
|
|
|
{
|
|
|
|
ERR("Engine make_current with internal resources failed.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------//
|
2013-01-06 22:16:18 -08:00
|
|
|
// Surface Related Functions
|
2012-09-24 00:41:27 -07:00
|
|
|
// - Texture/ Renderbuffer Creation/ Attachment to FBO
|
|
|
|
// - Surface capability check
|
|
|
|
// - Internal config choose function
|
|
|
|
//---------------------------------------------------------------//
|
2013-01-21 23:00:12 -08:00
|
|
|
// Gen Texture
|
2015-03-13 00:31:54 -07:00
|
|
|
static void
|
2013-01-21 23:00:12 -08:00
|
|
|
_texture_create(GLuint *tex)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
glGenTextures(1, tex);
|
2013-01-21 23:00:12 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Create and allocate 2D texture
|
2015-03-13 00:31:54 -07:00
|
|
|
static void
|
2013-01-21 23:00:12 -08:00
|
|
|
_texture_allocate_2d(GLuint tex, GLint ifmt, GLenum fmt, GLenum type, int w, int h)
|
|
|
|
{
|
|
|
|
//if (!(*tex))
|
|
|
|
// glGenTextures(1, tex);
|
2015-03-09 01:25:20 -07:00
|
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
2012-09-24 00:41:27 -07:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, ifmt, w, h, 0, fmt, type, NULL);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Destroy Texture
|
2015-03-13 00:31:54 -07:00
|
|
|
static void
|
2012-09-24 00:41:27 -07:00
|
|
|
_texture_destroy(GLuint *tex)
|
|
|
|
{
|
|
|
|
if (*tex)
|
|
|
|
{
|
|
|
|
glDeleteTextures(1, tex);
|
|
|
|
*tex = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Attach 2D texture with the given format to already bound FBO
|
|
|
|
// *NOTE: attach2 here is used for depth_stencil attachment in GLES env.
|
2015-03-13 00:31:54 -07:00
|
|
|
static void
|
|
|
|
_texture_attach_2d(GLuint tex, GLenum attach, GLenum attach2, int samples, Eina_Bool use_extension)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
if (samples)
|
|
|
|
{
|
|
|
|
#ifdef GL_GLES
|
|
|
|
//<<< TODO : CHECK EXTENSION SUPPORT>>>
|
|
|
|
EXT_FUNC(glFramebufferTexture2DMultisample)(GL_FRAMEBUFFER,
|
|
|
|
attach,
|
|
|
|
GL_TEXTURE_2D, tex,
|
|
|
|
0, samples);
|
|
|
|
|
|
|
|
if (attach2)
|
|
|
|
EXT_FUNC(glFramebufferTexture2DMultisample)(GL_FRAMEBUFFER,
|
|
|
|
attach2,
|
|
|
|
GL_TEXTURE_2D, tex,
|
|
|
|
0, samples);
|
|
|
|
#else
|
|
|
|
ERR("MSAA not supported. Should not have come in here...!");
|
|
|
|
#endif
|
|
|
|
}
|
2015-03-13 00:31:54 -07:00
|
|
|
else if (use_extension)
|
|
|
|
{
|
|
|
|
if (gles1_funcs->glFramebufferTexture2DOES)
|
|
|
|
gles1_funcs->glFramebufferTexture2DOES(GL_FRAMEBUFFER, attach, GL_TEXTURE_2D, tex, 0);
|
|
|
|
|
|
|
|
if (attach2)
|
|
|
|
if (gles1_funcs->glFramebufferTexture2DOES)
|
|
|
|
gles1_funcs->glFramebufferTexture2DOES(GL_FRAMEBUFFER, attach2, GL_TEXTURE_2D, tex, 0);
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
else
|
|
|
|
{
|
2015-03-13 00:31:54 -07:00
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, attach, GL_TEXTURE_2D, tex, 0);
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
if (attach2)
|
2015-03-13 00:31:54 -07:00
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, attach2, GL_TEXTURE_2D, tex, 0);
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
}
|
2015-03-09 01:25:20 -07:00
|
|
|
}
|
|
|
|
|
2015-03-13 00:31:54 -07:00
|
|
|
static void *
|
|
|
|
_egl_image_create(EVGL_Context *context, GLuint tex)
|
2015-03-09 01:25:20 -07:00
|
|
|
{
|
2015-03-09 04:41:58 -07:00
|
|
|
#ifdef GL_GLES
|
2015-03-13 00:31:54 -07:00
|
|
|
EGLDisplay dpy = EGL_NO_DISPLAY;
|
|
|
|
EGLContext ctx = EGL_NO_CONTEXT;
|
2015-03-09 01:25:20 -07:00
|
|
|
EVGL_Resource *rsc = NULL;
|
2015-03-09 04:41:58 -07:00
|
|
|
|
2015-03-09 01:25:20 -07:00
|
|
|
int attribs[] = {
|
2015-03-13 00:31:54 -07:00
|
|
|
EGL_GL_TEXTURE_LEVEL_KHR, 0,
|
|
|
|
EGL_IMAGE_PRESERVED_KHR, 0,
|
|
|
|
EGL_NONE
|
2015-03-09 01:25:20 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
// Retrieve the resource object
|
|
|
|
if (!(rsc = _evgl_tls_resource_get()))
|
|
|
|
{
|
|
|
|
ERR("Error creating resources in tls.");
|
2015-03-13 00:31:54 -07:00
|
|
|
return NULL;
|
2015-03-09 01:25:20 -07:00
|
|
|
}
|
|
|
|
|
2015-03-13 00:31:54 -07:00
|
|
|
dpy = (EGLDisplay)rsc->display;
|
|
|
|
ctx = (EGLContext)context->context;
|
2015-03-09 01:25:20 -07:00
|
|
|
|
2015-03-13 00:31:54 -07:00
|
|
|
return EXT_FUNC(eglCreateImage)(dpy, ctx, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(uintptr_t)tex, attribs);
|
2015-03-09 04:41:58 -07:00
|
|
|
#else
|
2015-03-13 00:31:54 -07:00
|
|
|
(void) context; (void) tex;
|
|
|
|
return NULL;
|
2015-03-09 04:41:58 -07:00
|
|
|
#endif
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
2015-03-13 00:31:54 -07:00
|
|
|
static void
|
|
|
|
_framebuffer_create(GLuint *buf, Eina_Bool use_extension)
|
|
|
|
{
|
|
|
|
if (use_extension)
|
|
|
|
{
|
|
|
|
if (gles1_funcs && gles1_funcs->glGenFramebuffersOES)
|
|
|
|
gles1_funcs->glGenFramebuffersOES(1, buf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glGenFramebuffers(1, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_framebuffer_bind(GLuint buf, Eina_Bool use_extension)
|
|
|
|
{
|
|
|
|
if (use_extension)
|
|
|
|
{
|
|
|
|
if (gles1_funcs && gles1_funcs->glBindFramebufferOES)
|
|
|
|
gles1_funcs->glBindFramebufferOES(GL_FRAMEBUFFER, buf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static GLenum
|
|
|
|
_framebuffer_check(Eina_Bool use_extension)
|
|
|
|
{
|
|
|
|
GLenum ret = 0;
|
|
|
|
if (use_extension)
|
|
|
|
{
|
|
|
|
if (gles1_funcs && gles1_funcs->glCheckFramebufferStatusOES)
|
|
|
|
ret = gles1_funcs->glCheckFramebufferStatusOES(GL_FRAMEBUFFER);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
// Gen Renderbuffer
|
2015-03-13 00:31:54 -07:00
|
|
|
static void
|
2013-01-21 23:00:12 -08:00
|
|
|
_renderbuffer_create(GLuint *buf)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
glGenRenderbuffers(1, buf);
|
2013-01-21 23:00:12 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Attach a renderbuffer with the given format to already bound FBO
|
2015-03-13 00:31:54 -07:00
|
|
|
static void
|
2013-01-21 23:00:12 -08:00
|
|
|
_renderbuffer_allocate(GLuint buf, GLenum fmt, int w, int h, int samples)
|
|
|
|
{
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, buf);
|
2012-09-24 00:41:27 -07:00
|
|
|
if (samples)
|
|
|
|
#ifdef GL_GLES
|
|
|
|
EXT_FUNC(glRenderbufferStorageMultisample)(GL_RENDERBUFFER, samples, fmt, w, h);
|
|
|
|
#else
|
|
|
|
ERR("MSAA not supported. Should not have come in here...!");
|
|
|
|
#endif
|
|
|
|
else
|
|
|
|
glRenderbufferStorage(GL_RENDERBUFFER, fmt, w, h);
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
|
|
|
|
|
|
return;
|
|
|
|
samples = 0;
|
|
|
|
}
|
|
|
|
|
2015-03-13 00:31:54 -07:00
|
|
|
static void
|
2012-09-24 00:41:27 -07:00
|
|
|
_renderbuffer_destroy(GLuint *buf)
|
|
|
|
{
|
|
|
|
if (*buf)
|
|
|
|
{
|
|
|
|
glDeleteRenderbuffers(1, buf);
|
|
|
|
*buf = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Attach a renderbuffer with the given format to already bound FBO
|
2015-03-13 00:31:54 -07:00
|
|
|
static void
|
|
|
|
_renderbuffer_attach(GLuint buf, GLenum attach, Eina_Bool use_extension)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2015-03-13 00:31:54 -07:00
|
|
|
if (use_extension)
|
|
|
|
{
|
|
|
|
if (gles1_funcs->glFramebufferRenderbufferOES)
|
|
|
|
gles1_funcs->glFramebufferRenderbufferOES(GL_FRAMEBUFFER, attach, GL_RENDERBUFFER, buf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attach, GL_RENDERBUFFER, buf);
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the given FBO surface config is supported by the driver
|
|
|
|
static int
|
2013-01-06 22:16:18 -08:00
|
|
|
_fbo_surface_cap_test(GLint color_ifmt, GLenum color_fmt,
|
2012-09-24 00:41:27 -07:00
|
|
|
GLenum depth_fmt, GLenum stencil_fmt, int mult_samples)
|
|
|
|
{
|
|
|
|
GLuint fbo = 0;
|
|
|
|
GLuint color_buf = 0;
|
|
|
|
GLuint depth_buf = 0;
|
|
|
|
GLuint stencil_buf = 0;
|
|
|
|
GLuint depth_stencil_buf = 0;
|
|
|
|
int depth_stencil = 0;
|
|
|
|
int fb_status = 0;
|
|
|
|
int w = 2, h = 2; // Test it with a simple (2,2) surface. Should I test it with NPOT?
|
|
|
|
|
|
|
|
// Gen FBO
|
|
|
|
glGenFramebuffers(1, &fbo);
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
|
|
|
|
|
|
|
// Color Buffer Texture
|
|
|
|
if ((color_ifmt) && (color_fmt))
|
|
|
|
{
|
2013-01-21 23:00:12 -08:00
|
|
|
_texture_create(&color_buf);
|
|
|
|
_texture_allocate_2d(color_buf, color_ifmt, color_fmt, GL_UNSIGNED_BYTE, w, h);
|
2015-03-09 01:25:20 -07:00
|
|
|
_texture_attach_2d(color_buf, GL_COLOR_ATTACHMENT0, 0, mult_samples, EINA_FALSE);
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check Depth_Stencil Format First
|
|
|
|
#ifdef GL_GLES
|
|
|
|
if (depth_fmt == GL_DEPTH_STENCIL_OES)
|
|
|
|
{
|
2013-01-21 23:00:12 -08:00
|
|
|
_texture_create(&depth_stencil_buf);
|
|
|
|
_texture_allocate_2d(depth_stencil_buf, depth_fmt,
|
2012-09-24 00:41:27 -07:00
|
|
|
depth_fmt, GL_UNSIGNED_INT_24_8_OES, w, h);
|
2013-01-21 23:00:12 -08:00
|
|
|
_texture_attach_2d(depth_stencil_buf, GL_DEPTH_ATTACHMENT,
|
2015-03-09 01:25:20 -07:00
|
|
|
GL_STENCIL_ATTACHMENT, mult_samples, EINA_FALSE);
|
2012-09-24 00:41:27 -07:00
|
|
|
depth_stencil = 1;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
if (depth_fmt == GL_DEPTH24_STENCIL8)
|
|
|
|
{
|
2013-01-21 23:00:12 -08:00
|
|
|
_renderbuffer_create(&depth_stencil_buf);
|
|
|
|
_renderbuffer_allocate(depth_stencil_buf, depth_fmt, w, h, mult_samples);
|
2015-03-09 01:25:20 -07:00
|
|
|
_renderbuffer_attach(depth_stencil_buf, GL_DEPTH_STENCIL_ATTACHMENT, EINA_FALSE);
|
2012-09-24 00:41:27 -07:00
|
|
|
depth_stencil = 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Depth Attachment
|
|
|
|
if ((!depth_stencil) && (depth_fmt))
|
|
|
|
{
|
2013-01-21 23:00:12 -08:00
|
|
|
_renderbuffer_create(&depth_buf);
|
|
|
|
_renderbuffer_allocate(depth_buf, depth_fmt, w, h, mult_samples);
|
2015-03-09 01:25:20 -07:00
|
|
|
_renderbuffer_attach(depth_buf, GL_DEPTH_ATTACHMENT, EINA_FALSE);
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Stencil Attachment
|
|
|
|
if ((!depth_stencil) && (stencil_fmt))
|
|
|
|
{
|
2013-01-21 23:00:12 -08:00
|
|
|
_renderbuffer_create(&stencil_buf);
|
|
|
|
_renderbuffer_allocate(stencil_buf, stencil_fmt, w, h, mult_samples);
|
2015-03-09 01:25:20 -07:00
|
|
|
_renderbuffer_attach(stencil_buf, GL_STENCIL_ATTACHMENT, EINA_FALSE);
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check FBO for completeness
|
|
|
|
fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
|
|
|
|
|
|
|
// Delete Created Resources
|
|
|
|
_texture_destroy(&color_buf);
|
|
|
|
_renderbuffer_destroy(&depth_buf);
|
|
|
|
_renderbuffer_destroy(&stencil_buf);
|
|
|
|
#ifdef GL_GLES
|
|
|
|
_texture_destroy(&depth_stencil_buf);
|
|
|
|
#else
|
|
|
|
_renderbuffer_destroy(&depth_stencil_buf);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Delete FBO
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
|
if (fbo) glDeleteFramebuffers(1, &fbo);
|
|
|
|
|
|
|
|
// Return the result
|
|
|
|
if (fb_status != GL_FRAMEBUFFER_COMPLETE)
|
2015-02-16 02:54:23 -08:00
|
|
|
{
|
|
|
|
int err = glGetError();
|
|
|
|
|
|
|
|
if (err != GL_NO_ERROR)
|
|
|
|
DBG("glGetError() returns %x ", err);
|
|
|
|
|
|
|
|
return 0;
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2015-03-13 00:31:54 -07:00
|
|
|
static int
|
2012-09-24 00:41:27 -07:00
|
|
|
_surface_cap_test(EVGL_Surface_Format *fmt, GL_Format *color,
|
|
|
|
GL_Format *depth, GL_Format *stencil, int samples)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if ( (depth->bit == DEPTH_STENCIL) && (stencil->bit != STENCIL_BIT_8))
|
|
|
|
return 0;
|
|
|
|
|
2013-01-06 22:16:18 -08:00
|
|
|
ret = _fbo_surface_cap_test((GLint)color->fmt,
|
2012-09-24 00:41:27 -07:00
|
|
|
color->fmt,
|
2013-01-06 22:16:18 -08:00
|
|
|
depth->fmt,
|
|
|
|
stencil->fmt, samples);
|
2012-09-24 00:41:27 -07:00
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
fmt->color_bit = color->bit;
|
|
|
|
fmt->color_ifmt = (GLint)color->fmt;
|
|
|
|
fmt->color_fmt = color->fmt;
|
|
|
|
fmt->samples = samples;
|
|
|
|
|
|
|
|
if (depth->bit == DEPTH_STENCIL)
|
|
|
|
{
|
|
|
|
// Depth Stencil Case
|
|
|
|
fmt->depth_stencil_fmt = depth->fmt;
|
|
|
|
fmt->depth_bit = DEPTH_BIT_24;
|
|
|
|
fmt->depth_fmt = 0;
|
|
|
|
fmt->stencil_bit = STENCIL_BIT_8;
|
|
|
|
fmt->stencil_fmt = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-01-06 22:16:18 -08:00
|
|
|
fmt->depth_stencil_fmt = 0;
|
2012-09-24 00:41:27 -07:00
|
|
|
fmt->depth_bit = depth->bit;
|
|
|
|
fmt->depth_fmt = depth->fmt;
|
|
|
|
fmt->stencil_bit = stencil->bit;
|
|
|
|
fmt->stencil_fmt = stencil->fmt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-03-13 00:31:54 -07:00
|
|
|
static int
|
2013-05-02 03:06:10 -07:00
|
|
|
_surface_cap_check()
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
int num_fmts = 0;
|
|
|
|
int i, j, k, m;
|
|
|
|
|
|
|
|
GL_Format color[] = {
|
|
|
|
{ COLOR_RGB_888, GL_RGB },
|
|
|
|
{ COLOR_RGBA_8888, GL_RGBA },
|
|
|
|
{ -1, -1 },
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifdef GL_GLES
|
2013-01-06 22:16:18 -08:00
|
|
|
GL_Format depth[] = {
|
2012-09-24 00:41:27 -07:00
|
|
|
{ DEPTH_NONE, 0 },
|
2013-01-06 22:16:18 -08:00
|
|
|
{ DEPTH_STENCIL, GL_DEPTH_STENCIL_OES },
|
2012-09-24 00:41:27 -07:00
|
|
|
{ DEPTH_BIT_8, GL_DEPTH_COMPONENT },
|
|
|
|
{ DEPTH_BIT_16, GL_DEPTH_COMPONENT16 },
|
|
|
|
{ DEPTH_BIT_24, GL_DEPTH_COMPONENT24_OES },
|
|
|
|
{ DEPTH_BIT_32, GL_DEPTH_COMPONENT32_OES },
|
|
|
|
{ -1, -1 },
|
2013-01-06 22:16:18 -08:00
|
|
|
};
|
|
|
|
GL_Format stencil[] = {
|
2012-09-24 00:41:27 -07:00
|
|
|
{ STENCIL_NONE, 0 },
|
|
|
|
{ STENCIL_BIT_1, GL_STENCIL_INDEX1_OES },
|
|
|
|
{ STENCIL_BIT_4, GL_STENCIL_INDEX4_OES },
|
|
|
|
{ STENCIL_BIT_8, GL_STENCIL_INDEX8 },
|
|
|
|
{ -1, -1 },
|
|
|
|
};
|
|
|
|
#else
|
2013-01-06 22:16:18 -08:00
|
|
|
GL_Format depth[] = {
|
2012-09-24 00:41:27 -07:00
|
|
|
{ DEPTH_NONE, 0 },
|
|
|
|
{ DEPTH_STENCIL, GL_DEPTH24_STENCIL8 },
|
|
|
|
{ DEPTH_BIT_8, GL_DEPTH_COMPONENT },
|
|
|
|
{ DEPTH_BIT_16, GL_DEPTH_COMPONENT16 },
|
|
|
|
{ DEPTH_BIT_24, GL_DEPTH_COMPONENT24 },
|
|
|
|
{ DEPTH_BIT_32, GL_DEPTH_COMPONENT32 },
|
|
|
|
{ -1, -1 },
|
2013-01-06 22:16:18 -08:00
|
|
|
};
|
2012-09-24 00:41:27 -07:00
|
|
|
GL_Format stencil[] = {
|
|
|
|
{ STENCIL_NONE, 0 },
|
|
|
|
{ STENCIL_BIT_1, GL_STENCIL_INDEX1 },
|
|
|
|
{ STENCIL_BIT_4, GL_STENCIL_INDEX4 },
|
|
|
|
{ STENCIL_BIT_8, GL_STENCIL_INDEX8 },
|
|
|
|
{ -1, -1 },
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int msaa_samples[4] = {0, -1, -1, -1}; // { NO_MSAA, LOW, MED, HIGH }
|
|
|
|
|
|
|
|
EVGL_Surface_Format *fmt = NULL;
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
// Check if engine is valid
|
|
|
|
if (!evgl_engine)
|
|
|
|
{
|
|
|
|
ERR("EVGL Engine not initialized!");
|
|
|
|
return 0;
|
|
|
|
}
|
2013-06-17 01:53:33 -07:00
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Check Surface Cap for MSAA
|
2013-05-02 03:06:10 -07:00
|
|
|
if (evgl_engine->caps.msaa_supported)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
if ((evgl_engine->caps.msaa_samples[2] != evgl_engine->caps.msaa_samples[1]) &&
|
|
|
|
(evgl_engine->caps.msaa_samples[2] != evgl_engine->caps.msaa_samples[0]))
|
|
|
|
msaa_samples[3] = evgl_engine->caps.msaa_samples[2]; // HIGH
|
|
|
|
if ((evgl_engine->caps.msaa_samples[1] != evgl_engine->caps.msaa_samples[0]))
|
|
|
|
msaa_samples[2] = evgl_engine->caps.msaa_samples[1]; // MED
|
|
|
|
if (evgl_engine->caps.msaa_samples[0])
|
|
|
|
msaa_samples[1] = evgl_engine->caps.msaa_samples[0]; // LOW
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// MSAA
|
|
|
|
for ( m = 0; m < 4; m++)
|
|
|
|
{
|
|
|
|
if (msaa_samples[m] < 0) continue;
|
|
|
|
|
|
|
|
// Color Formats
|
|
|
|
i = 0;
|
|
|
|
while ( color[i].bit >= 0 )
|
2013-01-06 22:16:18 -08:00
|
|
|
{
|
2012-09-24 00:41:27 -07:00
|
|
|
j = 0;
|
|
|
|
// Depth Formats
|
2013-01-06 22:16:18 -08:00
|
|
|
while ( depth[j].bit >= 0 )
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
k = 0;
|
|
|
|
// Stencil Formats
|
|
|
|
while ( stencil[k].bit >= 0)
|
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
fmt = &evgl_engine->caps.fbo_fmts[num_fmts];
|
2012-09-24 00:41:27 -07:00
|
|
|
if (_surface_cap_test(fmt, &color[i], &depth[j], &stencil[k], msaa_samples[m]))
|
|
|
|
num_fmts++;
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
j++;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return num_fmts;
|
|
|
|
}
|
|
|
|
|
2013-01-06 22:16:18 -08:00
|
|
|
static int
|
2013-05-02 03:06:10 -07:00
|
|
|
_surface_cap_load(Eet_File *ef)
|
2013-01-06 22:16:18 -08:00
|
|
|
{
|
|
|
|
int res = 0, i = 0, length = 0;
|
|
|
|
char tag[80];
|
2013-04-09 23:38:53 -07:00
|
|
|
char *data = NULL;
|
2013-01-06 22:16:18 -08:00
|
|
|
|
|
|
|
data = eet_read(ef, "num_fbo_fmts", &length);
|
|
|
|
if ((!data) || (length <= 0)) goto finish;
|
2013-04-09 23:38:53 -07:00
|
|
|
if (data[length - 1] != 0) goto finish;
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_engine->caps.num_fbo_fmts = atoi(data);
|
2013-01-06 22:16:18 -08:00
|
|
|
free(data);
|
2013-04-09 23:38:53 -07:00
|
|
|
data = NULL;
|
2013-01-06 22:16:18 -08:00
|
|
|
|
2013-06-17 01:53:33 -07:00
|
|
|
// !!!FIXME
|
2013-01-06 22:16:18 -08:00
|
|
|
// Should use eet functionality instead of just reading using sscanfs...
|
2013-05-02 03:06:10 -07:00
|
|
|
for (i = 0; i < evgl_engine->caps.num_fbo_fmts; ++i)
|
2013-01-06 22:16:18 -08:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
EVGL_Surface_Format *fmt = &evgl_engine->caps.fbo_fmts[i];
|
2013-01-06 22:16:18 -08:00
|
|
|
|
|
|
|
snprintf(tag, sizeof(tag), "fbo_%d", i);
|
|
|
|
data = eet_read(ef, tag, &length);
|
|
|
|
if ((!data) || (length <= 0)) goto finish;
|
2013-04-09 23:38:53 -07:00
|
|
|
if (data[length - 1] != 0) goto finish;
|
2013-01-06 22:16:18 -08:00
|
|
|
sscanf(data, "%d%d%d%d%d%d%d%d%d%d",
|
|
|
|
&(fmt->index),
|
|
|
|
(int*)(&(fmt->color_bit)), &(fmt->color_ifmt), &(fmt->color_fmt),
|
|
|
|
(int*)(&(fmt->depth_bit)), &(fmt->depth_fmt),
|
|
|
|
(int*)(&(fmt->stencil_bit)), &(fmt->stencil_fmt),
|
|
|
|
&(fmt->depth_stencil_fmt),
|
|
|
|
&(fmt->samples));
|
|
|
|
free(data);
|
2013-04-09 23:38:53 -07:00
|
|
|
data = NULL;
|
2013-01-06 22:16:18 -08:00
|
|
|
}
|
|
|
|
res = 1;
|
|
|
|
|
|
|
|
finish:
|
|
|
|
if (data) free(data);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-05-02 03:06:10 -07:00
|
|
|
_surface_cap_save(Eet_File *ef)
|
2013-01-06 22:16:18 -08:00
|
|
|
{
|
|
|
|
int i = 0;
|
2013-04-09 23:38:53 -07:00
|
|
|
char tag[80], data[80];
|
2013-01-06 22:16:18 -08:00
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
snprintf(data, sizeof(data), "%d", evgl_engine->caps.num_fbo_fmts);
|
2013-04-09 23:38:53 -07:00
|
|
|
if (eet_write(ef, "num_fbo_fmts", data, strlen(data) + 1, 1) < 0)
|
2013-01-06 22:16:18 -08:00
|
|
|
return 0;
|
|
|
|
|
2013-06-17 01:53:33 -07:00
|
|
|
// !!!FIXME
|
2013-01-06 22:16:18 -08:00
|
|
|
// Should use eet functionality instead of just writing out using snprintfs...
|
2013-05-02 03:06:10 -07:00
|
|
|
for (i = 0; i < evgl_engine->caps.num_fbo_fmts; ++i)
|
2013-01-06 22:16:18 -08:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
EVGL_Surface_Format *fmt = &evgl_engine->caps.fbo_fmts[i];
|
2013-01-06 22:16:18 -08:00
|
|
|
|
|
|
|
snprintf(tag, sizeof(tag), "fbo_%d", i);
|
|
|
|
snprintf(data, sizeof(data), "%d %d %d %d %d %d %d %d %d %d",
|
|
|
|
fmt->index,
|
|
|
|
fmt->color_bit, fmt->color_ifmt, fmt->color_fmt,
|
|
|
|
fmt->depth_bit, fmt->depth_fmt,
|
|
|
|
fmt->stencil_bit, fmt->stencil_fmt,
|
|
|
|
fmt->depth_stencil_fmt,
|
|
|
|
fmt->samples);
|
2013-04-09 23:38:53 -07:00
|
|
|
if (eet_write(ef, tag, data, strlen(data) + 1, 1) < 0) return 0;
|
2013-01-06 22:16:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-05-02 03:06:10 -07:00
|
|
|
_surface_cap_cache_load()
|
2013-01-06 22:16:18 -08:00
|
|
|
{
|
|
|
|
/* check eet */
|
|
|
|
Eet_File *et = NULL;
|
|
|
|
char cap_dir_path[PATH_MAX];
|
|
|
|
char cap_file_path[PATH_MAX];
|
|
|
|
|
|
|
|
if (!evas_gl_common_file_cache_dir_check(cap_dir_path, sizeof(cap_dir_path)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!evas_gl_common_file_cache_file_check(cap_dir_path, "surface_cap",
|
|
|
|
cap_file_path, sizeof(cap_dir_path)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* use eet */
|
|
|
|
if (!eet_init()) return 0;
|
|
|
|
et = eet_open(cap_file_path, EET_FILE_MODE_READ);
|
|
|
|
if (!et) goto error;
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!_surface_cap_load(et))
|
2013-01-06 22:16:18 -08:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (et) eet_close(et);
|
|
|
|
eet_shutdown();
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (et) eet_close(et);
|
|
|
|
eet_shutdown();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-05-02 03:06:10 -07:00
|
|
|
_surface_cap_cache_save()
|
2013-01-06 22:16:18 -08:00
|
|
|
{
|
|
|
|
/* check eet */
|
|
|
|
Eet_File *et = NULL; //check eet file
|
|
|
|
int tmpfd;
|
|
|
|
int res = 0;
|
|
|
|
char cap_dir_path[PATH_MAX];
|
|
|
|
char cap_file_path[PATH_MAX];
|
|
|
|
char tmp_file[PATH_MAX];
|
|
|
|
|
|
|
|
if (!evas_gl_common_file_cache_dir_check(cap_dir_path, sizeof(cap_dir_path)))
|
|
|
|
{
|
|
|
|
res = evas_gl_common_file_cache_mkpath(cap_dir_path);
|
|
|
|
if (!res) return 0; /* we can't make directory */
|
|
|
|
}
|
|
|
|
|
|
|
|
evas_gl_common_file_cache_file_check(cap_dir_path, "surface_cap", cap_file_path,
|
|
|
|
sizeof(cap_dir_path));
|
|
|
|
|
|
|
|
/* use mkstemp for writing */
|
|
|
|
snprintf(tmp_file, sizeof(tmp_file), "%s.XXXXXX", cap_file_path);
|
2014-10-27 05:48:37 -07:00
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
mode_t old_umask = umask(S_IRWXG|S_IRWXO);
|
|
|
|
#endif
|
2013-01-06 22:16:18 -08:00
|
|
|
tmpfd = mkstemp(tmp_file);
|
2014-10-27 05:48:37 -07:00
|
|
|
#ifndef _WIN32
|
|
|
|
umask(old_umask);
|
|
|
|
#endif
|
|
|
|
|
2013-01-06 22:16:18 -08:00
|
|
|
if (tmpfd < 0) goto error;
|
|
|
|
close(tmpfd);
|
|
|
|
|
|
|
|
/* use eet */
|
|
|
|
if (!eet_init()) goto error;
|
|
|
|
|
|
|
|
et = eet_open(tmp_file, EET_FILE_MODE_WRITE);
|
|
|
|
if (!et) goto error;
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!_surface_cap_save(et)) goto error;
|
2013-01-06 22:16:18 -08:00
|
|
|
|
|
|
|
if (eet_close(et) != EET_ERROR_NONE) goto error;
|
|
|
|
if (rename(tmp_file,cap_file_path) < 0) goto error;
|
|
|
|
eet_shutdown();
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (et) eet_close(et);
|
|
|
|
if (evas_gl_common_file_cache_file_exists(tmp_file)) unlink(tmp_file);
|
|
|
|
eet_shutdown();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
static int
|
2013-05-02 03:06:10 -07:00
|
|
|
_surface_cap_init(void *eng_data)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
int max_size = 0;
|
|
|
|
|
|
|
|
// Do internal make current
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!_internal_resource_make_current(eng_data, NULL))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Error doing an internal resource make current");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Query the max width and height of the surface
|
|
|
|
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &max_size);
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_engine->caps.max_w = max_size;
|
|
|
|
evgl_engine->caps.max_h = max_size;
|
|
|
|
DBG("Max Surface Width: %d Height: %d", evgl_engine->caps.max_w, evgl_engine->caps.max_h);
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Check for MSAA support
|
|
|
|
#ifdef GL_GLES
|
|
|
|
int max_samples = 0;
|
|
|
|
|
2014-06-10 03:20:16 -07:00
|
|
|
if (EXTENSION_SUPPORT(IMG_multisampled_render_to_texture))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
glGetIntegerv(GL_MAX_SAMPLES_IMG, &max_samples);
|
2014-06-10 03:20:16 -07:00
|
|
|
}
|
|
|
|
else if (EXTENSION_SUPPORT(EXT_multisampled_render_to_texture))
|
|
|
|
{
|
|
|
|
glGetIntegerv(GL_MAX_SAMPLES_EXT, &max_samples);
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2014-06-10 03:20:16 -07:00
|
|
|
if (max_samples >= 2)
|
|
|
|
{
|
|
|
|
evgl_engine->caps.msaa_samples[0] = 2;
|
2014-06-10 03:22:04 -07:00
|
|
|
evgl_engine->caps.msaa_samples[1] = (max_samples >> 1) < 2 ? 2 : (max_samples >> 1);
|
2014-06-10 03:20:16 -07:00
|
|
|
evgl_engine->caps.msaa_samples[2] = max_samples;
|
|
|
|
evgl_engine->caps.msaa_supported = 1;
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-01-06 22:16:18 -08:00
|
|
|
// Load Surface Cap
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!_surface_cap_cache_load())
|
2013-01-06 22:16:18 -08:00
|
|
|
{
|
|
|
|
// Check Surface Cap
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_engine->caps.num_fbo_fmts = _surface_cap_check();
|
|
|
|
_surface_cap_cache_save();
|
2013-01-06 22:16:18 -08:00
|
|
|
DBG("Ran Evas GL Surface Cap and Cached the existing values.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DBG("Loaded cached Evas GL Surface Cap values.");
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
if (evgl_engine->caps.num_fbo_fmts)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
_surface_cap_print(0);
|
|
|
|
DBG("Number of supported surface formats: %d", evgl_engine->caps.num_fbo_fmts);
|
2012-09-24 00:41:27 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ERR("There are no available surface formats. Error!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-09 01:25:20 -07:00
|
|
|
static int
|
|
|
|
_context_ext_check(EVGL_Context *ctx)
|
|
|
|
{
|
|
|
|
if (!ctx)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (ctx->extension_checked)
|
|
|
|
return 1;
|
|
|
|
|
2015-03-09 04:41:58 -07:00
|
|
|
#ifdef GL_GLES
|
2015-03-16 19:40:04 -07:00
|
|
|
int fbo_supported = 0;
|
|
|
|
int egl_image_supported = 0;
|
|
|
|
|
2015-03-09 01:25:20 -07:00
|
|
|
switch (ctx->version)
|
|
|
|
{
|
|
|
|
case EVAS_GL_GLES_1_X:
|
|
|
|
if (EXTENSION_SUPPORT_GLES1(framebuffer_object))
|
2015-03-13 00:31:54 -07:00
|
|
|
fbo_supported = 1;
|
2015-03-09 01:25:20 -07:00
|
|
|
break;
|
|
|
|
case EVAS_GL_GLES_2_X:
|
2015-03-13 00:31:54 -07:00
|
|
|
case EVAS_GL_GLES_3_X:
|
2015-03-09 01:25:20 -07:00
|
|
|
default:
|
|
|
|
fbo_supported = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (EXTENSION_SUPPORT(EGL_KHR_image_base)
|
|
|
|
&& EXTENSION_SUPPORT(EGL_KHR_gl_texture_2D_image))
|
|
|
|
egl_image_supported = 1;
|
|
|
|
|
|
|
|
if (fbo_supported && egl_image_supported)
|
2015-03-13 00:31:54 -07:00
|
|
|
ctx->fbo_image_supported = 1;
|
2015-03-16 19:40:04 -07:00
|
|
|
#else
|
|
|
|
ctx->fbo_image_supported = 1;
|
|
|
|
#endif
|
2015-03-09 01:25:20 -07:00
|
|
|
|
|
|
|
ctx->extension_checked = 1;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
static const char *
|
|
|
|
_glenum_string_get(GLenum e)
|
|
|
|
{
|
|
|
|
switch (e)
|
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
return "0";
|
|
|
|
case GL_RGB:
|
|
|
|
return "GL_RGB";
|
|
|
|
case GL_RGBA:
|
|
|
|
return "GL_RGBA";
|
|
|
|
|
|
|
|
#ifdef GL_GLES
|
|
|
|
// Depth
|
|
|
|
case GL_DEPTH_COMPONENT:
|
|
|
|
return "GL_DEPTH_COMPONENT";
|
|
|
|
case GL_DEPTH_COMPONENT16:
|
|
|
|
return "GL_DEPTH_COMPONENT16";
|
|
|
|
case GL_DEPTH_COMPONENT24_OES:
|
|
|
|
return "GL_DEPTH_COMPONENT24_OES";
|
|
|
|
|
|
|
|
// Stencil
|
|
|
|
case GL_STENCIL_INDEX1_OES:
|
|
|
|
return "GL_STENCIL_INDEX1_OES";
|
|
|
|
case GL_STENCIL_INDEX4_OES:
|
|
|
|
return "GL_STENCIL_INDEX4_OES";
|
|
|
|
case GL_STENCIL_INDEX8:
|
|
|
|
return "GL_STENCIL_INDEX8";
|
|
|
|
|
|
|
|
// Depth_Stencil
|
|
|
|
case GL_DEPTH_STENCIL_OES:
|
|
|
|
return "GL_DEPTH_STENCIL_OES";
|
|
|
|
#else
|
|
|
|
// Depth
|
|
|
|
case GL_DEPTH_COMPONENT:
|
|
|
|
return "GL_DEPTH_COMPONENT";
|
|
|
|
case GL_DEPTH_COMPONENT16:
|
|
|
|
return "GL_DEPTH_COMPONENT16";
|
|
|
|
case GL_DEPTH_COMPONENT24:
|
|
|
|
return "GL_DEPTH_COMPONENT24";
|
|
|
|
case GL_DEPTH_COMPONENT32:
|
|
|
|
return "GL_DEPTH_COMPONENT32";
|
|
|
|
|
|
|
|
// Stencil
|
|
|
|
case GL_STENCIL_INDEX:
|
|
|
|
return "GL_STENCIL_INDEX";
|
|
|
|
case GL_STENCIL_INDEX1:
|
|
|
|
return "GL_STENCIL_INDEX1";
|
|
|
|
case GL_STENCIL_INDEX4:
|
|
|
|
return "GL_STENCIL_INDEX4";
|
|
|
|
case GL_STENCIL_INDEX8:
|
|
|
|
return "GL_STENCIL_INDEX8";
|
|
|
|
|
|
|
|
// Depth_Stencil
|
2014-11-18 00:37:25 -08:00
|
|
|
case GL_DEPTH_STENCIL:
|
|
|
|
return "GL_DEPTH_STENCIL";
|
2012-09-24 00:41:27 -07:00
|
|
|
case GL_DEPTH24_STENCIL8:
|
|
|
|
return "GL_DEPTH24_STENCIL8";
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
return "ERR";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2013-05-02 03:06:10 -07:00
|
|
|
_surface_cap_print(int error)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
#define PRINT_LOG(...) \
|
|
|
|
if (error) \
|
|
|
|
ERR(__VA_ARGS__); \
|
|
|
|
else \
|
|
|
|
DBG(__VA_ARGS__);
|
|
|
|
|
|
|
|
PRINT_LOG("----------------------------------------------------------------------------------------------------------------");
|
|
|
|
PRINT_LOG(" Evas GL Supported Surface Format ");
|
|
|
|
PRINT_LOG("----------------------------------------------------------------------------------------------------------------\n");
|
2013-05-02 03:06:10 -07:00
|
|
|
PRINT_LOG(" Max Surface Width: %d Height: %d", evgl_engine->caps.max_w, evgl_engine->caps.max_h);
|
|
|
|
PRINT_LOG(" Multisample Support: %d", evgl_engine->caps.msaa_supported);
|
|
|
|
//if (evgl_engine->caps.msaa_supported)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
PRINT_LOG(" Low Samples: %d", evgl_engine->caps.msaa_samples[0]);
|
|
|
|
PRINT_LOG(" Med Samples: %d", evgl_engine->caps.msaa_samples[1]);
|
|
|
|
PRINT_LOG(" High Samples: %d", evgl_engine->caps.msaa_samples[2]);
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
PRINT_LOG("[Index] [Color Format] [------Depth Bits------] [----Stencil Bits---] [---Depth_Stencil---] [Samples]");
|
|
|
|
|
|
|
|
#define PRINT_SURFACE_CAP(IDX, COLOR, DEPTH, STENCIL, DS, SAMPLE) \
|
|
|
|
{ \
|
|
|
|
PRINT_LOG(" %3d %10s %25s %25s %25s %5d", IDX, _glenum_string_get(COLOR), _glenum_string_get(DEPTH), _glenum_string_get(STENCIL), _glenum_string_get(DS), SAMPLE ); \
|
|
|
|
}
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
for (i = 0; i < evgl_engine->caps.num_fbo_fmts; ++i)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
EVGL_Surface_Format *fmt = &evgl_engine->caps.fbo_fmts[i];
|
2012-09-24 00:41:27 -07:00
|
|
|
PRINT_SURFACE_CAP(i, fmt->color_fmt, fmt->depth_fmt, fmt->stencil_fmt, fmt->depth_stencil_fmt, fmt->samples);
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef PRINT_SURFACE_CAP
|
|
|
|
#undef PRINT_LOG
|
|
|
|
}
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
static void
|
2013-05-02 03:06:10 -07:00
|
|
|
_surface_context_list_print()
|
2013-01-21 23:00:12 -08:00
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
EVGL_Surface *s;
|
|
|
|
EVGL_Context *c;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
// Only print them when the log level is 6
|
|
|
|
if (_evas_gl_log_level < 6) return;
|
|
|
|
|
|
|
|
#define RESET "\e[m"
|
|
|
|
#define GREEN "\e[1;32m"
|
|
|
|
#define YELLOW "\e[1;33m"
|
|
|
|
#define RED "\e[1;31m"
|
|
|
|
|
2014-09-01 00:50:19 -07:00
|
|
|
LKL(evgl_engine->resource_lock);
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
DBG( YELLOW "-----------------------------------------------" RESET);
|
2013-05-02 03:06:10 -07:00
|
|
|
DBG("Total Number of active Evas GL Surfaces: %d", eina_list_count(evgl_engine->surfaces));
|
2013-01-21 23:00:12 -08:00
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
EINA_LIST_FOREACH(evgl_engine->surfaces, l, s)
|
2013-01-21 23:00:12 -08:00
|
|
|
{
|
|
|
|
DBG( YELLOW "\t-----------------------------------------------" RESET);
|
|
|
|
DBG( RED "\t[Surface %d]" YELLOW " Ptr: %p" RED " Appx Mem: %d Byte", count++, s, (s->buffer_mem[0]+s->buffer_mem[1]+s->buffer_mem[2]+s->buffer_mem[3]));
|
|
|
|
DBG( GREEN "\t\t Size:" RESET " (%d, %d)", s->w, s->h);
|
|
|
|
|
2013-06-17 01:53:33 -07:00
|
|
|
if (s->buffer_mem[0])
|
2013-01-21 23:00:12 -08:00
|
|
|
{
|
|
|
|
DBG( GREEN "\t\t Color Format:" RESET " %s", _glenum_string_get(s->color_fmt));
|
|
|
|
DBG( GREEN "\t\t Color Buffer Appx. Mem Usage:" RESET " %d Byte", s->buffer_mem[0]);
|
|
|
|
}
|
|
|
|
if (s->buffer_mem[1])
|
|
|
|
{
|
|
|
|
DBG( GREEN "\t\t Depth Format:" RESET " %s", _glenum_string_get(s->depth_fmt));
|
|
|
|
DBG( GREEN "\t\t Depth Buffer Appx. Mem Usage: " RESET "%d Byte", s->buffer_mem[1]);
|
|
|
|
}
|
|
|
|
if (s->buffer_mem[2])
|
|
|
|
{
|
|
|
|
DBG( GREEN "\t\t Stencil Format:" RESET " %s", _glenum_string_get(s->stencil_fmt));
|
|
|
|
DBG( GREEN "\t\t Stencil Buffer Appx. Mem Usage:" RESET " %d Byte", s->buffer_mem[2]);
|
|
|
|
}
|
|
|
|
if (s->buffer_mem[3])
|
|
|
|
{
|
|
|
|
DBG( GREEN "\t\t D-Stencil Format:" RESET " %s", _glenum_string_get(s->depth_stencil_fmt));
|
|
|
|
DBG( GREEN "\t\t D-Stencil Buffer Appx. Mem Usage:" RESET " %d Byte", s->buffer_mem[3]);
|
|
|
|
}
|
|
|
|
if (s->msaa_samples)
|
|
|
|
DBG( GREEN "\t\t MSAA Samples:" RESET " %d", s->msaa_samples);
|
|
|
|
if (s->direct_fb_opt)
|
|
|
|
DBG( GREEN "\t\t Direct Option Enabled" RESET );
|
|
|
|
DBG( YELLOW "\t-----------------------------------------------" RESET);
|
|
|
|
}
|
|
|
|
|
|
|
|
count = 0;
|
|
|
|
|
|
|
|
DBG( YELLOW "-----------------------------------------------" RESET);
|
2013-05-02 03:06:10 -07:00
|
|
|
DBG("Total Number of active Evas GL Contexts: %d", eina_list_count(evgl_engine->contexts));
|
|
|
|
EINA_LIST_FOREACH(evgl_engine->contexts, l, c)
|
2013-01-21 23:00:12 -08:00
|
|
|
{
|
|
|
|
DBG( YELLOW "\t-----------------------------------------------" RESET);
|
|
|
|
DBG( RED "\t[Context %d]" YELLOW " Ptr: %p", count++, c);
|
|
|
|
}
|
|
|
|
DBG( YELLOW "-----------------------------------------------" RESET);
|
|
|
|
|
2014-09-01 00:50:19 -07:00
|
|
|
LKU(evgl_engine->resource_lock);
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
#undef RESET
|
|
|
|
#undef GREEN
|
|
|
|
#undef YELLOW
|
|
|
|
#undef RED
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
//--------------------------------------------------------//
|
|
|
|
// Start from here.....
|
|
|
|
//--------------------------------------------------------//
|
|
|
|
static int
|
2015-03-13 00:31:54 -07:00
|
|
|
_surface_buffers_fbo_set(EVGL_Surface *sfc, GLuint fbo, Eina_Bool use_extension)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
int status;
|
|
|
|
|
2015-03-13 00:31:54 -07:00
|
|
|
_framebuffer_bind(fbo, use_extension);
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Detach any previously attached buffers
|
2015-03-13 00:31:54 -07:00
|
|
|
_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);
|
2012-09-24 00:41:27 -07:00
|
|
|
#ifdef GL_GLES
|
2015-03-13 00:31:54 -07:00
|
|
|
_texture_attach_2d(0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT, 0, use_extension);
|
2012-09-24 00:41:27 -07:00
|
|
|
#else
|
2015-03-13 00:31:54 -07:00
|
|
|
_renderbuffer_attach(0, GL_DEPTH_STENCIL_ATTACHMENT, use_extension);
|
2012-09-24 00:41:27 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Render Target Texture
|
|
|
|
if (sfc->color_buf)
|
2015-03-13 00:31:54 -07:00
|
|
|
_texture_attach_2d(sfc->color_buf, GL_COLOR_ATTACHMENT0, 0, sfc->msaa_samples, use_extension);
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Depth Stencil RenderBuffer - Attach it to FBO
|
|
|
|
if (sfc->depth_stencil_buf)
|
|
|
|
{
|
|
|
|
#ifdef GL_GLES
|
2013-01-21 23:00:12 -08:00
|
|
|
_texture_attach_2d(sfc->depth_stencil_buf, GL_DEPTH_ATTACHMENT,
|
2015-03-13 00:31:54 -07:00
|
|
|
GL_STENCIL_ATTACHMENT, sfc->msaa_samples, use_extension);
|
2012-09-24 00:41:27 -07:00
|
|
|
#else
|
2015-03-13 00:31:54 -07:00
|
|
|
_renderbuffer_attach(sfc->depth_stencil_buf, GL_DEPTH_STENCIL_ATTACHMENT, use_extension);
|
2012-09-24 00:41:27 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// Depth RenderBuffer - Attach it to FBO
|
|
|
|
if (sfc->depth_buf)
|
2015-03-13 00:31:54 -07:00
|
|
|
_renderbuffer_attach(sfc->depth_buf, GL_DEPTH_ATTACHMENT, use_extension);
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Stencil RenderBuffer - Attach it to FBO
|
|
|
|
if (sfc->stencil_buf)
|
2015-03-13 00:31:54 -07:00
|
|
|
_renderbuffer_attach(sfc->stencil_buf, GL_STENCIL_ATTACHMENT, use_extension);
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Check FBO for completeness
|
2015-03-13 00:31:54 -07:00
|
|
|
status = _framebuffer_check(use_extension);
|
2012-09-24 00:41:27 -07:00
|
|
|
if (status != GL_FRAMEBUFFER_COMPLETE)
|
|
|
|
{
|
|
|
|
ERR("FBO not complete. Error Code: %x!", status);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-01-23 20:51:51 -08:00
|
|
|
_surface_buffers_create(EVGL_Surface *sfc)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
// Create buffers
|
|
|
|
if (sfc->color_fmt)
|
|
|
|
{
|
2013-01-21 23:00:12 -08:00
|
|
|
_texture_create(&sfc->color_buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Depth_stencil buffers or separate buffers
|
|
|
|
if (sfc->depth_stencil_fmt)
|
|
|
|
{
|
|
|
|
#ifdef GL_GLES
|
|
|
|
_texture_create(&sfc->depth_stencil_buf);
|
|
|
|
#else
|
|
|
|
_renderbuffer_create(&sfc->depth_stencil_buf);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (sfc->depth_fmt)
|
|
|
|
{
|
|
|
|
_renderbuffer_create(&sfc->depth_buf);
|
|
|
|
}
|
|
|
|
if (sfc->stencil_fmt)
|
|
|
|
{
|
|
|
|
_renderbuffer_create(&sfc->stencil_buf);
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
return 1; //ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-05-02 03:06:10 -07:00
|
|
|
_surface_buffers_allocate(void *eng_data, EVGL_Surface *sfc, int w, int h, int mc)
|
2013-01-21 23:00:12 -08:00
|
|
|
{
|
|
|
|
// Set the context current with resource context/surface
|
2013-01-23 20:51:51 -08:00
|
|
|
if (mc)
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!_internal_resource_make_current(eng_data, NULL))
|
2013-01-23 20:51:51 -08:00
|
|
|
{
|
|
|
|
ERR("Error doing an internal resource make current");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
// Create buffers
|
|
|
|
if (sfc->color_fmt)
|
|
|
|
{
|
|
|
|
_texture_allocate_2d(sfc->color_buf, sfc->color_ifmt, sfc->color_fmt,
|
|
|
|
GL_UNSIGNED_BYTE, w, h);
|
2015-03-13 00:31:54 -07:00
|
|
|
if ((sfc->current_ctx) && (sfc->current_ctx->fbo_image_supported))
|
|
|
|
sfc->egl_image = _egl_image_create(sfc->current_ctx, sfc->color_buf);
|
2015-03-09 04:41:58 -07:00
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
sfc->buffer_mem[0] = w * h * 4;
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Depth_stencil buffers or separate buffers
|
|
|
|
if (sfc->depth_stencil_fmt)
|
|
|
|
{
|
|
|
|
#ifdef GL_GLES
|
2013-01-21 23:00:12 -08:00
|
|
|
_texture_allocate_2d(sfc->depth_stencil_buf, sfc->depth_stencil_fmt,
|
2012-09-24 00:41:27 -07:00
|
|
|
sfc->depth_stencil_fmt, GL_UNSIGNED_INT_24_8_OES,
|
2013-01-21 23:00:12 -08:00
|
|
|
w, h);
|
2012-09-24 00:41:27 -07:00
|
|
|
#else
|
2013-01-21 23:00:12 -08:00
|
|
|
_renderbuffer_allocate(sfc->depth_stencil_buf, sfc->depth_stencil_fmt,
|
|
|
|
w, h, sfc->msaa_samples);
|
2012-09-24 00:41:27 -07:00
|
|
|
#endif
|
2013-01-21 23:00:12 -08:00
|
|
|
sfc->buffer_mem[3] = w * h * 4;
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (sfc->depth_fmt)
|
|
|
|
{
|
2013-01-21 23:00:12 -08:00
|
|
|
_renderbuffer_allocate(sfc->depth_buf, sfc->depth_fmt, w, h,
|
2012-09-24 00:41:27 -07:00
|
|
|
sfc->msaa_samples);
|
2013-01-21 23:00:12 -08:00
|
|
|
sfc->buffer_mem[1] = w * h * 3; // Assume it's 24 bits
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
if (sfc->stencil_fmt)
|
|
|
|
{
|
2013-01-21 23:00:12 -08:00
|
|
|
_renderbuffer_allocate(sfc->stencil_buf, sfc->stencil_fmt, w,
|
|
|
|
h, sfc->msaa_samples);
|
|
|
|
sfc->buffer_mem[2] = w * h; // Assume it's 8 bits
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
return 1; //ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2013-01-23 20:51:51 -08:00
|
|
|
_surface_buffers_destroy(EVGL_Surface *sfc)
|
2013-01-21 23:00:12 -08:00
|
|
|
{
|
|
|
|
if (sfc->color_buf)
|
|
|
|
_texture_destroy(&sfc->color_buf);
|
|
|
|
if (sfc->depth_buf)
|
|
|
|
_renderbuffer_destroy(&sfc->depth_buf);
|
|
|
|
if (sfc->stencil_buf)
|
|
|
|
_renderbuffer_destroy(&sfc->stencil_buf);
|
|
|
|
if (sfc->depth_stencil_buf)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
#ifdef GL_GLES
|
2013-01-21 23:00:12 -08:00
|
|
|
_texture_destroy(&sfc->depth_stencil_buf);
|
2012-09-24 00:41:27 -07:00
|
|
|
#else
|
2013-01-21 23:00:12 -08:00
|
|
|
_renderbuffer_destroy(&sfc->depth_stencil_buf);
|
2012-09-24 00:41:27 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
return 1;
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
static int
|
2015-03-15 21:57:09 -07:00
|
|
|
_internal_config_set(void *eng_data, EVGL_Surface *sfc, Evas_GL_Config *cfg)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
int i = 0, cfg_index = -1;
|
|
|
|
int color_bit = 0, depth_bit = 0, stencil_bit = 0, msaa_samples = 0;
|
2015-03-15 21:57:09 -07:00
|
|
|
int depth_size = 0;
|
|
|
|
Eina_Bool support_win_cfg = 1;
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
// Check if engine is valid
|
|
|
|
if (!evgl_engine)
|
|
|
|
{
|
|
|
|
ERR("Invalid EVGL Engine!");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Convert Config Format to bitmask friendly format
|
|
|
|
color_bit = (1 << cfg->color_format);
|
2015-03-15 21:57:09 -07:00
|
|
|
if (cfg->depth_bits)
|
|
|
|
{
|
|
|
|
depth_bit = (1 << (cfg->depth_bits-1));
|
|
|
|
depth_size = 8 * cfg->depth_bits;
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
if (cfg->stencil_bits) stencil_bit = (1 << (cfg->stencil_bits-1));
|
2013-01-06 22:16:18 -08:00
|
|
|
if (cfg->multisample_bits)
|
2013-05-02 03:06:10 -07:00
|
|
|
msaa_samples = evgl_engine->caps.msaa_samples[cfg->multisample_bits-1];
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2015-03-16 01:19:37 -07:00
|
|
|
try_again:
|
2012-09-24 00:41:27 -07:00
|
|
|
// Run through all the available formats and choose the first match
|
2013-05-02 03:06:10 -07:00
|
|
|
for (i = 0; i < evgl_engine->caps.num_fbo_fmts; ++i)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
// Check if the MSAA is supported. Fallback if not.
|
2013-05-02 03:06:10 -07:00
|
|
|
if ((msaa_samples) && (evgl_engine->caps.msaa_supported))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
if (msaa_samples > evgl_engine->caps.fbo_fmts[i].samples)
|
2012-09-24 00:41:27 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
if (color_bit & evgl_engine->caps.fbo_fmts[i].color_bit)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
if (depth_bit)
|
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!(depth_bit & evgl_engine->caps.fbo_fmts[i].depth_bit))
|
2012-09-24 00:41:27 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stencil_bit)
|
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!(stencil_bit & evgl_engine->caps.fbo_fmts[i].stencil_bit))
|
2012-09-24 00:41:27 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the surface format
|
2013-05-02 03:06:10 -07:00
|
|
|
sfc->color_ifmt = evgl_engine->caps.fbo_fmts[i].color_ifmt;
|
|
|
|
sfc->color_fmt = evgl_engine->caps.fbo_fmts[i].color_fmt;
|
|
|
|
sfc->depth_fmt = evgl_engine->caps.fbo_fmts[i].depth_fmt;
|
|
|
|
sfc->stencil_fmt = evgl_engine->caps.fbo_fmts[i].stencil_fmt;
|
|
|
|
sfc->depth_stencil_fmt = evgl_engine->caps.fbo_fmts[i].depth_stencil_fmt;
|
|
|
|
sfc->msaa_samples = evgl_engine->caps.fbo_fmts[i].samples;
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2015-03-15 21:57:09 -07:00
|
|
|
// Direct Rendering Option
|
|
|
|
if (((depth_bit > 0) || (stencil_bit > 0) || (msaa_samples > 0))
|
2015-02-24 02:05:39 -08:00
|
|
|
&& (evgl_engine->funcs->native_win_surface_config_check))
|
|
|
|
{
|
2015-03-15 21:57:09 -07:00
|
|
|
DBG("request to check win cfg with depth %d, stencil %d, msaa %d", depth_size, stencil_bit, msaa_samples);
|
|
|
|
support_win_cfg = evgl_engine->funcs->native_win_surface_config_check(eng_data, depth_size, stencil_bit, msaa_samples);
|
2015-02-24 02:05:39 -08:00
|
|
|
}
|
2014-09-01 04:22:12 -07:00
|
|
|
|
2015-03-15 21:57:09 -07:00
|
|
|
if ((sfc->direct_override) || support_win_cfg)
|
2015-02-24 02:05:39 -08:00
|
|
|
sfc->direct_fb_opt = !!(cfg->options_bits & EVAS_GL_OPTIONS_DIRECT);
|
2015-03-16 00:58:37 -07:00
|
|
|
else if (cfg->options_bits & EVAS_GL_OPTIONS_DIRECT)
|
|
|
|
{
|
|
|
|
const char *s1[] = { "", ":depth8", ":depth16", ":depth24", ":depth32" };
|
|
|
|
const char *s2[] = { "", ":stencil1", ":stencil2", ":stencil4", ":stencil8", ":stencil16" };
|
|
|
|
const char *s3[] = { "", ":msaa_low", ":msaa_mid", ":msaa_high" };
|
|
|
|
INF("Can not enable direct rendering with depth %d, stencil %d "
|
|
|
|
"and MSAA %d. When using Elementary GLView, try to set "
|
|
|
|
"the accel_preference to \"opengl%s%s%s\".",
|
|
|
|
depth_size, stencil_bit, msaa_samples,
|
|
|
|
s1[cfg->depth_bits], s2[cfg->stencil_bits], s3[cfg->multisample_bits]);
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2014-09-01 04:22:12 -07:00
|
|
|
// Extra flags for direct rendering
|
2014-09-03 19:42:01 -07:00
|
|
|
sfc->client_side_rotation = !!(cfg->options_bits & EVAS_GL_OPTIONS_CLIENT_SIDE_ROTATION);
|
2014-09-01 04:22:12 -07:00
|
|
|
sfc->alpha = (cfg->color_format == EVAS_GL_RGBA_8888);
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
cfg_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cfg_index < 0)
|
|
|
|
{
|
2015-03-16 00:58:37 -07:00
|
|
|
ERR("Unable to find a matching config format.");
|
2015-03-16 01:19:37 -07:00
|
|
|
if ((stencil_bit > 8) || (depth_size > 24))
|
2015-03-16 00:58:37 -07:00
|
|
|
{
|
|
|
|
INF("Please note that Evas GL might not support 32-bit depth or "
|
|
|
|
"16-bit stencil buffers, so depth24, stencil8 are the maximum "
|
|
|
|
"recommended values.");
|
2015-03-16 01:19:37 -07:00
|
|
|
if (depth_size > 24)
|
|
|
|
{
|
|
|
|
depth_bit = 4; // see DEPTH_BIT_24
|
|
|
|
depth_size = 24;
|
|
|
|
}
|
|
|
|
if (stencil_bit > 8) stencil_bit = 8; // see STENCIL_BIT_8
|
|
|
|
DBG("Fallback to depth:%d, stencil:%d", depth_size, stencil_bit);
|
|
|
|
goto try_again;
|
2015-03-16 00:58:37 -07:00
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-03-15 21:57:09 -07:00
|
|
|
DBG("-------------Evas GL Surface Config---------------");
|
2012-09-24 00:41:27 -07:00
|
|
|
DBG("Selected Config Index: %d", cfg_index);
|
|
|
|
DBG(" Color Format : %s", _glenum_string_get(sfc->color_fmt));
|
|
|
|
DBG(" Depth Format : %s", _glenum_string_get(sfc->depth_fmt));
|
|
|
|
DBG(" Stencil Format : %s", _glenum_string_get(sfc->stencil_fmt));
|
|
|
|
DBG(" D-Stencil Format : %s", _glenum_string_get(sfc->depth_stencil_fmt));
|
|
|
|
DBG(" MSAA Samples : %d", sfc->msaa_samples);
|
2015-02-24 02:05:39 -08:00
|
|
|
DBG(" Direct Option : %d%s", sfc->direct_fb_opt, sfc->direct_override ? " (override)" : "");
|
2014-09-03 19:42:01 -07:00
|
|
|
DBG(" Client-side Rot. : %d", sfc->client_side_rotation);
|
2015-03-15 21:57:09 -07:00
|
|
|
DBG("--------------------------------------------------");
|
2012-09-24 00:41:27 -07:00
|
|
|
sfc->cfg_index = cfg_index;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-05 03:03:37 -07:00
|
|
|
static int
|
2013-05-02 03:06:10 -07:00
|
|
|
_evgl_direct_renderable(EVGL_Resource *rsc, EVGL_Surface *sfc)
|
2012-10-05 03:03:37 -07:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
if (evgl_engine->direct_force_off) return 0;
|
|
|
|
if (rsc->id != evgl_engine->main_tid) return 0;
|
2012-10-05 03:03:37 -07:00
|
|
|
if (!sfc->direct_fb_opt) return 0;
|
2013-10-24 01:37:22 -07:00
|
|
|
if (!rsc->direct.enabled) return 0;
|
2012-10-05 03:03:37 -07:00
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
//---------------------------------------------------------------//
|
2012-11-20 20:59:52 -08:00
|
|
|
// Functions used by Evas GL module
|
2012-09-24 00:41:27 -07:00
|
|
|
//---------------------------------------------------------------//
|
|
|
|
EVGL_Resource *
|
2014-09-03 19:42:01 -07:00
|
|
|
_evgl_tls_resource_get(void)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
EVGL_Resource *rsc = NULL;
|
|
|
|
|
|
|
|
// Check if engine is valid
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!evgl_engine)
|
|
|
|
{
|
|
|
|
ERR("Invalid EVGL Engine!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
rsc = eina_tls_get(evgl_engine->resource_key);
|
|
|
|
|
|
|
|
if (!rsc)
|
|
|
|
return NULL;
|
|
|
|
else
|
|
|
|
return rsc;
|
|
|
|
}
|
|
|
|
|
|
|
|
EVGL_Resource *
|
|
|
|
_evgl_tls_resource_create(void *eng_data)
|
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
|
|
|
|
// Check if engine is valid
|
|
|
|
if (!evgl_engine)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Invalid EVGL Engine!");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create internal resources if it hasn't been created already
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!(rsc = _internal_resources_create(eng_data)))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
ERR("Error creating internal resources.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the resource in TLS
|
|
|
|
if (eina_tls_set(evgl_engine->resource_key, (void*)rsc) == EINA_TRUE)
|
|
|
|
{
|
|
|
|
// Add to the resource resource list for cleanup
|
|
|
|
LKL(evgl_engine->resource_lock);
|
|
|
|
rsc->id = evgl_engine->resource_count++;
|
|
|
|
evgl_engine->resource_list = eina_list_prepend(evgl_engine->resource_list, rsc);
|
|
|
|
LKU(evgl_engine->resource_lock);
|
|
|
|
return rsc;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ERR("Failed setting TLS Resource");
|
|
|
|
_internal_resources_destroy(eng_data, rsc);
|
|
|
|
return NULL;
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
void
|
|
|
|
_evgl_tls_resource_destroy(void *eng_data)
|
|
|
|
{
|
|
|
|
Eina_List *l;
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
|
|
|
|
// Check if engine is valid
|
|
|
|
if (!evgl_engine)
|
|
|
|
{
|
|
|
|
ERR("Invalid EVGL Engine!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-08-24 20:55:40 -07:00
|
|
|
if (!_evgl_tls_resource_get())
|
2013-05-02 03:06:10 -07:00
|
|
|
{
|
|
|
|
ERR("Error retrieving resource from TLS");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LKL(evgl_engine->resource_lock);
|
|
|
|
EINA_LIST_FOREACH(evgl_engine->resource_list, l, rsc)
|
|
|
|
{
|
|
|
|
_internal_resources_destroy(eng_data, rsc);
|
|
|
|
}
|
|
|
|
eina_list_free(evgl_engine->resource_list);
|
|
|
|
LKU(evgl_engine->resource_lock);
|
|
|
|
|
|
|
|
// Destroy TLS
|
|
|
|
if (evgl_engine->resource_key)
|
|
|
|
eina_tls_free(evgl_engine->resource_key);
|
|
|
|
evgl_engine->resource_key = 0;
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2014-09-01 20:52:52 -07:00
|
|
|
EAPI void * /* EVGL_Context */
|
|
|
|
evas_gl_common_current_context_get(void)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!(rsc = _evgl_tls_resource_get()))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("No current context set.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
else
|
2014-09-01 20:52:52 -07:00
|
|
|
return rsc->current_ctx;
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
2012-11-20 20:59:52 -08:00
|
|
|
int
|
2014-09-03 19:42:01 -07:00
|
|
|
_evgl_not_in_pixel_get(void)
|
2012-11-20 20:59:52 -08:00
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
2015-03-03 03:08:16 -08:00
|
|
|
EVGL_Context *ctx;
|
2012-11-20 20:59:52 -08:00
|
|
|
|
2015-03-03 03:08:16 -08:00
|
|
|
if (!(rsc=_evgl_tls_resource_get()))
|
|
|
|
return 1;
|
2014-12-09 04:36:45 -08:00
|
|
|
|
|
|
|
if (rsc->id != evgl_engine->main_tid)
|
|
|
|
return 0;
|
|
|
|
|
2015-03-03 03:08:16 -08:00
|
|
|
ctx = rsc->current_ctx;
|
2014-12-09 04:36:45 -08:00
|
|
|
if (!ctx || !ctx->current_sfc)
|
|
|
|
return 0;
|
|
|
|
|
2015-04-06 01:23:44 -07:00
|
|
|
// if indirect rendering, we don't care. eg. elm_glview's init cb
|
|
|
|
if (!ctx->current_sfc->direct_fb_opt)
|
|
|
|
return 0;
|
|
|
|
|
2015-03-03 03:08:16 -08:00
|
|
|
return !rsc->direct.in_get_pixels;
|
2012-11-20 20:59:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-09-03 19:42:01 -07:00
|
|
|
_evgl_direct_enabled(void)
|
2012-11-20 20:59:52 -08:00
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
EVGL_Surface *sfc;
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!(rsc=_evgl_tls_resource_get())) return 0;
|
2012-11-20 21:11:17 -08:00
|
|
|
if (!(rsc->current_ctx)) return 0;
|
2012-11-20 20:59:52 -08:00
|
|
|
if (!(sfc=rsc->current_ctx->current_sfc)) return 0;
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
return _evgl_direct_renderable(rsc, sfc);
|
2012-11-20 20:59:52 -08:00
|
|
|
}
|
|
|
|
|
2014-09-01 20:52:52 -07:00
|
|
|
EAPI void
|
|
|
|
evas_gl_common_error_set(void *data EINA_UNUSED, int error_enum)
|
2014-09-01 02:11:53 -07:00
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
|
|
|
|
if (!(rsc=_evgl_tls_resource_get()))
|
|
|
|
{
|
|
|
|
WRN("evgl: Unable to set error!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rsc->error_state = error_enum;
|
|
|
|
}
|
|
|
|
|
2014-09-01 20:52:52 -07:00
|
|
|
EAPI int
|
|
|
|
evas_gl_common_error_get(void *data EINA_UNUSED)
|
2014-09-01 02:11:53 -07:00
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
|
|
|
|
if (!(rsc=_evgl_tls_resource_get()))
|
|
|
|
{
|
|
|
|
WRN("evgl: Unable to get error!");
|
|
|
|
return EVAS_GL_NOT_INITIALIZED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rsc->error_state;
|
|
|
|
}
|
|
|
|
|
2014-09-19 01:44:56 -07:00
|
|
|
EVGLNative_Context
|
|
|
|
_evgl_native_context_get(Evas_GL_Context *ctx)
|
|
|
|
{
|
|
|
|
EVGL_Context *evglctx;
|
|
|
|
|
|
|
|
if (!glsym_evas_gl_native_context_get)
|
|
|
|
{
|
|
|
|
ERR("Engine can't get a pointer to the native context");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
evglctx = glsym_evas_gl_native_context_get(ctx);
|
|
|
|
if (!evglctx) return NULL;
|
|
|
|
return evglctx->context;
|
|
|
|
}
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
//---------------------------------------------------------------//
|
|
|
|
// Exported functions for evas_engine to use
|
|
|
|
|
|
|
|
// Initialize engine
|
|
|
|
// - Allocate the engine struct
|
|
|
|
// - Assign engine funcs form evas_engine
|
|
|
|
// - Create internal resources: internal context, surface for resource creation
|
|
|
|
// - Initialize extensions
|
|
|
|
// - Check surface capability
|
|
|
|
//
|
|
|
|
// This code should be called during eng_setup() in evas_engine
|
|
|
|
EVGL_Engine *
|
2014-07-11 06:10:53 -07:00
|
|
|
evgl_engine_init(void *eng_data, const EVGL_Interface *efunc)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2015-02-24 02:05:39 -08:00
|
|
|
int direct_off = 0, direct_soff = 0, debug_mode = 0;
|
2012-09-24 00:41:27 -07:00
|
|
|
char *s = NULL;
|
|
|
|
|
2012-10-31 05:57:21 -07:00
|
|
|
if (evgl_engine) return evgl_engine;
|
|
|
|
|
2012-10-05 03:03:37 -07:00
|
|
|
// Initialize Log Domain
|
|
|
|
if (_evas_gl_log_dom < 0)
|
2013-06-17 01:53:33 -07:00
|
|
|
_evas_gl_log_dom = eina_log_domain_register("EvasGL", EVAS_DEFAULT_LOG_COLOR);
|
2012-10-05 03:03:37 -07:00
|
|
|
if (_evas_gl_log_dom < 0)
|
|
|
|
{
|
|
|
|
EINA_LOG_ERR("Can not create a module log domain.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
// Store the Log Level
|
|
|
|
_evas_gl_log_level = eina_log_domain_level_get("EvasGL");
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Check the validity of the efunc
|
|
|
|
if ((!efunc) ||
|
|
|
|
(!efunc->surface_create) ||
|
|
|
|
(!efunc->context_create) ||
|
|
|
|
(!efunc->make_current))
|
|
|
|
{
|
|
|
|
ERR("Invalid Engine Functions for Evas GL Engine.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate engine
|
|
|
|
evgl_engine = calloc(1, sizeof(EVGL_Engine));
|
|
|
|
if (!evgl_engine)
|
|
|
|
{
|
|
|
|
ERR("Error allocating EVGL Engine. GL initialization failed.");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2014-09-01 00:50:19 -07:00
|
|
|
LKI(evgl_engine->resource_lock);
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Assign functions
|
2013-05-24 13:32:58 -07:00
|
|
|
evgl_engine->funcs = efunc;
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Initialize Resource TLS
|
|
|
|
if (eina_tls_new(&evgl_engine->resource_key) == EINA_FALSE)
|
|
|
|
{
|
|
|
|
ERR("Error creating tls key");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
DBG("TLS KEY created: %d", evgl_engine->resource_key);
|
|
|
|
|
2014-09-19 01:44:56 -07:00
|
|
|
// Link to evas_gl.c (this doesn't look great)
|
|
|
|
glsym_evas_gl_native_context_get = dlsym(RTLD_DEFAULT, "_evas_gl_native_context_get");
|
|
|
|
|
2014-10-24 05:25:08 -07:00
|
|
|
evgl_engine->safe_extensions = eina_hash_string_small_new(NULL);
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Initialize Extensions
|
|
|
|
if (efunc->proc_address_get && efunc->ext_string_get)
|
2014-10-28 20:56:00 -07:00
|
|
|
{
|
|
|
|
if (!evgl_api_ext_init(efunc->proc_address_get, efunc->ext_string_get(eng_data)))
|
|
|
|
{
|
|
|
|
ERR("Extensions failed to load. This shouldn't happen, Evas GL load fails.");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
else
|
2014-10-28 20:56:00 -07:00
|
|
|
ERR("Proc address get function not available. Extensions not initialized.");
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2013-07-08 06:30:41 -07:00
|
|
|
if (efunc->ext_string_get)
|
|
|
|
DBG("GLUE Extension String: %s", efunc->ext_string_get(eng_data));
|
2012-09-24 00:41:27 -07:00
|
|
|
DBG("GL Extension String: %s", glGetString(GL_EXTENSIONS));
|
|
|
|
|
|
|
|
// Surface Caps
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!_surface_cap_init(eng_data))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Error initializing surface cap");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2015-02-24 02:05:39 -08:00
|
|
|
// NOTE: Should we finally remove these variables?
|
|
|
|
// Check for Direct rendering override env var.
|
|
|
|
if ((s = getenv("EVAS_GL_DIRECT_OVERRIDE")))
|
|
|
|
{
|
|
|
|
WRN("EVAS_GL_DIRECT_OVERRIDE is set to '%s' for the whole application. "
|
|
|
|
"This should never be done except for debugging purposes.", s);
|
|
|
|
if (atoi(s) == 1)
|
|
|
|
evgl_engine->direct_override = 1;
|
|
|
|
}
|
|
|
|
|
2013-01-23 20:51:51 -08:00
|
|
|
// Check if Direct Rendering Memory Optimzation flag is on
|
|
|
|
// Creates resources on demand when it fallsback to fbo rendering
|
2015-02-24 02:05:39 -08:00
|
|
|
if ((s = getenv("EVAS_GL_DIRECT_MEM_OPT")))
|
|
|
|
{
|
|
|
|
WRN("EVAS_GL_DIRECT_MEM_OPT is set to '%s' for the whole application. "
|
|
|
|
"This should never be done except for debugging purposes.", s);
|
|
|
|
if (atoi(s) == 1)
|
|
|
|
evgl_engine->direct_mem_opt = 1;
|
|
|
|
}
|
2014-12-09 04:36:45 -08:00
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Check if Direct Rendering Override Force Off flag is on
|
|
|
|
s = getenv("EVAS_GL_DIRECT_OVERRIDE_FORCE_OFF");
|
|
|
|
if (s) direct_off = atoi(s);
|
|
|
|
if (direct_off == 1)
|
2013-06-17 01:53:33 -07:00
|
|
|
evgl_engine->direct_force_off = 1;
|
|
|
|
|
|
|
|
// Check if Direct Rendering Override Force Off flag is on
|
|
|
|
s = getenv("EVAS_GL_DIRECT_SCISSOR_OFF");
|
|
|
|
if (s) direct_soff = atoi(s);
|
|
|
|
if (direct_soff == 1)
|
|
|
|
evgl_engine->direct_scissor_off = 1;
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2012-10-05 03:03:37 -07:00
|
|
|
// Check if API Debug mode is on
|
|
|
|
s = getenv("EVAS_GL_API_DEBUG");
|
|
|
|
if (s) debug_mode = atoi(s);
|
|
|
|
if (debug_mode == 1)
|
2013-06-17 01:53:33 -07:00
|
|
|
evgl_engine->api_debug_mode = 1;
|
2012-10-05 03:03:37 -07:00
|
|
|
|
|
|
|
// Maint Thread ID (get tid not available in eina thread yet)
|
2012-09-24 00:41:27 -07:00
|
|
|
evgl_engine->main_tid = 0;
|
|
|
|
|
|
|
|
// Clear Function Pointers
|
2014-12-02 18:44:09 -08:00
|
|
|
if (!gl_funcs) gl_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
return evgl_engine;
|
|
|
|
|
|
|
|
error:
|
2015-03-04 23:16:11 -08:00
|
|
|
ERR("Failed to initialize EvasGL!");
|
2012-09-24 00:41:27 -07:00
|
|
|
if (evgl_engine)
|
2014-02-13 02:19:59 -08:00
|
|
|
{
|
2014-10-24 05:25:08 -07:00
|
|
|
eina_hash_free(evgl_engine->safe_extensions);
|
2014-02-13 02:19:59 -08:00
|
|
|
if (evgl_engine->resource_key)
|
|
|
|
eina_tls_free(evgl_engine->resource_key);
|
2014-09-01 00:50:19 -07:00
|
|
|
LKD(evgl_engine->resource_lock);
|
2014-02-13 02:19:59 -08:00
|
|
|
free(evgl_engine);
|
|
|
|
}
|
2013-06-26 02:40:44 -07:00
|
|
|
evgl_engine = NULL;
|
2012-09-24 00:41:27 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Terminate engine and all the resources
|
|
|
|
// - destroy all internal resources
|
|
|
|
// - free allocated engine struct
|
2013-10-24 01:37:22 -07:00
|
|
|
void
|
2013-05-24 13:32:58 -07:00
|
|
|
evgl_engine_shutdown(void *eng_data)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
// Check if engine is valid
|
2014-09-03 19:42:01 -07:00
|
|
|
if (!evgl_engine)
|
|
|
|
{
|
2015-03-04 23:16:11 -08:00
|
|
|
EINA_LOG_INFO("EvasGL Engine is not initialized.");
|
2014-09-03 19:42:01 -07:00
|
|
|
return;
|
|
|
|
}
|
2012-10-05 03:03:37 -07:00
|
|
|
|
|
|
|
// Log
|
|
|
|
eina_log_domain_unregister(_evas_gl_log_dom);
|
|
|
|
_evas_gl_log_dom = -1;
|
2013-01-06 22:16:18 -08:00
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Destroy internal resources
|
2013-05-02 03:06:10 -07:00
|
|
|
_evgl_tls_resource_destroy(eng_data);
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2014-09-01 00:50:19 -07:00
|
|
|
LKD(evgl_engine->resource_lock);
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Free engine
|
2013-05-02 03:06:10 -07:00
|
|
|
free(evgl_engine);
|
2012-09-24 00:41:27 -07:00
|
|
|
evgl_engine = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_surface_create(void *eng_data, Evas_GL_Config *cfg, int w, int h)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-06-28 06:23:57 -07:00
|
|
|
EVGL_Surface *sfc = NULL;
|
2014-11-18 00:37:25 -08:00
|
|
|
Eina_Bool dbg;
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Check if engine is valid
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!evgl_engine)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Invalid EVGL Engine!");
|
2014-09-01 20:52:52 -07:00
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ACCESS);
|
2012-09-24 00:41:27 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
2014-11-18 00:37:25 -08:00
|
|
|
dbg = evgl_engine->api_debug_mode;
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
if (!cfg)
|
|
|
|
{
|
|
|
|
ERR("Invalid Config!");
|
2014-09-01 20:52:52 -07:00
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONFIG);
|
2012-09-24 00:41:27 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the size of the surface
|
2013-05-02 03:06:10 -07:00
|
|
|
if ((w > evgl_engine->caps.max_w) || (h > evgl_engine->caps.max_h))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Requested surface size [%d, %d] is greater than max supported size [%d, %d]",
|
2013-05-02 03:06:10 -07:00
|
|
|
w, h, evgl_engine->caps.max_w, evgl_engine->caps.max_h);
|
2014-09-01 20:52:52 -07:00
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_PARAMETER);
|
2012-09-24 00:41:27 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate surface structure
|
|
|
|
sfc = calloc(1, sizeof(EVGL_Surface));
|
|
|
|
if (!sfc)
|
|
|
|
{
|
|
|
|
ERR("Surface allocation failed.");
|
2014-09-01 20:52:52 -07:00
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
|
2012-09-24 00:41:27 -07:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set surface info
|
|
|
|
sfc->w = w;
|
|
|
|
sfc->h = h;
|
|
|
|
|
2015-02-24 02:05:39 -08:00
|
|
|
// Extra options for DR
|
|
|
|
if (cfg->options_bits & EVAS_GL_OPTIONS_DIRECT_MEMORY_OPTIMIZE)
|
|
|
|
{
|
|
|
|
DBG("Setting DIRECT_MEMORY_OPTIMIZE bit");
|
|
|
|
sfc->direct_mem_opt = EINA_TRUE;
|
|
|
|
}
|
|
|
|
else if (evgl_engine->direct_mem_opt == 1)
|
|
|
|
sfc->direct_mem_opt = EINA_TRUE;
|
|
|
|
|
|
|
|
if (cfg->options_bits & EVAS_GL_OPTIONS_DIRECT_OVERRIDE)
|
|
|
|
{
|
|
|
|
DBG("Setting DIRECT_OVERRIDE bit");
|
|
|
|
sfc->direct_override = EINA_TRUE;
|
|
|
|
}
|
|
|
|
else if (evgl_engine->direct_override == 1)
|
|
|
|
sfc->direct_override = EINA_TRUE;
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Set the internal config value
|
2015-03-15 21:57:09 -07:00
|
|
|
if (!_internal_config_set(eng_data, sfc, cfg))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Unsupported Format!");
|
2014-09-01 20:52:52 -07:00
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONFIG);
|
2012-09-24 00:41:27 -07:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
// Keep track of all the created surfaces
|
2014-09-01 00:50:19 -07:00
|
|
|
LKL(evgl_engine->resource_lock);
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_engine->surfaces = eina_list_prepend(evgl_engine->surfaces, sfc);
|
2014-11-18 00:37:25 -08:00
|
|
|
LKU(evgl_engine->resource_lock);
|
2014-09-03 19:42:01 -07:00
|
|
|
|
2014-11-18 00:37:25 -08:00
|
|
|
if (dbg) DBG("Created surface sfc %p (eng %p)", sfc, eng_data);
|
|
|
|
|
2015-02-24 21:58:19 -08:00
|
|
|
_surface_context_list_print();
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
return sfc;
|
|
|
|
|
|
|
|
error:
|
|
|
|
if (sfc) free(sfc);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-09-19 01:32:26 -07:00
|
|
|
void *
|
|
|
|
evgl_pbuffer_surface_create(void *eng_data, Evas_GL_Config *cfg,
|
|
|
|
int w, int h, const int *attrib_list)
|
|
|
|
{
|
|
|
|
EVGL_Surface *sfc = NULL;
|
|
|
|
void *pbuffer;
|
2014-11-18 00:37:25 -08:00
|
|
|
Eina_Bool dbg;
|
2014-09-19 01:32:26 -07:00
|
|
|
|
|
|
|
// Check if engine is valid
|
|
|
|
if (!evgl_engine)
|
|
|
|
{
|
|
|
|
ERR("Invalid EVGL Engine!");
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ACCESS);
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-11-18 00:37:25 -08:00
|
|
|
dbg = evgl_engine->api_debug_mode;
|
2014-09-19 01:32:26 -07:00
|
|
|
|
|
|
|
if (!cfg)
|
|
|
|
{
|
|
|
|
ERR("Invalid Config!");
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONFIG);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!evgl_engine->funcs->pbuffer_surface_create)
|
|
|
|
{
|
|
|
|
ERR("Engine can not create PBuffers");
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_NOT_INITIALIZED);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Allocate surface structure
|
|
|
|
sfc = calloc(1, sizeof(EVGL_Surface));
|
|
|
|
if (!sfc)
|
|
|
|
{
|
|
|
|
ERR("Surface allocation failed.");
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfc->w = w;
|
|
|
|
sfc->h = h;
|
|
|
|
sfc->pbuffer.color_fmt = cfg->color_format;
|
|
|
|
sfc->pbuffer.is_pbuffer = EINA_TRUE;
|
|
|
|
|
|
|
|
// Set the context current with resource context/surface
|
|
|
|
if (!_internal_resource_make_current(eng_data, NULL))
|
|
|
|
{
|
|
|
|
ERR("Error doing an internal resource make current");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the surface is defined as RGB or RGBA, then create an FBO
|
|
|
|
if (sfc->pbuffer.color_fmt != EVAS_GL_NO_FBO)
|
|
|
|
{
|
|
|
|
// Set the internal config value
|
2015-03-15 21:57:09 -07:00
|
|
|
if (!_internal_config_set(eng_data, sfc, cfg))
|
2014-09-19 01:32:26 -07:00
|
|
|
{
|
|
|
|
ERR("Unsupported Format!");
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONFIG);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create internal buffers
|
|
|
|
if (!_surface_buffers_create(sfc))
|
|
|
|
{
|
|
|
|
ERR("Unable Create Specificed Surfaces.");
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
|
|
|
|
goto error;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Allocate resources for fallback unless the flag is on
|
2015-02-24 02:05:39 -08:00
|
|
|
// Note: we don't care about sfc->direct_mem_opt, as DR makes no sense with PBuffer.
|
2014-09-19 01:32:26 -07:00
|
|
|
if (!evgl_engine->direct_mem_opt)
|
|
|
|
{
|
|
|
|
if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 0))
|
|
|
|
{
|
|
|
|
ERR("Unable Create Allocate Memory for Surface.");
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not calling make_current
|
|
|
|
|
|
|
|
pbuffer = evgl_engine->funcs->pbuffer_surface_create
|
|
|
|
(eng_data, sfc, attrib_list);
|
|
|
|
|
|
|
|
if (!pbuffer)
|
|
|
|
{
|
|
|
|
ERR("Engine failed to create a PBuffer");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
sfc->pbuffer.native_surface = pbuffer;
|
|
|
|
|
2014-11-18 00:37:25 -08:00
|
|
|
if (dbg) DBG("Calling make_current(NULL, NULL)");
|
2014-09-19 01:32:26 -07:00
|
|
|
if (!evgl_engine->funcs->make_current(eng_data, NULL, NULL, 0))
|
|
|
|
{
|
|
|
|
ERR("Error doing make_current(NULL, NULL).");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Keep track of all the created surfaces
|
|
|
|
LKL(evgl_engine->resource_lock);
|
|
|
|
evgl_engine->surfaces = eina_list_prepend(evgl_engine->surfaces, sfc);
|
|
|
|
LKU(evgl_engine->resource_lock);
|
|
|
|
|
2014-11-18 00:37:25 -08:00
|
|
|
if (dbg) DBG("Created PBuffer surface sfc %p:%p (eng %p)", sfc, pbuffer, eng_data);
|
|
|
|
|
2014-09-19 01:32:26 -07:00
|
|
|
return sfc;
|
|
|
|
|
|
|
|
error:
|
|
|
|
free(sfc);
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
int
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_surface_destroy(void *eng_data, EVGL_Surface *sfc)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
2014-11-18 00:37:25 -08:00
|
|
|
Eina_Bool dbg;
|
|
|
|
|
|
|
|
// FIXME: This does some make_current(0,0) which may have side effects
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Check input parameter
|
2013-05-02 03:06:10 -07:00
|
|
|
if ((!evgl_engine) || (!sfc))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
ERR("Invalid input data. Engine: %p Surface:%p", evgl_engine, sfc);
|
2012-09-24 00:41:27 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve the resource object
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!(rsc = _evgl_tls_resource_get()))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Error retrieving resource from TLS");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-11-18 00:37:25 -08:00
|
|
|
if ((dbg = evgl_engine->api_debug_mode))
|
|
|
|
DBG("Destroying surface sfc %p (eng %p)", sfc, eng_data);
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
if ((rsc->current_ctx) && (rsc->current_ctx->current_sfc == sfc) )
|
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
if (evgl_engine->api_debug_mode)
|
2012-10-05 03:03:37 -07:00
|
|
|
{
|
|
|
|
ERR("The surface is still current before it's being destroyed.");
|
|
|
|
ERR("Doing make_current(NULL, NULL)");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
WRN("The surface is still current before it's being destroyed.");
|
|
|
|
WRN("Doing make_current(NULL, NULL)");
|
|
|
|
}
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_make_current(eng_data, NULL, NULL);
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
2015-04-14 04:55:50 -07:00
|
|
|
if (sfc->current_ctx && sfc->current_ctx->current_sfc == sfc)
|
|
|
|
sfc->current_ctx->current_sfc = NULL;
|
|
|
|
|
2014-09-19 01:32:26 -07:00
|
|
|
if (!sfc->pbuffer.native_surface)
|
2013-01-23 20:51:51 -08:00
|
|
|
{
|
2014-09-19 01:32:26 -07:00
|
|
|
// Set the context current with resource context/surface
|
|
|
|
if (!_internal_resource_make_current(eng_data, NULL))
|
|
|
|
{
|
|
|
|
ERR("Error doing an internal resource make current");
|
|
|
|
return 0;
|
|
|
|
}
|
2013-01-23 20:51:51 -08:00
|
|
|
}
|
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
// Destroy indirect surface
|
|
|
|
if (sfc->indirect)
|
2014-09-22 23:33:16 -07:00
|
|
|
{
|
|
|
|
int ret;
|
2015-03-09 01:17:19 -07:00
|
|
|
if (dbg) DBG("sfc %p is used for indirect rendering", sfc);
|
2014-11-18 00:37:25 -08:00
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
if (!evgl_engine->funcs->indirect_surface_destroy)
|
2014-09-22 23:33:16 -07:00
|
|
|
{
|
2015-03-09 01:17:19 -07:00
|
|
|
ERR("Error destroying indirect surface");
|
2014-09-22 23:33:16 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
DBG("Destroying special surface used for indirect rendering");
|
|
|
|
ret = evgl_engine->funcs->indirect_surface_destroy(eng_data, sfc);
|
2014-09-22 23:33:16 -07:00
|
|
|
|
2015-02-24 21:58:19 -08:00
|
|
|
if (!ret)
|
|
|
|
{
|
2015-03-09 01:17:19 -07:00
|
|
|
ERR("Engine failed to destroy indirect surface.");
|
2015-02-24 21:58:19 -08:00
|
|
|
return ret;
|
|
|
|
}
|
2014-09-22 23:33:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
// Destroy created buffers
|
2013-01-23 20:51:51 -08:00
|
|
|
if (!_surface_buffers_destroy(sfc))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-01-21 23:00:12 -08:00
|
|
|
ERR("Error deleting surface resources.");
|
2012-09-24 00:41:27 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-19 01:32:26 -07:00
|
|
|
// Destroy PBuffer surfaces
|
|
|
|
if (sfc->pbuffer.native_surface)
|
|
|
|
{
|
|
|
|
int ret;
|
2014-11-18 00:37:25 -08:00
|
|
|
if (dbg) DBG("Surface sfc %p is a pbuffer: %p", sfc, sfc->pbuffer.native_surface);
|
2014-09-19 01:32:26 -07:00
|
|
|
|
2014-10-06 05:26:11 -07:00
|
|
|
ret = evgl_engine->funcs->pbuffer_surface_destroy(eng_data, sfc->pbuffer.native_surface);
|
2014-09-19 01:32:26 -07:00
|
|
|
LKL(evgl_engine->resource_lock);
|
|
|
|
evgl_engine->surfaces = eina_list_remove(evgl_engine->surfaces, sfc);
|
|
|
|
LKU(evgl_engine->resource_lock);
|
|
|
|
free(sfc);
|
|
|
|
|
|
|
|
if (!ret) ERR("Engine failed to destroy a PBuffer.");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2014-11-18 00:37:25 -08:00
|
|
|
if (dbg) DBG("Calling make_current(NULL, NULL)");
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!evgl_engine->funcs->make_current(eng_data, NULL, NULL, 0))
|
2013-01-23 20:51:51 -08:00
|
|
|
{
|
|
|
|
ERR("Error doing make_current(NULL, NULL).");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
// Remove it from the list
|
2014-09-01 00:50:19 -07:00
|
|
|
LKL(evgl_engine->resource_lock);
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_engine->surfaces = eina_list_remove(evgl_engine->surfaces, sfc);
|
2014-11-18 00:37:25 -08:00
|
|
|
LKU(evgl_engine->resource_lock);
|
2014-09-03 19:42:01 -07:00
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
free(sfc);
|
|
|
|
sfc = NULL;
|
|
|
|
|
2015-02-24 21:58:19 -08:00
|
|
|
_surface_context_list_print();
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
2014-09-22 03:15:37 -07:00
|
|
|
evgl_context_create(void *eng_data, EVGL_Context *share_ctx,
|
|
|
|
Evas_GL_Context_Version version)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
EVGL_Context *ctx = NULL;
|
2015-03-09 01:25:20 -07:00
|
|
|
EVGL_Resource *rsc = NULL;
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Check the input
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!evgl_engine)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Invalid EVGL Engine!");
|
2014-09-01 20:52:52 -07:00
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ACCESS);
|
2012-09-24 00:41:27 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-09-22 03:15:37 -07:00
|
|
|
if ((version < EVAS_GL_GLES_1_X) || (version > EVAS_GL_GLES_3_X))
|
|
|
|
{
|
|
|
|
ERR("Invalid context version number %d", version);
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_PARAMETER);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-11-18 00:37:25 -08:00
|
|
|
if (evgl_engine->api_debug_mode)
|
|
|
|
DBG("Creating context GLESv%d (eng = %p, shctx = %p)", version, eng_data, share_ctx);
|
|
|
|
|
2015-03-09 01:25:20 -07:00
|
|
|
if (!(rsc = _evgl_tls_resource_get()))
|
|
|
|
{
|
|
|
|
ERR("Error creating resources in tls.");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Allocate context object
|
|
|
|
ctx = calloc(1, sizeof(EVGL_Context));
|
|
|
|
if (!ctx)
|
|
|
|
{
|
|
|
|
ERR("Error allocating context object.");
|
2014-09-01 20:52:52 -07:00
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
|
2012-09-24 00:41:27 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-12-09 01:02:20 -08:00
|
|
|
// Set default values
|
2014-09-22 23:33:16 -07:00
|
|
|
ctx->version = version;
|
2014-12-09 01:02:20 -08:00
|
|
|
ctx->scissor_coord[0] = 0;
|
|
|
|
ctx->scissor_coord[1] = 0;
|
|
|
|
ctx->scissor_coord[2] = evgl_engine->caps.max_w;
|
|
|
|
ctx->scissor_coord[3] = evgl_engine->caps.max_h;
|
2014-09-22 23:33:16 -07:00
|
|
|
|
|
|
|
// Call engine create context
|
2012-09-24 00:41:27 -07:00
|
|
|
if (share_ctx)
|
2014-09-22 03:15:37 -07:00
|
|
|
ctx->context = evgl_engine->funcs->context_create(eng_data, share_ctx->context, version);
|
2012-09-24 00:41:27 -07:00
|
|
|
else
|
2014-09-22 03:15:37 -07:00
|
|
|
ctx->context = evgl_engine->funcs->context_create(eng_data, NULL, version);
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Call engine create context
|
2014-02-13 02:38:13 -08:00
|
|
|
if (!ctx->context)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Error creating context from the Engine.");
|
|
|
|
free(ctx);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
// Keep track of all the created context
|
2014-09-01 00:50:19 -07:00
|
|
|
LKL(evgl_engine->resource_lock);
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_engine->contexts = eina_list_prepend(evgl_engine->contexts, ctx);
|
2014-09-01 00:50:19 -07:00
|
|
|
LKU(evgl_engine->resource_lock);
|
2013-01-21 23:00:12 -08:00
|
|
|
|
2014-11-18 00:37:25 -08:00
|
|
|
if (evgl_engine->api_debug_mode)
|
|
|
|
DBG("Created ctx %p", ctx);
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_context_destroy(void *eng_data, EVGL_Context *ctx)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2014-11-18 00:37:25 -08:00
|
|
|
Eina_Bool dbg;
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Check the input
|
2013-05-02 03:06:10 -07:00
|
|
|
if ((!evgl_engine) || (!ctx))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
ERR("Invalid input data. Engine: %p Context:%p", evgl_engine, ctx);
|
2012-09-24 00:41:27 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2014-11-18 00:37:25 -08:00
|
|
|
dbg = evgl_engine->api_debug_mode;
|
|
|
|
|
|
|
|
// FIXME: this calls make_current(0,0) which probably shouldn't be the case
|
|
|
|
// if the context is not current (?)
|
|
|
|
|
|
|
|
if (dbg) DBG("Destroying context (eng = %p, ctx = %p)", eng_data, ctx);
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2015-04-14 04:55:50 -07:00
|
|
|
if (ctx->current_sfc && (ctx->current_sfc->current_ctx == ctx))
|
|
|
|
ctx->current_sfc->current_ctx = NULL;
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Set the context current with resource context/surface
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!_internal_resource_make_current(eng_data, NULL))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Error doing an internal resource make current");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete the FBO
|
|
|
|
if (ctx->surface_fbo)
|
|
|
|
glDeleteFramebuffers(1, &ctx->surface_fbo);
|
|
|
|
|
|
|
|
// Unset the currrent context
|
2014-11-18 00:37:25 -08:00
|
|
|
if (dbg) DBG("Calling make_current(NULL, NULL)");
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!evgl_engine->funcs->make_current(eng_data, NULL, NULL, 0))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Error doing make_current(NULL, NULL).");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
// Destroy indirect rendering context
|
|
|
|
if (ctx->indirect_context &&
|
|
|
|
!evgl_engine->funcs->context_destroy(eng_data, ctx->indirect_context))
|
2015-02-24 03:54:55 -08:00
|
|
|
{
|
2015-03-09 01:17:19 -07:00
|
|
|
ERR("Error destroying the indirect context.");
|
2015-02-24 03:54:55 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Destroy engine context
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!evgl_engine->funcs->context_destroy(eng_data, ctx->context))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Error destroying the engine context.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-21 23:00:12 -08:00
|
|
|
// Remove it from the list
|
2014-09-01 00:50:19 -07:00
|
|
|
LKL(evgl_engine->resource_lock);
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_engine->contexts = eina_list_remove(evgl_engine->contexts, ctx);
|
2014-09-01 00:50:19 -07:00
|
|
|
LKU(evgl_engine->resource_lock);
|
2013-01-21 23:00:12 -08:00
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Free context
|
|
|
|
free(ctx);
|
|
|
|
ctx = NULL;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_make_current(void *eng_data, EVGL_Surface *sfc, EVGL_Context *ctx)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2014-11-18 00:37:25 -08:00
|
|
|
Eina_Bool dbg = EINA_FALSE;
|
2012-09-24 00:41:27 -07:00
|
|
|
EVGL_Resource *rsc;
|
|
|
|
int curr_fbo = 0;
|
|
|
|
|
|
|
|
// Check the input validity. If either sfc or ctx is NULL, it's also error.
|
2013-05-02 03:06:10 -07:00
|
|
|
if ( (!evgl_engine) ||
|
2012-09-24 00:41:27 -07:00
|
|
|
((!sfc) && ctx) ||
|
|
|
|
(sfc && (!ctx)) )
|
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
ERR("Invalid Inputs. Engine: %p Surface: %p Context: %p!", evgl_engine, sfc, ctx);
|
2014-09-01 20:52:52 -07:00
|
|
|
if(!sfc) evas_gl_common_error_set(eng_data, EVAS_GL_BAD_SURFACE);
|
|
|
|
if(!ctx) evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
|
2012-09-24 00:41:27 -07:00
|
|
|
return 0;
|
|
|
|
}
|
2013-01-06 22:16:18 -08:00
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
// Get TLS Resources
|
2014-11-18 00:37:25 -08:00
|
|
|
rsc = _evgl_tls_resource_get();
|
|
|
|
|
|
|
|
// Abuse debug mode - extra tracing for make_current and friends
|
|
|
|
dbg = evgl_engine->api_debug_mode;
|
|
|
|
if (dbg) DBG("(eng = %p, sfc = %p, ctx = %p), rsc = %p", eng_data, sfc, ctx, rsc);
|
|
|
|
|
2014-11-18 01:37:59 -08:00
|
|
|
if (!rsc)
|
|
|
|
{
|
2015-03-13 00:31:54 -07:00
|
|
|
DBG("Creating new TLS for this thread: %lu", (unsigned long)eina_thread_self());
|
2014-11-18 01:37:59 -08:00
|
|
|
rsc = _evgl_tls_resource_create(eng_data);
|
|
|
|
if (!rsc) return 0;
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
|
|
|
|
// Unset
|
|
|
|
if ((!sfc) && (!ctx))
|
|
|
|
{
|
2014-02-14 09:33:47 -08:00
|
|
|
if (rsc->current_ctx)
|
|
|
|
{
|
|
|
|
if (rsc->direct.partial.enabled)
|
|
|
|
evgl_direct_partial_render_end();
|
2014-12-09 01:02:20 -08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2014-02-14 09:33:47 -08:00
|
|
|
}
|
|
|
|
|
2014-11-18 00:37:25 -08:00
|
|
|
if (dbg) DBG("Calling make_current(NULL, NULL)");
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!evgl_engine->funcs->make_current(eng_data, NULL, NULL, 0))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
ERR("Error doing make_current(NULL, NULL).");
|
|
|
|
return 0;
|
|
|
|
}
|
2014-11-18 00:37:25 -08:00
|
|
|
|
2014-11-18 01:37:59 -08:00
|
|
|
// FIXME -- What is this "FIXME" about?
|
2012-09-24 00:41:27 -07:00
|
|
|
if (rsc->current_ctx)
|
|
|
|
{
|
|
|
|
rsc->current_ctx->current_sfc = NULL;
|
|
|
|
rsc->current_ctx = NULL;
|
2013-05-02 03:06:10 -07:00
|
|
|
rsc->current_eng = NULL;
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
2014-11-18 00:37:25 -08:00
|
|
|
if (dbg) DBG("Call to make_current(NULL, NULL) was successful.");
|
2012-09-24 00:41:27 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2014-02-14 09:33:47 -08:00
|
|
|
// Disable partial rendering for previous context
|
|
|
|
if ((rsc->current_ctx) && (rsc->current_ctx != ctx))
|
|
|
|
{
|
|
|
|
evas_gl_common_tiling_done(NULL);
|
|
|
|
rsc->current_ctx->partial_render = 0;
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2015-03-09 01:25:20 -07:00
|
|
|
// Do a make current
|
|
|
|
if (!_internal_resource_make_current(eng_data, ctx))
|
|
|
|
{
|
|
|
|
ERR("Error doing a make current with internal surface. Context: %p", ctx);
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_CONTEXT);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
sfc->current_ctx = ctx;
|
|
|
|
rsc->current_ctx = ctx;
|
|
|
|
rsc->current_eng = eng_data;
|
|
|
|
|
|
|
|
// Check whether extensions are supported for the current context version
|
|
|
|
// to use fbo & egl image passing to evas
|
|
|
|
if (!ctx->extension_checked)
|
|
|
|
{
|
|
|
|
if (!evgl_api_get(ctx->version))
|
|
|
|
{
|
|
|
|
ERR("Unable to get the list of GL APIs for version %d", ctx->version);
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_NOT_INITIALIZED);
|
|
|
|
return 0;
|
|
|
|
}
|
2015-03-09 04:41:58 -07:00
|
|
|
|
2015-03-09 01:25:20 -07:00
|
|
|
if (!_context_ext_check(ctx))
|
|
|
|
{
|
|
|
|
ERR("Unable to check required extension for the current context");
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_NOT_INITIALIZED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sfc->color_buf && !_surface_buffers_create(sfc))
|
|
|
|
{
|
|
|
|
ERR("Unable to create specified surfaces.");
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
2013-01-23 20:51:51 -08:00
|
|
|
// Allocate or free resources depending on what mode (direct of fbo) it's
|
|
|
|
// running only if the env var EVAS_GL_DIRECT_MEM_OPT is set.
|
2013-05-02 03:06:10 -07:00
|
|
|
if (evgl_engine->direct_mem_opt)
|
2013-01-21 23:00:12 -08:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
if (_evgl_direct_renderable(rsc, sfc))
|
2013-01-21 23:00:12 -08:00
|
|
|
{
|
2014-11-26 21:45:34 -08:00
|
|
|
if (dbg) DBG("sfc %p is direct renderable (has buffers: %d).", sfc, (int) sfc->buffers_allocated);
|
2014-11-18 00:37:25 -08:00
|
|
|
|
2013-01-23 20:51:51 -08:00
|
|
|
// Destroy created resources
|
|
|
|
if (sfc->buffers_allocated)
|
2013-01-21 23:00:12 -08:00
|
|
|
{
|
2013-09-17 01:22:26 -07:00
|
|
|
if (!_surface_buffers_allocate(eng_data, sfc, 0, 0, 1))
|
2013-01-23 20:51:51 -08:00
|
|
|
{
|
|
|
|
ERR("Unable to destroy surface buffers!");
|
2014-09-01 20:52:52 -07:00
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
|
2013-01-23 20:51:51 -08:00
|
|
|
return 0;
|
2013-02-11 07:03:56 -08:00
|
|
|
}
|
2013-01-23 20:51:51 -08:00
|
|
|
sfc->buffers_allocated = 0;
|
|
|
|
}
|
2013-01-21 23:00:12 -08:00
|
|
|
}
|
2013-01-23 20:51:51 -08:00
|
|
|
else
|
2013-01-21 23:00:12 -08:00
|
|
|
{
|
2014-02-14 09:33:47 -08:00
|
|
|
if (evgl_engine->direct_override)
|
|
|
|
{
|
|
|
|
DBG("Not creating fallback surfaces even though it should. Use at OWN discretion!");
|
|
|
|
}
|
|
|
|
else
|
2013-01-21 23:00:12 -08:00
|
|
|
{
|
2014-02-14 09:33:47 -08:00
|
|
|
// Create internal buffers if not yet created
|
|
|
|
if (!sfc->buffers_allocated)
|
2013-01-23 20:51:51 -08:00
|
|
|
{
|
2014-11-18 00:37:25 -08:00
|
|
|
if (dbg) DBG("Allocating buffers for sfc %p", sfc);
|
2014-02-14 09:33:47 -08:00
|
|
|
if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 1))
|
|
|
|
{
|
|
|
|
ERR("Unable Create Specificed Surfaces. Unsupported format!");
|
2014-09-01 20:52:52 -07:00
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
|
2014-02-14 09:33:47 -08:00
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
sfc->buffers_allocated = 1;
|
2013-05-14 07:45:22 -07:00
|
|
|
}
|
2013-01-23 20:51:51 -08:00
|
|
|
}
|
2013-01-21 23:00:12 -08:00
|
|
|
}
|
|
|
|
}
|
2015-03-09 01:25:20 -07:00
|
|
|
else
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2015-03-09 01:25:20 -07:00
|
|
|
if (!sfc->buffers_allocated)
|
|
|
|
{
|
|
|
|
if (!_surface_buffers_allocate(eng_data, sfc, sfc->w, sfc->h, 0))
|
|
|
|
{
|
|
|
|
ERR("Unable Create Allocate Memory for Surface.");
|
|
|
|
evas_gl_common_error_set(eng_data, EVAS_GL_BAD_ALLOC);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
sfc->buffers_allocated = 1;
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
2015-03-13 00:31:54 -07:00
|
|
|
if (!ctx->fbo_image_supported)
|
2014-09-22 23:33:16 -07:00
|
|
|
{
|
2015-03-09 01:17:19 -07:00
|
|
|
if (dbg) DBG("ctx %p is GLES %d", ctx, ctx->version);
|
2014-09-22 23:33:16 -07:00
|
|
|
if (_evgl_direct_renderable(rsc, sfc))
|
|
|
|
{
|
2015-03-09 01:17:19 -07:00
|
|
|
// Transition from indirect rendering to direct rendering
|
2015-02-24 03:54:55 -08:00
|
|
|
if (!rsc->direct.rendered)
|
|
|
|
{
|
|
|
|
// Restore viewport and scissor test to direct rendering mode
|
|
|
|
glViewport(ctx->viewport_direct[0], ctx->viewport_direct[1], ctx->viewport_direct[2], ctx->viewport_direct[3]);
|
|
|
|
if ((ctx->direct_scissor) && (!ctx->scissor_enabled))
|
|
|
|
glEnable(GL_SCISSOR_TEST);
|
|
|
|
}
|
2014-11-18 00:37:25 -08:00
|
|
|
if (dbg) DBG("sfc %p is direct renderable.", sfc);
|
2014-09-22 23:33:16 -07:00
|
|
|
rsc->direct.rendered = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-03-09 01:17:19 -07:00
|
|
|
if (!ctx->indirect_context)
|
2015-02-24 03:54:55 -08:00
|
|
|
{
|
2015-03-09 01:17:19 -07:00
|
|
|
ctx->indirect_context =
|
2015-03-04 22:36:35 -08:00
|
|
|
evgl_engine->funcs->gles_context_create(eng_data, ctx, sfc);
|
2015-02-24 03:54:55 -08:00
|
|
|
}
|
2015-03-09 01:17:19 -07:00
|
|
|
if (dbg) DBG("Calling make_current(%p, %p)", sfc->indirect_sfc, ctx->context);
|
|
|
|
if (!evgl_engine->funcs->make_current(eng_data, sfc->indirect_sfc,
|
|
|
|
ctx->indirect_context, EINA_TRUE))
|
2015-02-24 03:54:55 -08:00
|
|
|
{
|
2015-03-09 01:17:19 -07:00
|
|
|
ERR("Failed to make current with indirect surface.");
|
2015-02-24 03:54:55 -08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
// Transition from direct rendering to indirect rendering
|
2015-02-24 03:54:55 -08:00
|
|
|
if (rsc->direct.rendered)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx->current_fbo = 0;
|
|
|
|
rsc->direct.rendered = 0;
|
2014-09-22 23:33:16 -07:00
|
|
|
}
|
|
|
|
}
|
2015-03-09 01:17:19 -07:00
|
|
|
else
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2015-03-13 00:31:54 -07:00
|
|
|
Eina_Bool use_extension = EINA_FALSE;
|
|
|
|
if ((ctx->version == EVAS_GL_GLES_1_X) && (gles1_funcs))
|
|
|
|
use_extension = EINA_TRUE;
|
2014-11-18 00:37:25 -08:00
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
// Normal FBO Rendering
|
|
|
|
// Create FBO if it hasn't been created
|
|
|
|
if (!ctx->surface_fbo)
|
2015-03-13 00:31:54 -07:00
|
|
|
_framebuffer_create(&ctx->surface_fbo, use_extension);
|
2014-02-14 09:33:47 -08:00
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
// Direct Rendering
|
|
|
|
if (_evgl_direct_renderable(rsc, sfc))
|
2014-02-14 09:33:47 -08:00
|
|
|
{
|
2015-03-09 01:17:19 -07:00
|
|
|
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)
|
2014-02-14 09:33:47 -08:00
|
|
|
{
|
2015-03-13 00:31:54 -07:00
|
|
|
_framebuffer_bind(0, use_extension);
|
2015-03-09 01:17:19 -07:00
|
|
|
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
|
2015-03-13 00:31:54 -07:00
|
|
|
_framebuffer_bind(0, use_extension);
|
2015-03-09 01:17:19 -07:00
|
|
|
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)
|
2014-02-14 09:33:47 -08:00
|
|
|
{
|
2015-03-09 01:17:19 -07:00
|
|
|
if (!ctx->partial_render)
|
|
|
|
{
|
|
|
|
evgl_direct_partial_render_start();
|
|
|
|
ctx->partial_render = 1;
|
|
|
|
}
|
2014-02-14 09:33:47 -08:00
|
|
|
}
|
|
|
|
}
|
2014-11-18 00:37:25 -08:00
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
rsc->direct.rendered = 1;
|
2014-09-19 01:32:26 -07:00
|
|
|
}
|
2015-03-09 01:17:19 -07:00
|
|
|
else if (sfc->pbuffer.native_surface)
|
|
|
|
{
|
|
|
|
if (dbg) DBG("Surface sfc %p is a pbuffer: %p", sfc, sfc->pbuffer.native_surface);
|
2014-09-19 01:32:26 -07:00
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
// Call end tiling
|
|
|
|
if (rsc->direct.partial.enabled)
|
|
|
|
evgl_direct_partial_render_end();
|
2014-09-19 01:32:26 -07:00
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
if (sfc->color_buf)
|
|
|
|
{
|
2015-03-13 00:31:54 -07:00
|
|
|
if (!_surface_buffers_fbo_set(sfc, sfc->color_buf, use_extension))
|
2015-03-09 01:17:19 -07:00
|
|
|
ERR("Could not detach current FBO");
|
|
|
|
}
|
2014-09-19 01:32:26 -07:00
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
if (dbg) DBG("Calling make_current(%p, %p)", sfc->pbuffer.native_surface, ctx->context);
|
|
|
|
evgl_engine->funcs->make_current(eng_data, sfc->pbuffer.native_surface,
|
|
|
|
ctx->context, EINA_TRUE);
|
2014-11-18 00:37:25 -08:00
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
// Bind to the previously bound buffer (may be 0)
|
|
|
|
if (ctx->current_fbo)
|
2015-03-13 00:31:54 -07:00
|
|
|
_framebuffer_bind(ctx->current_fbo, use_extension);
|
2015-03-09 01:17:19 -07:00
|
|
|
|
|
|
|
rsc->direct.rendered = 0;
|
|
|
|
}
|
|
|
|
else
|
2012-10-05 03:03:37 -07:00
|
|
|
{
|
2015-03-09 01:17:19 -07:00
|
|
|
if (dbg) DBG("Surface sfc %p is a normal surface.", sfc);
|
2014-02-14 09:33:47 -08:00
|
|
|
|
2015-03-09 01:17:19 -07:00
|
|
|
// Attach fbo and the buffers
|
|
|
|
if ((rsc->current_ctx != ctx) || (ctx->current_sfc != sfc) || (rsc->direct.rendered))
|
|
|
|
{
|
|
|
|
sfc->current_ctx = ctx;
|
|
|
|
if ((evgl_engine->direct_mem_opt) && (evgl_engine->direct_override))
|
2014-02-14 09:33:47 -08:00
|
|
|
{
|
2015-03-09 01:17:19 -07:00
|
|
|
DBG("Not creating fallback surfaces even though it should. Use at OWN discretion!");
|
2014-02-14 09:33:47 -08:00
|
|
|
}
|
2015-03-09 01:17:19 -07:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// If it's transitioning from direct render to fbo render
|
|
|
|
// Call end tiling
|
|
|
|
if (rsc->direct.partial.enabled)
|
|
|
|
evgl_direct_partial_render_end();
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2015-03-13 00:31:54 -07:00
|
|
|
if (!_surface_buffers_fbo_set(sfc, ctx->surface_fbo, use_extension))
|
2015-03-09 01:17:19 -07:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bind to the previously bound buffer
|
|
|
|
if (ctx->current_fbo)
|
2015-03-13 00:31:54 -07:00
|
|
|
_framebuffer_bind(ctx->current_fbo, use_extension);
|
2015-03-09 01:17:19 -07:00
|
|
|
}
|
|
|
|
rsc->direct.rendered = 0;
|
2012-10-05 03:03:37 -07:00
|
|
|
}
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2012-10-05 03:03:37 -07:00
|
|
|
ctx->current_sfc = sfc;
|
2012-09-24 00:41:27 -07:00
|
|
|
rsc->current_ctx = ctx;
|
2013-05-02 03:06:10 -07:00
|
|
|
rsc->current_eng = eng_data;
|
2012-09-24 00:41:27 -07:00
|
|
|
|
2013-06-26 06:30:48 -07:00
|
|
|
_surface_context_list_print();
|
2013-01-21 23:00:12 -08:00
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_string_query(int name)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2015-03-04 22:36:35 -08:00
|
|
|
EVGL_Resource *rsc;
|
|
|
|
int ctx_version = EVAS_GL_GLES_2_X;
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
switch(name)
|
|
|
|
{
|
|
|
|
case EVAS_GL_EXTENSIONS:
|
2015-03-04 22:36:35 -08:00
|
|
|
rsc = _evgl_tls_resource_get();
|
|
|
|
if ((rsc) && (rsc->current_ctx))
|
|
|
|
ctx_version = rsc->current_ctx->version;
|
|
|
|
return evgl_api_ext_string_get(EINA_FALSE, ctx_version);
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
default:
|
|
|
|
return "";
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2014-10-24 05:25:08 -07:00
|
|
|
void
|
|
|
|
evgl_safe_extension_add(const char *name, void *funcptr)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2014-10-24 05:25:08 -07:00
|
|
|
if (!name) return;
|
|
|
|
|
2014-12-19 01:06:23 -08:00
|
|
|
if (evgl_engine->api_debug_mode)
|
|
|
|
DBG("Whitelisting function [%p] %s", funcptr, name);
|
|
|
|
|
2014-10-24 05:25:08 -07:00
|
|
|
if (funcptr)
|
|
|
|
eina_hash_set(evgl_engine->safe_extensions, name, funcptr);
|
|
|
|
else
|
|
|
|
eina_hash_set(evgl_engine->safe_extensions, name, (void*) 0x1);
|
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
|
|
|
evgl_safe_extension_get(const char *name, void **pfuncptr)
|
|
|
|
{
|
|
|
|
static Eina_Bool _unsafe_checked = EINA_FALSE, _unsafe = EINA_FALSE;
|
|
|
|
void *func;
|
|
|
|
|
|
|
|
if (!name || !*name)
|
|
|
|
return EINA_FALSE;
|
|
|
|
|
|
|
|
// use this for debugging or if you want to break everything
|
|
|
|
if (!_unsafe_checked)
|
|
|
|
{
|
|
|
|
if (getenv("EVAS_GL_UNSAFE_EXTENSIONS"))
|
|
|
|
_unsafe = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_unsafe)
|
|
|
|
return EINA_TRUE;
|
|
|
|
|
|
|
|
func = eina_hash_find(evgl_engine->safe_extensions, name);
|
|
|
|
if (!func) return EINA_FALSE;
|
|
|
|
|
|
|
|
// this is for safe extensions of which we didn't resolve the address
|
|
|
|
if (func == (void *) 0x1)
|
|
|
|
{
|
|
|
|
if (pfuncptr) *pfuncptr = NULL;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pfuncptr) *pfuncptr = func;
|
|
|
|
return EINA_TRUE;
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
2015-03-09 01:25:20 -07:00
|
|
|
void *
|
2015-03-16 19:40:04 -07:00
|
|
|
evgl_native_surface_buffer_get(EVGL_Surface *sfc)
|
2015-03-09 01:25:20 -07:00
|
|
|
{
|
|
|
|
if (!evgl_engine)
|
|
|
|
{
|
|
|
|
ERR("Invalid input data. Engine: %p", evgl_engine);
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-03-16 19:40:04 -07:00
|
|
|
#ifdef GL_GLES
|
2015-03-09 01:25:20 -07:00
|
|
|
return sfc->egl_image;
|
2015-03-16 19:40:04 -07:00
|
|
|
#else
|
|
|
|
return (void *)(uintptr_t)sfc->color_buf;
|
|
|
|
#endif
|
2015-03-09 01:25:20 -07:00
|
|
|
}
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
int
|
2013-05-02 03:06:10 -07:00
|
|
|
evgl_native_surface_get(EVGL_Surface *sfc, Evas_Native_Surface *ns)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
|
|
|
// Check the input
|
2013-05-02 03:06:10 -07:00
|
|
|
if ((!evgl_engine) || (!ns))
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2013-05-02 03:06:10 -07:00
|
|
|
ERR("Invalid input data. Engine: %p NS:%p", evgl_engine, ns);
|
2012-09-24 00:41:27 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-04-10 00:13:22 -07:00
|
|
|
ns->type = EVAS_NATIVE_SURFACE_EVASGL;
|
|
|
|
ns->version = EVAS_NATIVE_SURFACE_VERSION;
|
|
|
|
ns->data.evasgl.surface = sfc;
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2015-03-03 03:08:16 -08:00
|
|
|
evgl_direct_rendered(void)
|
2012-10-05 03:03:37 -07:00
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
|
2013-05-02 03:06:10 -07:00
|
|
|
if (!(rsc=_evgl_tls_resource_get())) return 0;
|
2012-10-05 03:03:37 -07:00
|
|
|
|
2013-10-24 01:37:22 -07:00
|
|
|
return rsc->direct.rendered;
|
|
|
|
}
|
|
|
|
|
2014-12-09 04:36:45 -08:00
|
|
|
/*
|
|
|
|
* This function can tell the engine whether a surface can be directly
|
|
|
|
* rendered to the Evas, despite any window rotation. For that purpose,
|
|
|
|
* we let the engine know the surface flags for this texture
|
|
|
|
*/
|
|
|
|
Eina_Bool
|
|
|
|
evgl_native_surface_direct_opts_get(Evas_Native_Surface *ns,
|
|
|
|
Eina_Bool *direct_render,
|
2015-02-24 02:05:39 -08:00
|
|
|
Eina_Bool *client_side_rotation,
|
2015-03-02 23:38:52 -08:00
|
|
|
Eina_Bool *direct_override)
|
2014-12-09 04:36:45 -08:00
|
|
|
{
|
|
|
|
EVGL_Surface *sfc;
|
|
|
|
|
|
|
|
if (direct_render) *direct_render = EINA_FALSE;
|
2015-03-02 23:38:52 -08:00
|
|
|
if (direct_override) *direct_override = EINA_FALSE;
|
2014-12-09 04:36:45 -08:00
|
|
|
if (client_side_rotation) *client_side_rotation = EINA_FALSE;
|
|
|
|
|
|
|
|
if (!evgl_engine) return EINA_FALSE;
|
2015-03-02 23:38:52 -08:00
|
|
|
if (!ns) return EINA_FALSE;
|
2014-12-09 04:36:45 -08:00
|
|
|
|
2015-04-10 00:13:22 -07:00
|
|
|
if (ns->type == EVAS_NATIVE_SURFACE_EVASGL &&
|
2015-03-09 01:25:20 -07:00
|
|
|
ns->data.evasgl.surface)
|
|
|
|
{
|
|
|
|
sfc = ns->data.evasgl.surface;
|
|
|
|
}
|
2015-04-11 19:36:28 -07:00
|
|
|
else return EINA_FALSE;
|
2014-12-09 04:36:45 -08:00
|
|
|
|
|
|
|
if (evgl_engine->api_debug_mode)
|
|
|
|
{
|
|
|
|
DBG("Found native surface: texid:%u DR:%d CSR:%d",
|
|
|
|
ns->data.opengl.texture_id, (int) sfc->direct_fb_opt,
|
|
|
|
(int) sfc->client_side_rotation);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (direct_render) *direct_render = sfc->direct_fb_opt;
|
2015-03-02 23:38:52 -08:00
|
|
|
if (direct_override) *direct_override |= sfc->direct_override;
|
2014-12-09 04:36:45 -08:00
|
|
|
if (client_side_rotation) *client_side_rotation = sfc->client_side_rotation;
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
2013-10-24 01:37:22 -07:00
|
|
|
void
|
2014-09-03 19:42:01 -07:00
|
|
|
evgl_direct_info_set(int win_w, int win_h, int rot,
|
|
|
|
int img_x, int img_y, int img_w, int img_h,
|
2014-12-09 04:36:45 -08:00
|
|
|
int clip_x, int clip_y, int clip_w, int clip_h,
|
2015-03-09 01:25:20 -07:00
|
|
|
void *surface)
|
2013-10-24 01:37:22 -07:00
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
2015-03-09 01:25:20 -07:00
|
|
|
EVGL_Surface *sfc = surface;
|
2013-10-24 01:37:22 -07:00
|
|
|
|
2014-12-09 04:36:45 -08:00
|
|
|
if (!(rsc = _evgl_tls_resource_get()))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Check for direct rendering
|
|
|
|
*
|
|
|
|
* DR is allowed iif:
|
|
|
|
* - Rotation == 0
|
|
|
|
* OR: - Client-Side Rotation is set on the surface
|
|
|
|
* - Direct Override is set
|
|
|
|
*
|
|
|
|
* If the surface is not found, we assume indirect rendering.
|
2014-09-03 19:42:01 -07:00
|
|
|
*/
|
2014-12-09 04:36:45 -08:00
|
|
|
|
2015-02-24 02:05:39 -08:00
|
|
|
if (sfc &&
|
|
|
|
((rot == 0) || sfc->client_side_rotation || sfc->direct_override))
|
2013-10-24 01:37:22 -07:00
|
|
|
{
|
2014-12-09 04:36:45 -08:00
|
|
|
if (evgl_engine->api_debug_mode)
|
|
|
|
DBG("Direct rendering is enabled.");
|
|
|
|
|
2013-10-24 01:37:22 -07:00
|
|
|
rsc->direct.enabled = EINA_TRUE;
|
|
|
|
|
2014-09-03 19:42:01 -07:00
|
|
|
rsc->direct.win_w = win_w;
|
|
|
|
rsc->direct.win_h = win_h;
|
|
|
|
rsc->direct.rot = rot;
|
2013-10-24 01:37:22 -07:00
|
|
|
|
2014-09-03 19:42:01 -07:00
|
|
|
rsc->direct.img.x = img_x;
|
|
|
|
rsc->direct.img.y = img_y;
|
|
|
|
rsc->direct.img.w = img_w;
|
|
|
|
rsc->direct.img.h = img_h;
|
2013-10-24 01:37:22 -07:00
|
|
|
|
2014-09-03 19:42:01 -07:00
|
|
|
rsc->direct.clip.x = clip_x;
|
|
|
|
rsc->direct.clip.y = clip_y;
|
|
|
|
rsc->direct.clip.w = clip_w;
|
|
|
|
rsc->direct.clip.h = clip_h;
|
2013-10-24 01:37:22 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-12-09 04:36:45 -08:00
|
|
|
if (evgl_engine->api_debug_mode)
|
|
|
|
DBG("Direct rendering is disabled.");
|
|
|
|
|
2013-10-24 01:37:22 -07:00
|
|
|
rsc->direct.enabled = EINA_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2015-03-03 03:08:16 -08:00
|
|
|
evgl_direct_info_clear(void)
|
2013-10-24 01:37:22 -07:00
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
|
|
|
|
if (!(rsc=_evgl_tls_resource_get())) return;
|
|
|
|
|
|
|
|
rsc->direct.enabled = EINA_FALSE;
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
2015-03-03 03:08:16 -08:00
|
|
|
void
|
|
|
|
evgl_get_pixels_pre(void)
|
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
|
|
|
|
if (!(rsc=_evgl_tls_resource_get())) return;
|
|
|
|
|
|
|
|
rsc->direct.in_get_pixels = EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evgl_get_pixels_post(void)
|
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
|
|
|
|
if (!(rsc=_evgl_tls_resource_get())) return;
|
|
|
|
|
|
|
|
rsc->direct.in_get_pixels = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2012-09-24 00:41:27 -07:00
|
|
|
Evas_GL_API *
|
2014-09-22 03:15:37 -07:00
|
|
|
evgl_api_get(Evas_GL_Context_Version version)
|
2012-09-24 00:41:27 -07:00
|
|
|
{
|
2014-09-22 03:15:37 -07:00
|
|
|
if (version == EVAS_GL_GLES_2_X)
|
|
|
|
{
|
2014-12-02 18:44:09 -08:00
|
|
|
_evgl_api_get(gl_funcs, evgl_engine->api_debug_mode);
|
|
|
|
return gl_funcs;
|
2014-09-22 03:15:37 -07:00
|
|
|
}
|
|
|
|
else if (version == EVAS_GL_GLES_1_X)
|
|
|
|
{
|
2015-03-04 22:36:35 -08:00
|
|
|
if (!gles1_funcs) gles1_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
|
|
|
|
|
2014-12-02 18:44:09 -08:00
|
|
|
_evgl_api_gles1_get(gles1_funcs, evgl_engine->api_debug_mode);
|
|
|
|
return gles1_funcs;
|
2014-09-22 03:15:37 -07:00
|
|
|
}
|
2015-03-04 22:36:35 -08:00
|
|
|
else if (version == EVAS_GL_GLES_3_X)
|
|
|
|
{
|
|
|
|
// Allocate gles3 funcs here, as this is called only if GLES_3 is supported
|
|
|
|
if (!gles3_funcs) gles3_funcs = calloc(1, EVAS_GL_API_STRUCT_SIZE);
|
|
|
|
|
|
|
|
if (!_evgl_api_gles3_get(gles3_funcs, evgl_engine->api_debug_mode))
|
|
|
|
{
|
|
|
|
free(gles3_funcs);
|
|
|
|
gles3_funcs = NULL;
|
|
|
|
}
|
|
|
|
return gles3_funcs;
|
|
|
|
}
|
2014-09-22 03:15:37 -07:00
|
|
|
else return NULL;
|
2012-09-24 00:41:27 -07:00
|
|
|
}
|
|
|
|
|
2014-02-14 09:33:47 -08:00
|
|
|
|
|
|
|
void
|
|
|
|
evgl_direct_partial_info_set(int pres)
|
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
|
|
|
|
if (!(rsc=_evgl_tls_resource_get())) return;
|
|
|
|
|
|
|
|
rsc->direct.partial.enabled = EINA_TRUE;
|
|
|
|
rsc->direct.partial.preserve = pres;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evgl_direct_partial_info_clear()
|
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
|
|
|
|
if (!(rsc=_evgl_tls_resource_get())) return;
|
|
|
|
|
|
|
|
rsc->direct.partial.enabled = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
2013-06-17 01:53:33 -07:00
|
|
|
void
|
2015-02-24 02:05:39 -08:00
|
|
|
evgl_direct_override_get(Eina_Bool *override, Eina_Bool *force_off)
|
2013-06-17 01:53:33 -07:00
|
|
|
{
|
2014-12-09 04:36:45 -08:00
|
|
|
if (override) *override = evgl_engine->direct_override;
|
|
|
|
if (force_off) *force_off = evgl_engine->direct_force_off;
|
2013-06-17 01:53:33 -07:00
|
|
|
}
|
|
|
|
|
2014-02-14 09:33:47 -08:00
|
|
|
void
|
|
|
|
evgl_direct_partial_render_start()
|
|
|
|
{
|
|
|
|
EVGL_Resource *rsc;
|
|
|
|
|
|
|
|
if (!(rsc=_evgl_tls_resource_get())) return;
|
|
|
|
|
|
|
|
evas_gl_common_tiling_start(NULL,
|
|
|
|
rsc->direct.rot,
|
|
|
|
rsc->direct.win_w,
|
|
|
|
rsc->direct.win_h,
|
|
|
|
rsc->direct.clip.x,
|
|
|
|
rsc->direct.win_h - rsc->direct.clip.y - rsc->direct.clip.h,
|
|
|
|
rsc->direct.clip.w,
|
|
|
|
rsc->direct.clip.h,
|
|
|
|
rsc->direct.partial.preserve);
|
|
|
|
|
|
|
|
if (!rsc->direct.partial.preserve)
|
|
|
|
rsc->direct.partial.preserve = GL_COLOR_BUFFER_BIT0_QCOM;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
evgl_direct_partial_render_end()
|
|
|
|
{
|
|
|
|
EVGL_Context *ctx;
|
2014-09-01 20:52:52 -07:00
|
|
|
ctx = evas_gl_common_current_context_get();
|
2014-02-14 09:33:47 -08:00
|
|
|
|
|
|
|
if (!ctx) return;
|
|
|
|
|
|
|
|
if (ctx->partial_render)
|
|
|
|
{
|
|
|
|
evas_gl_common_tiling_done(NULL);
|
|
|
|
ctx->partial_render = 0;
|
|
|
|
}
|
|
|
|
}
|
2012-09-24 00:41:27 -07:00
|
|
|
//-----------------------------------------------------//
|
|
|
|
|
|
|
|
|