Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock = NULL;
Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_relax = NULL;
+glsym_func_void glsym_evas_gl_common_error_set = NULL;
+glsym_func_int glsym_evas_gl_common_error_get = NULL;
+glsym_func_void_ptr glsym_evas_gl_common_current_context_get = NULL;
+
_eng_fn (*glsym_eglGetProcAddress) (const char *a) = NULL;
void *(*glsym_eglCreateImage) (EGLDisplay a, EGLContext b, EGLenum c, EGLClientBuffer d, const int *e) = NULL;
void (*glsym_eglDestroyImage) (EGLDisplay a, void *b) = NULL;
return re->generic.software.ob;
}
-static void
+static void
gl_symbols(void)
{
static Eina_Bool done = EINA_FALSE;
LINK2GENERIC(evas_gl_preload_shutdown);
LINK2GENERIC(evgl_engine_shutdown);
LINK2GENERIC(evas_gl_symbols);
+ LINK2GENERIC(evas_gl_common_error_get);
+ LINK2GENERIC(evas_gl_common_error_set);
+ LINK2GENERIC(evas_gl_common_current_context_get);
#define FINDSYM(dst, sym, typ) \
if (glsym_eglGetProcAddress) { \
FINDSYM(glsym_eglDestroyImage, "eglDestroyImageARB", glsym_func_void);
FINDSYM(glsym_eglDestroyImage, "eglDestroyImage", glsym_func_void);
- FINDSYM(glsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES",
+ FINDSYM(glsym_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES",
glsym_func_void);
- FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageEXT",
+ FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageEXT",
glsym_func_uint);
- FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageINTEL",
+ FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamageINTEL",
glsym_func_uint);
- FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamage",
+ FINDSYM(glsym_eglSwapBuffersWithDamage, "eglSwapBuffersWithDamage",
glsym_func_uint);
done = EINA_TRUE;
}
}
-static void
+static void
_re_winfree(Render_Engine *re)
{
Outbuf *ob;
if (ctxt)
{
- context =
- eglCreateContext(ob->egl_disp, ob->egl_config,
+ context =
+ eglCreateContext(ob->egl_disp, ob->egl_config,
(EGLContext)ctxt, attrs);
}
else
{
- context =
- eglCreateContext(ob->egl_disp, ob->egl_config,
+ context =
+ eglCreateContext(ob->egl_disp, ob->egl_config,
ob->egl_context[0], attrs);
}
return (void *)context;
}
-static int
+static int
evgl_eng_context_destroy(void *data, void *ctxt)
{
Render_Engine *re;
return 1;
}
-static int
+static int
evgl_eng_make_current(void *data, void *surface, void *ctxt, int flush)
{
Render_Engine *re;
if ((!ctxt) && (!surface))
{
- ret =
- eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE,
+ ret =
+ eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!ret)
{
return 1;
}
- if ((eglGetCurrentContext() != ctx) ||
- (eglGetCurrentSurface(EGL_READ) != surf) ||
+ if ((eglGetCurrentContext() != ctx) ||
+ (eglGetCurrentSurface(EGL_READ) != surf) ||
(eglGetCurrentSurface(EGL_DRAW) != surf))
{
if (flush) eng_window_use(NULL);
return eglQueryString(ob->egl_disp, EGL_EXTENSIONS);
}
-static int
+static int
evgl_eng_rotation_angle_get(void *data)
{
Render_Engine *re;
return 0;
}
-static const EVGL_Interface evgl_funcs =
+static void *
+evgl_eng_pbuffer_surface_create(void *data, EVGL_Surface *sfc,
+ const int *attrib_list)
+{
+ Render_Engine_GL_Generic *re = data;
+
+ // TODO: Add support for surfaceless pbuffers (EGL_NO_TEXTURE)
+ // TODO: Add support for EGL_MIPMAP_TEXTURE??? (GLX doesn't support them)
+
+ if (attrib_list)
+ WRN("This PBuffer implementation does not support extra attributes yet");
+
+#ifdef GL_GLES
+ Evas_Engine_GL_Context *evasglctx;
+ int config_attrs[20];
+ int surface_attrs[20];
+ EGLSurface egl_sfc;
+ EGLConfig egl_cfg;
+ int num_config, i = 0;
+ EGLDisplay disp;
+ EGLContext ctx;
+
+ disp = re->window_egl_display_get(re->software.ob);
+ evasglctx = re->window_gl_context_get(re->software.ob);
+ ctx = evasglctx->eglctxt;
+
+ // It looks like eglMakeCurrent might fail if we use a different config from
+ // the actual display surface. This is weird.
+ i = 0;
+ config_attrs[i++] = EGL_CONFIG_ID;
+ config_attrs[i++] = 0;
+ config_attrs[i++] = EGL_NONE;
+ eglQueryContext(disp, ctx, EGL_CONFIG_ID, &config_attrs[1]);
+
+ if (!eglChooseConfig(disp, config_attrs, &egl_cfg, 1, &num_config)
+ || (num_config < 1))
+ {
+ int err = eglGetError();
+ glsym_evas_gl_common_error_set(data, err - EGL_SUCCESS);
+ ERR("eglChooseConfig failed with error %x", err);
+ return NULL;
+ }
+
+ // Now, choose the config for the PBuffer
+ i = 0;
+ surface_attrs[i++] = EGL_WIDTH;
+ surface_attrs[i++] = sfc->w;
+ surface_attrs[i++] = EGL_HEIGHT;
+ surface_attrs[i++] = sfc->h;
+
+ surface_attrs[i++] = EGL_NONE;
+
+ egl_sfc = eglCreatePbufferSurface(disp, egl_cfg, surface_attrs);
+ if (!egl_sfc)
+ {
+ int err = eglGetError();
+ glsym_evas_gl_common_error_set(data, err - EGL_SUCCESS);
+ ERR("eglCreatePbufferSurface failed with error %x", err);
+ return NULL;
+ }
+
+ return egl_sfc;
+#else
+ GLXPbuffer pbuf;
+ GLXFBConfig *cfgs;
+ int config_attrs[20];
+ int surface_attrs[20];
+ int ncfg = 0, i;
+
+ // TODO: Check all required config attributes
+ // TODO: Should be tested when EFL runs with wayland on Desktop
+
+#ifndef GLX_VISUAL_ID
+# define GLX_VISUAL_ID 0x800b
+#endif
+
+ i = 0;
+ if (sfc->pbuffer.color_fmt != EVAS_GL_NO_FBO)
+ {
+ config_attrs[i++] = GLX_BUFFER_SIZE;
+ if (sfc->pbuffer.color_fmt == EVAS_GL_RGBA_8888)
+ {
+ config_attrs[i++] = 32;
+ //config_attrs[i++] = GLX_BIND_TO_TEXTURE_RGBA_EXT;
+ //config_attrs[i++] = 1;
+ }
+ else
+ {
+ config_attrs[i++] = 24;
+ //config_attrs[i++] = GLX_BIND_TO_TEXTURE_RGB_EXT;
+ //config_attrs[i++] = 1;
+ }
+ }
+ if (sfc->depth_fmt)
+ {
+ config_attrs[i++] = GLX_DEPTH_SIZE;
+ config_attrs[i++] = 24; // FIXME: This should depend on the requested bits
+ }
+ if (sfc->stencil_fmt)
+ {
+ config_attrs[i++] = GLX_STENCIL_SIZE;
+ config_attrs[i++] = 8; // FIXME: This should depend on the requested bits
+ }
+ //config_attrs[i++] = GLX_VISUAL_ID;
+ //config_attrs[i++] = XVisualIDFromVisual(vis);
+ config_attrs[i++] = 0;
+
+ cfgs = glXChooseFBConfig(re->software.ob->disp, re->software.ob->screen,
+ config_attrs, &ncfg);
+ if (!cfgs || !ncfg)
+ {
+ ERR("GLX failed to find a valid config for the pbuffer");
+ if (cfgs) XFree(cfgs);
+ return NULL;
+ }
+
+ i = 0;
+ surface_attrs[i++] = GLX_LARGEST_PBUFFER;
+ surface_attrs[i++] = 0;
+ surface_attrs[i++] = GLX_PBUFFER_WIDTH;
+ surface_attrs[i++] = sfc->w;
+ surface_attrs[i++] = GLX_PBUFFER_HEIGHT;
+ surface_attrs[i++] = sfc->h;
+ surface_attrs[i++] = 0;
+ pbuf = glXCreatePbuffer(re->software.ob->disp, cfgs[0], surface_attrs);
+ if (cfgs) XFree(cfgs);
+
+ if (!pbuf)
+ {
+ ERR("GLX failed to create a pbuffer");
+ return NULL;
+ }
+
+ return (void*)(intptr_t)pbuf;
+#endif
+}
+
+static int
+evgl_eng_pbuffer_surface_destroy(void *data, void *surface)
+{
+ /* EVGLINIT(re, 0); */
+ if (!data)
+ {
+ ERR("Invalid Render Engine Data!");
+ glsym_evas_gl_common_error_set(NULL, EVAS_GL_NOT_INITIALIZED);
+ return 0;
+ }
+
+ if (!surface)
+ {
+ ERR("Invalid surface.");
+ glsym_evas_gl_common_error_set(data, EVAS_GL_BAD_SURFACE);
+ return 0;
+ }
+
+#ifdef GL_GLES
+ Render_Engine *re = data;
+
+ eglDestroySurface(eng_get_ob(re)->egl_disp, (EGLSurface)surface);
+#else
+ // TODO: Should be tested when EFL runs with wayland on Desktop
+ Render_Engine_GL_Generic *re = data;
+ GLXPbuffer pbuf = (GLXPbuffer)(intptr_t) surface;
+
+ glXDestroyPbuffer(re->software.ob->disp, pbuf);
+#endif
+
+ return 1;
+}
+
+static const EVGL_Interface evgl_funcs =
{
evgl_eng_display_get,
evgl_eng_evas_surface_get,
evgl_eng_proc_address_get,
evgl_eng_string_get,
evgl_eng_rotation_angle_get,
- NULL, // PBuffer
- NULL, // PBuffer
- NULL, // OpenGL-ES 1
- NULL, // OpenGL-ES 1
+ evgl_eng_pbuffer_surface_create,
+ evgl_eng_pbuffer_surface_destroy,
+ NULL, //gles1_surface_create
+ NULL, // gles1_surface_destroy
};
/* engine functions */
return info;
}
-static void
+static void
eng_info_free(Evas *evas EINA_UNUSED, void *info)
{
Evas_Engine_Info_Wayland_Egl *inf;
free(inf);
}
-static int
+static int
eng_setup(Evas *evas, void *info)
{
Render_Engine_Swap_Mode swap_mode = MODE_FULL;
ob = eng_window_new(evas, inf, epd->output.w, epd->output.h, swap_mode);
if (!ob) goto ob_err;
- if (!evas_render_engine_gl_generic_init(&re->generic, ob,
- eng_outbuf_swap_mode_get,
- eng_outbuf_rotation_get,
- eng_outbuf_reconfigure,
- eng_outbuf_region_first_rect,
- eng_outbuf_update_region_new,
+ if (!evas_render_engine_gl_generic_init(&re->generic, ob,
+ eng_outbuf_swap_mode_get,
+ eng_outbuf_rotation_get,
+ eng_outbuf_reconfigure,
+ eng_outbuf_region_first_rect,
+ eng_outbuf_update_region_new,
eng_outbuf_update_region_push,
- eng_outbuf_update_region_free,
- NULL,
- eng_outbuf_flush,
- eng_window_free,
- eng_window_use,
- eng_outbuf_gl_context_get,
- eng_outbuf_egl_display_get,
- eng_gl_context_new,
- eng_gl_context_use,
- &evgl_funcs,
+ eng_outbuf_update_region_free,
+ NULL,
+ eng_outbuf_flush,
+ eng_window_free,
+ eng_window_use,
+ eng_outbuf_gl_context_get,
+ eng_outbuf_egl_display_get,
+ eng_gl_context_new,
+ eng_gl_context_use,
+ &evgl_funcs,
epd->output.w, epd->output.h))
{
eng_window_free(ob);
if ((ob) && (_re_wincheck(ob)))
{
ob->info = inf;
- if ((ob->info->info.display != ob->disp) ||
- (ob->info->info.surface != ob->surface) ||
- (ob->info->info.win != ob->win) ||
- (ob->info->info.depth != ob->depth) ||
- (ob->info->info.screen != ob->screen) ||
+ if ((ob->info->info.display != ob->disp) ||
+ (ob->info->info.surface != ob->surface) ||
+ (ob->info->info.win != ob->win) ||
+ (ob->info->info.depth != ob->depth) ||
+ (ob->info->info.screen != ob->screen) ||
(ob->info->info.destination_alpha != ob->alpha))
{
ob->gl_context->references++;
ob = eng_window_new(evas, inf, epd->output.w, epd->output.h, swap_mode);
if (!ob) goto ob_err;
-
+
eng_window_use(ob);
- evas_render_engine_software_generic_update(&re->generic.software, ob,
+ evas_render_engine_software_generic_update(&re->generic.software, ob,
epd->output.w, epd->output.h);
gl_wins++;
eng_get_ob(re)->gl_context->references--;
}
- else if ((ob->w != epd->output.w) || (ob->h != epd->output.h) ||
+ else if ((ob->w != epd->output.w) || (ob->h != epd->output.h) ||
(ob->info->info.rotation != ob->rot))
{
- eng_outbuf_reconfigure(ob, epd->output.w, epd->output.h,
+ eng_outbuf_reconfigure(ob, epd->output.w, epd->output.h,
ob->info->info.rotation, 0);
}
}
if (re->generic.software.tb)
evas_common_tilebuf_free(re->generic.software.tb);
- re->generic.software.tb =
+ re->generic.software.tb =
evas_common_tilebuf_new(epd->output.w, epd->output.h);
if (re->generic.software.tb)
{
- evas_common_tilebuf_set_tile_size(re->generic.software.tb,
+ evas_common_tilebuf_set_tile_size(re->generic.software.tb,
TILESIZE, TILESIZE);
evas_render_engine_software_generic_tile_strict_set
(&re->generic.software, EINA_TRUE);
if (!epd->engine.data.context)
{
- epd->engine.data.context =
+ epd->engine.data.context =
epd->engine.func->context_new(epd->engine.data.output);
}
return 0;
}
-static Eina_Bool
+static Eina_Bool
eng_canvas_alpha_get(void *data, void *info EINA_UNUSED)
{
Render_Engine *re;
return EINA_FALSE;
}
-static void
+static void
eng_output_free(void *data)
{
Render_Engine *re;
}
}
-static void
+static void
eng_output_dump(void *data)
{
Render_Engine *re;
_re_winfree(re);
}
-static void
+static void *
+eng_gl_current_context_get(void *data EINA_UNUSED)
+{
+ EVGL_Context *ctx;
+
+ ctx = glsym_evas_gl_common_current_context_get();
+ if (!ctx)
+ return NULL;
+
+#ifdef GL_GLES
+ if (eglGetCurrentContext() == (ctx->context))
+ return ctx;
+ else
+ return NULL;
+#else
+ if (glXGetCurrentContext() == (ctx->context))
+ return ctx;
+ else
+ return NULL;
+#endif
+}
+
+
+static void
_native_cb_bind(void *data EINA_UNUSED, void *image)
{
Evas_GL_Image *img;
}
}
-static void
+static void
_native_cb_unbind(void *data EINA_UNUSED, void *image)
{
Evas_GL_Image *img;
}
}
-static void
+static void
_native_cb_free(void *data, void *image)
{
Render_Engine *re;
{
if ((ns) && (ns->type == EVAS_NATIVE_SURFACE_OPENGL))
{
- img =
- glsym_evas_gl_common_image_new_from_data(ob->gl_context,
- ns->data.opengl.w,
- ns->data.opengl.h,
- NULL, 1,
+ img =
+ glsym_evas_gl_common_image_new_from_data(ob->gl_context,
+ ns->data.opengl.w,
+ ns->data.opengl.h,
+ NULL, 1,
EVAS_COLORSPACE_ARGB8888);
}
else
Evas_Native_Surface *ens;
ens = img->native.data;
- if ((ens->data.opengl.texture_id == tex) &&
+ if ((ens->data.opengl.texture_id == tex) &&
(ens->data.opengl.framebuffer_id == fbo))
return img;
}
img2 = eina_hash_find(ob->gl_context->shared->native_tex_hash, &texid);
if (img2 == img) return img;
if (img2)
- {
+ {
if ((n = img2->native.data))
{
glsym_evas_gl_common_image_ref(img2);
}
}
- img2 = glsym_evas_gl_common_image_new_from_data(ob->gl_context, img->w,
- img->h, NULL, img->alpha,
+ img2 = glsym_evas_gl_common_image_new_from_data(ob->gl_context, img->w,
+ img->h, NULL, img->alpha,
EVAS_COLORSPACE_ARGB8888);
glsym_evas_gl_common_image_free(img);
return img;
}
-Eina_Bool
+Eina_Bool
eng_preload_make_current(void *data, void *doit)
{
Outbuf *ob;
if (doit)
{
- if (!eglMakeCurrent(ob->egl_disp, ob->egl_surface[0],
+ if (!eglMakeCurrent(ob->egl_disp, ob->egl_surface[0],
ob->egl_surface[0], ob->egl_context[0]))
return EINA_FALSE;
}
else
{
- if (!eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ if (!eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT))
return EINA_FALSE;
}
}
/* evas module functions */
-static int
+static int
module_open(Evas_Module *em)
{
/* check for valid module */
/* setup logging domain */
if (_evas_engine_wl_egl_log_dom < 0)
{
- _evas_engine_wl_egl_log_dom =
+ _evas_engine_wl_egl_log_dom =
eina_log_domain_register("evas-wayland_egl", EVAS_DEFAULT_LOG_COLOR);
}
ORD(image_native_set);
+ ORD(gl_current_context_get);
+
gl_symbols();
/* advertise out which functions we support */
return 1;
}
-static void
+static void
module_close(Evas_Module *em EINA_UNUSED)
{
eina_log_domain_unregister(_evas_engine_wl_egl_log_dom);