static void * evgl_eng_native_window_create(void *data) { Render_Engine *re; struct gbm_surface *surface; Evas_Engine_Info_GL_Drm *info; re = (Render_Engine *)data; if (!re) { ERR("Invalid Render Engine Data!"); return NULL; } info = eng_get_ob(re)->info; if (!info) { ERR("Invalid Evas Engine GL_DRM Info!"); return NULL; } surface = gbm_surface_create(info->info.gbm, eng_get_ob(re)->w, eng_get_ob(re)->h, info->info.format, info->info.flags); if (!surface) { ERR("Could not create gl drm window: %m"); return NULL; } return (void *)surface; }
static void * evgl_eng_window_surface_create(void *data, void *native_window) { Render_Engine *re; EGLSurface surface = EGL_NO_SURFACE; re = (Render_Engine *)data; if (!re) { ERR("Invalid Render Engine Data!"); return NULL; } // Create resource surface for EGL surface = eglCreateWindowSurface(eng_get_ob(re)->egl.disp, eng_get_ob(re)->egl.config, (EGLNativeWindowType)native_window, NULL); if (!surface) { ERR("Creating window surface failed. Error: %#x.", eglGetError()); return NULL; } return (void *)surface; }
static void _re_winfree(Render_Engine *re) { if (!re) return; if (!eng_get_ob(re)->surf) return; glsym_evas_gl_preload_render_relax(eng_preload_make_current, eng_get_ob(re)); evas_outbuf_unsurf(eng_get_ob(re)); }
static void * evgl_eng_context_create(void *data, void *share_ctx, Evas_GL_Context_Version version) { Render_Engine *re; EGLContext context = EGL_NO_CONTEXT; int context_attrs[3]; re = (Render_Engine *)data; if (!re) { ERR("Invalid Render Engine Data!"); return NULL; } if (version != EVAS_GL_GLES_2_X) { ERR("This engine only supports OpenGL-ES 2.0 contexts for now!"); return NULL; } context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION; context_attrs[1] = 2; context_attrs[2] = EGL_NONE; // Share context already assumes that it's sharing with evas' context if (share_ctx) { context = eglCreateContext(eng_get_ob(re)->egl.disp, eng_get_ob(re)->egl.config, (EGLContext)share_ctx, context_attrs); } else { context = eglCreateContext(eng_get_ob(re)->egl.disp, eng_get_ob(re)->egl.config, eng_get_ob(re)->egl.context[0], // Evas' GL Context context_attrs); } if (!context) { ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError()); return NULL; } return (void *)context; }
static void gl_extn_veto(Render_Engine *re) { const char *str = NULL; str = eglQueryString(eng_get_ob(re)->egl.disp, EGL_EXTENSIONS); if (str) { const char *s = NULL; if (getenv("EVAS_GL_INFO")) printf("EGL EXTN:\n%s\n", str); // Disable Partial Rendering s = getenv("EVAS_GL_PARTIAL_DISABLE"); if ((s) && (atoi(s))) { _extn_have_buffer_age = 0; glsym_eglSwapBuffersWithDamage = NULL; } if (!strstr(str, "EGL_EXT_buffer_age")) _extn_have_buffer_age = 0; if (!strstr(str, "EGL_EXT_swap_buffers_with_damage")) glsym_eglSwapBuffersWithDamage = NULL; } else { if (getenv("EVAS_GL_INFO")) printf("NO EGL EXTN!\n"); _extn_have_buffer_age = 0; } }
static void * evgl_eng_evas_surface_get(void *data) { Render_Engine *re; re = (Render_Engine *)data; if (!re) { ERR("Invalid Render Engine Data!"); return NULL; } if (eng_get_ob(re)) return (void *)eng_get_ob(re)->egl.surface[0]; else return NULL; }
static void * evgl_eng_display_get(void *data) { Render_Engine *re; re = (Render_Engine *)data; if (!re) { ERR("Invalid Render Engine Data!"); return NULL; } if (eng_get_ob(re)) return (void *)eng_get_ob(re)->egl.disp; else return NULL; }
static void gl_extn_veto(Render_Engine *re) { const char *str = NULL; str = eglQueryString(eng_get_ob(re)->egl_disp, EGL_EXTENSIONS); if (str) { const char *s; if (getenv("EVAS_GL_INFO")) printf("EGL EXTN:\n%s\n", str); // Disable Partial Rendering if ((s = getenv("EVAS_GL_PARTIAL_DISABLE")) && atoi(s)) { extn_have_buffer_age = EINA_FALSE; glsym_eglSwapBuffersWithDamage = NULL; } if (!strstr(str, "EGL_EXT_buffer_age")) { extn_have_buffer_age = EINA_FALSE; } if (!strstr(str, "EGL_NOK_texture_from_pixmap")) { extn_have_y_inverted = EINA_FALSE; } else { const GLubyte *vendor, *renderer; vendor = glGetString(GL_VENDOR); renderer = glGetString(GL_RENDERER); // XXX: workaround mesa bug! // looking for mesa and intel build which is known to // advertise the EGL_NOK_texture_from_pixmap extension // but not set it correctly. guessing vendor/renderer // strings will be like the following: // OpenGL vendor string: Intel Open Source Technology Center // OpenGL renderer string: Mesa DRI Intel(R) Sandybridge Desktop if (((vendor) && (strstr((const char *)vendor, "Intel"))) && ((renderer) && (strstr((const char *)renderer, "Mesa"))) && ((renderer) && (strstr((const char *)renderer, "Intel"))) ) extn_have_y_inverted = EINA_FALSE; } if (!strstr(str, "EGL_EXT_swap_buffers_with_damage")) { glsym_eglSwapBuffersWithDamage = NULL; } } else { if (getenv("EVAS_GL_INFO")) printf("NO EGL EXTN!\n"); extn_have_buffer_age = EINA_FALSE; } }
static void * evgl_eng_evas_surface_get(void *data) { Render_Engine *re; Outbuf *ob; if (!(re = (Render_Engine *)data)) return NULL; if (!(ob = eng_get_ob(re))) return NULL; return (void *)ob->egl_surface[0]; }
static void * evgl_eng_display_get(void *data) { Render_Engine *re; Outbuf *ob; if (!(re = (Render_Engine *)data)) return NULL; if (!(ob = eng_get_ob(re))) return NULL; return (void *)ob->egl_disp; }
static void _re_winfree(Render_Engine *re) { Outbuf *ob; if (!(ob = eng_get_ob(re))) return; if (!ob->surf) return; glsym_evas_gl_preload_render_relax(eng_preload_make_current, ob); eng_window_unsurf(ob); }
static const char * evgl_eng_string_get(void *data) { Render_Engine *re; Outbuf *ob; if (!(re = (Render_Engine *)data)) return NULL; if (!(ob = eng_get_ob(re))) return NULL; return eglQueryString(ob->egl_disp, EGL_EXTENSIONS); }
static int evgl_eng_rotation_angle_get(void *data) { Render_Engine *re; re = (Render_Engine *)data; if (!re) { ERR("Invalid Render Engine Data!"); return 0; } if ((eng_get_ob(re)) && (eng_get_ob(re)->gl_context)) return eng_get_ob(re)->gl_context->rot; else { ERR("Unable to retrieve rotation angle."); return 0; } }
static int evgl_eng_context_destroy(void *data, void *ctxt) { Render_Engine *re; Outbuf *ob; if (!(re = (Render_Engine *)data)) return 0; if (!(ob = eng_get_ob(re))) return 0; if (!ctxt) return 0; eglDestroyContext(ob->egl_disp, (EGLContext)ctxt); return 1; }
static int evgl_eng_window_surface_destroy(void *data, void *surface) { Render_Engine *re; Outbuf *ob; if (!(re = (Render_Engine *)data)) return 0; if (!(ob = eng_get_ob(re))) return 0; if (!surface) return 0; eglDestroySurface(ob->egl_disp, (EGLSurface)surface); return 1; }
static int evgl_eng_rotation_angle_get(void *data) { Render_Engine *re; Outbuf *ob; if (!(re = (Render_Engine *)data)) return 0; if (!(ob = eng_get_ob(re))) return 0; if (ob->gl_context) return ob->gl_context->rot; return 0; }
static const char * evgl_eng_string_get(void *data) { Render_Engine *re; re = (Render_Engine *)data; if (!re) { ERR("Invalid Render Engine Data!"); return NULL; } return eglQueryString(eng_get_ob(re)->egl.disp, EGL_EXTENSIONS); }
static int evgl_eng_make_current(void *data, void *surface, void *context, int flush) { Render_Engine *re; EGLContext ctx; EGLSurface sfc; EGLDisplay dpy; int ret = 0; re = (Render_Engine *)data; if (!re) { ERR("Invalid Render Engine Data!"); return 0; } dpy = eng_get_ob(re)->egl.disp; ctx = (EGLContext)context; sfc = (EGLSurface)surface; if ((!context) && (!surface)) { ret = eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (!ret) { ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError()); return 0; } return 1; } if ((eglGetCurrentContext() != ctx) || (eglGetCurrentSurface(EGL_READ) != sfc) || (eglGetCurrentSurface(EGL_DRAW) != sfc) ) { if (flush) evas_outbuf_use(NULL); ret = eglMakeCurrent(dpy, sfc, sfc, ctx); if (!ret) { ERR("eglMakeCurrent() failed! Error Code=%#x", eglGetError()); return 0; } } return 1; }
static void * evgl_eng_native_window_create(void *data) { Render_Engine *re; Outbuf *ob; struct wl_egl_window *win; if (!(re = (Render_Engine *)data)) return NULL; if (!(ob = eng_get_ob(re))) return NULL; if (!(win = wl_egl_window_create(ob->info->info.surface, 1, 1))) { ERR("Could not create wl_egl window: %m"); return NULL; } return (void *)win; }
static int evgl_eng_make_current(void *data, void *surface, void *ctxt, int flush) { Render_Engine *re; Outbuf *ob; EGLContext ctx; EGLSurface surf; int ret = 0; if (!(re = (Render_Engine *)data)) return 0; if (!(ob = eng_get_ob(re))) return 0; ctx = (EGLContext)ctxt; surf = (EGLSurface)surface; if ((!ctxt) && (!surface)) { ret = eglMakeCurrent(ob->egl_disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); if (!ret) { ERR("eglMakeCurrent Failed: %#x", eglGetError()); return 0; } return 1; } if ((eglGetCurrentContext() != ctx) || (eglGetCurrentSurface(EGL_READ) != surf) || (eglGetCurrentSurface(EGL_DRAW) != surf)) { if (flush) eng_window_use(NULL); ret = eglMakeCurrent(ob->egl_disp, surf, surf, ctx); if (!ret) { ERR("eglMakeCurrent Failed: %#x", eglGetError()); return 0; } } return 1; }
static int evgl_eng_context_destroy(void *data, void *context) { Render_Engine *re; EGLBoolean ret = EGL_FALSE; re = (Render_Engine *)data; if ((!re) || (!context)) { ERR("Invalid Render Input Data. Engine: %p, Context: %p", data, context); return 0; } ret = eglDestroyContext(eng_get_ob(re)->egl.disp, (EGLContext)context); if (ret == EGL_TRUE) return 1; return 0; }
static void * evgl_eng_context_create(void *data, void *ctxt, Evas_GL_Context_Version version) { Render_Engine *re; Outbuf *ob; EGLContext context = EGL_NO_CONTEXT; int attrs[3]; if (!(re = (Render_Engine *)data)) return NULL; if (!(ob = eng_get_ob(re))) return NULL; if (version != EVAS_GL_GLES_2_X) { ERR("This engine only supports OpenGL-ES 2.0 contexts for now!"); return NULL; } attrs[0] = EGL_CONTEXT_CLIENT_VERSION; attrs[1] = 2; attrs[2] = EGL_NONE; if (ctxt) { context = eglCreateContext(ob->egl_disp, ob->egl_config, (EGLContext)ctxt, attrs); } else { context = eglCreateContext(ob->egl_disp, ob->egl_config, ob->egl_context[0], attrs); } if (!context) { ERR("Failed to create egl context: %#x", eglGetError()); return NULL; } return (void *)context; }
static void * evgl_eng_window_surface_create(void *data, void *win) { Render_Engine *re; Outbuf *ob; EGLSurface surface = EGL_NO_SURFACE; if (!(re = (Render_Engine *)data)) return NULL; if (!(ob = eng_get_ob(re))) return NULL; surface = eglCreateWindowSurface(ob->egl_disp, ob->egl_config, (EGLNativeWindowType)win, NULL); if (!surface) { ERR("Could not create egl window surface: %#x", eglGetError()); return NULL; } return (void *)surface; }
static void * evgl_eng_native_window_create(void *data) { Render_Engine *re; Evas_Engine_Info_Eglfs *info; struct ANativeWindow *native_window; re = (Render_Engine *)data; if (!re) { ERR("Invalid Render Engine Data!"); return NULL; } info = eng_get_ob(re)->info; if (!info) { ERR("Invalid Evas Engine Eglfs Info!"); return NULL; } EGLNativeWindowType win; win = create_hwcomposernativewindow(); return (void *)win; }
static int evgl_eng_window_surface_destroy(void *data, void *surface) { Render_Engine *re; EGLBoolean ret = EGL_FALSE; re = (Render_Engine *)data; if (!re) { ERR("Invalid Render Engine Data!"); return 0; } if (!surface) { ERR("Invalid surface."); return 0; } ret = eglDestroySurface(eng_get_ob(re)->egl.disp, (EGLSurface)surface); if (ret == EGL_TRUE) return 1; return 0; }
static void * eng_output_setup(void *engine, void *in, unsigned int w, unsigned int h) { Evas_Engine_Info_Eglfs *info = in; Render_Engine *re = NULL; Outbuf *ob = NULL; Render_Output_Swap_Mode swap_mode; swap_mode = evas_render_engine_gl_swap_mode_get(info->info.swap_mode); if (!initted) { glsym_evas_gl_preload_init(); } if (!(re = calloc(1, sizeof(Render_Engine)))) return NULL; /* try to create new outbuf */ ob = evas_outbuf_new(info, w, h, swap_mode); if (!ob) goto on_error; ob->evas = evas; if (!evas_render_engine_gl_generic_init(engine, &re->generic, ob, evas_outbuf_buffer_state_get, evas_outbuf_rot_get, evas_outbuf_reconfigure, evas_outbuf_update_region_first_rect, NULL, evas_outbuf_update_region_new, evas_outbuf_update_region_push, NULL, NULL, evas_outbuf_flush, NULL, evas_outbuf_free, evas_outbuf_use, evas_outbuf_gl_context_get, evas_outbuf_egl_display_get, evas_outbuf_gl_context_new, evas_outbuf_gl_context_use, &evgl_funcs, ob->w, ob->h)) goto on_error; gl_wins++; evas_render_engine_software_generic_merge_mode_set(&re->generic.software); evas_outbuf_use(eng_get_ob(re)); if (!initted) { gl_extn_veto(re); initted = EINA_TRUE; } return re; on_error: /* free outbuf */ evas_outbuf_free(ob); free(re); return NULL; }