efl/src/modules/evas/engines/gl_drm/evas_outbuf.c

833 lines
22 KiB
C

#include "evas_engine.h"
/* local variables */
static Outbuf *_evas_gl_drm_window = NULL;
static EGLContext context = EGL_NO_CONTEXT;
static int win_count = 0;
#ifdef EGL_MESA_platform_gbm
static PFNEGLGETPLATFORMDISPLAYEXTPROC dlsym_eglGetPlatformDisplayEXT = NULL;
static PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC dlsym_eglCreatePlatformWindowSurfaceEXT = NULL;
#endif
static void
_evas_outbuf_gbm_surface_destroy(Outbuf *ob)
{
if (!ob) return;
if (ob->surface)
{
gbm_surface_destroy(ob->surface);
ob->surface = NULL;
}
}
static void
_evas_outbuf_gbm_surface_create(Outbuf *ob, int w, int h)
{
unsigned int format = GBM_FORMAT_XRGB8888;
unsigned int flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
if (!ob) return;
ob->surface =
gbm_surface_create(ob->info->info.gbm, w, h, format, flags);
if (!ob->surface) ERR("Failed to create gbm surface");
}
static void
_evas_outbuf_fb_cb_destroy(struct gbm_bo *bo EINA_UNUSED, void *data)
{
Ecore_Drm2_Fb *fb;
fb = data;
if (fb) ecore_drm2_fb_discard(fb);
}
void
_evas_outbuf_release_fb(Ecore_Drm2_Fb *fb, Ecore_Drm2_Fb_Status status, void *data)
{
struct gbm_bo *bo;
Outbuf *ob;
if (status != ECORE_DRM2_FB_STATUS_RELEASE) return;
ob = data;
bo = ecore_drm2_fb_bo_get(fb);
if ((!ob->surface) || (!bo)) return;
gbm_surface_release_buffer(ob->surface, bo);
}
static Ecore_Drm2_Fb *
_evas_outbuf_fb_get(Outbuf *ob, struct gbm_bo *bo)
{
Ecore_Drm2_Fb *fb;
uint32_t format, hdl, stride;
int w, h;
fb = gbm_bo_get_user_data(bo);
if (fb) return fb;
format = gbm_bo_get_format(bo);
w = gbm_bo_get_width(bo);
h = gbm_bo_get_height(bo);
hdl = gbm_bo_get_handle(bo).u32;
stride = gbm_bo_get_stride(bo);
/* fb->size = fb->stride * fb->h; */
fb =
ecore_drm2_fb_gbm_create(ob->dev, w, h, ob->depth, ob->bpp,
format, hdl, stride, bo);
if (!fb)
{
ERR("Failed to create FBO");
return NULL;
}
ecore_drm2_fb_status_handler_set(fb, _evas_outbuf_release_fb, ob);
gbm_bo_set_user_data(bo, fb, _evas_outbuf_fb_cb_destroy);
return fb;
}
static void
_evas_outbuf_buffer_swap(Outbuf *ob)
{
struct gbm_bo *bo;
Ecore_Drm2_Fb *fb = NULL;
bo = gbm_surface_lock_front_buffer(ob->surface);
if (!bo)
{
ecore_drm2_fb_release(ob->priv.output, EINA_TRUE);
bo = gbm_surface_lock_front_buffer(ob->surface);
}
if (bo) fb = _evas_outbuf_fb_get(ob, bo);
if (fb)
{
if (!ob->priv.plane)
ob->priv.plane = ecore_drm2_plane_assign(ob->priv.output, fb, 0, 0);
else ecore_drm2_plane_fb_set(ob->priv.plane, fb);
ecore_drm2_fb_flip(fb, ob->priv.output);
}
else
WRN("Could not get FBO from Bo");
}
static Eina_Bool
_evas_outbuf_make_current(void *data, void *doit)
{
Outbuf *ob;
if (!(ob = data)) return EINA_FALSE;
if (doit)
{
if (!eglMakeCurrent(ob->egl.disp, ob->egl.surface,
ob->egl.surface, ob->egl.context))
return EINA_FALSE;
}
else
{
if (!eglMakeCurrent(ob->egl.disp, EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT))
return EINA_FALSE;
}
return EINA_TRUE;
}
static Eina_Bool
_evas_outbuf_init(void)
{
static int _init = 0;
if (_init) return EINA_TRUE;
#ifdef EGL_MESA_platform_gbm
{
const char *exts;
exts = eglQueryString(NULL, EGL_EXTENSIONS);
if (_ckext(exts, "EGL_EXT_platform_base"))
{
dlsym_eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)
eglGetProcAddress("eglGetPlatformDisplayEXT");
dlsym_eglCreatePlatformWindowSurfaceEXT = (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)
eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT");
}
}
#endif
_init = 1;
return EINA_TRUE;
}
static Eina_Bool
_evas_outbuf_egl_setup(Outbuf *ob)
{
const char *exts;
int ctx_attr[5];
int cfg_attr[40];
int maj = 0, min = 0, n = 0, i = 0, cn = 0;
EGLint ncfg = 0;
EGLConfig *cfgs;
const GLubyte *vendor, *renderer, *version, *glslversion;
Eina_Bool blacklist = EINA_FALSE;
if (!_evas_outbuf_init())
{
ERR("Could not initialize engine!");
return EINA_FALSE;
}
/* setup gbm egl surface */
ctx_attr[cn++] = EGL_CONTEXT_CLIENT_VERSION;
ctx_attr[cn++] = 2;
if (_extn_have_context_priority)
{
ctx_attr[cn++] = EGL_CONTEXT_PRIORITY_LEVEL_IMG;
ctx_attr[cn++] = EGL_CONTEXT_PRIORITY_HIGH_IMG;
}
ctx_attr[cn++] = EGL_NONE;
cfg_attr[n++] = EGL_RENDERABLE_TYPE;
cfg_attr[n++] = EGL_OPENGL_ES2_BIT;
cfg_attr[n++] = EGL_SURFACE_TYPE;
cfg_attr[n++] = EGL_WINDOW_BIT;
cfg_attr[n++] = EGL_RED_SIZE;
cfg_attr[n++] = 1;
cfg_attr[n++] = EGL_GREEN_SIZE;
cfg_attr[n++] = 1;
cfg_attr[n++] = EGL_BLUE_SIZE;
cfg_attr[n++] = 1;
cfg_attr[n++] = EGL_ALPHA_SIZE;
if (ob->destination_alpha) cfg_attr[n++] = 1;
else cfg_attr[n++] = 0;
cfg_attr[n++] = EGL_NONE;
ob->egl.disp = EGL_NO_DISPLAY;
#ifdef EGL_MESA_platform_gbm
if (dlsym_eglGetPlatformDisplayEXT)
ob->egl.disp = dlsym_eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_MESA,
ob->info->info.gbm,
NULL);
#endif
if (ob->egl.disp == EGL_NO_DISPLAY)
ob->egl.disp = eglGetDisplay((EGLNativeDisplayType)ob->info->info.gbm);
if (ob->egl.disp == EGL_NO_DISPLAY)
{
ERR("eglGetDisplay() fail. code=%#x", eglGetError());
return EINA_FALSE;
}
if (!eglInitialize(ob->egl.disp, &maj, &min))
{
ERR("eglInitialize() fail. code=%#x", eglGetError());
return EINA_FALSE;
}
eglBindAPI(EGL_OPENGL_ES_API);
if (eglGetError() != EGL_SUCCESS)
{
ERR("eglBindAPI() fail. code=%#x", eglGetError());
return EINA_FALSE;
}
eng_egl_symbols(ob->egl.disp);
if (!eglGetConfigs(ob->egl.disp, NULL, 0, &ncfg) || (ncfg == 0))
{
ERR("eglGetConfigs() fail. code=%#x", eglGetError());
return EINA_FALSE;
}
cfgs = malloc(ncfg * sizeof(EGLConfig));
if (!cfgs)
{
ERR("Failed to malloc space for egl configs");
return EINA_FALSE;
}
if (!eglChooseConfig(ob->egl.disp, cfg_attr, cfgs,
ncfg, &ncfg) || (ncfg == 0))
{
ERR("eglChooseConfig() fail. code=%#x", eglGetError());
goto err;
}
for (; i < ncfg; ++i)
{
EGLint format = 0;
if (!eglGetConfigAttrib(ob->egl.disp, cfgs[i], EGL_NATIVE_VISUAL_ID,
&format))
{
ERR("eglGetConfigAttrib() fail. code=%#x", eglGetError());
goto err;
}
if (format == (int)ob->info->info.format)
{
ob->egl.config = cfgs[i];
break;
}
}
if (ob->egl.surface != EGL_NO_SURFACE)
eglDestroySurface(ob->egl.disp, ob->egl.surface);
ob->egl.surface = EGL_NO_SURFACE;
#ifdef EGL_MESA_platform_gbm
if (dlsym_eglCreatePlatformWindowSurfaceEXT)
ob->egl.surface =
dlsym_eglCreatePlatformWindowSurfaceEXT(ob->egl.disp, ob->egl.config,
ob->surface, NULL);
#endif
if (ob->egl.surface == EGL_NO_SURFACE)
ob->egl.surface = eglCreateWindowSurface(ob->egl.disp, ob->egl.config,
(EGLNativeWindowType)ob->surface,
NULL);
if (ob->egl.surface == EGL_NO_SURFACE)
{
ERR("eglCreateWindowSurface() fail for %p. code=%#x",
ob->surface, eglGetError());
goto err;
}
ob->egl.context =
eglCreateContext(ob->egl.disp, ob->egl.config, context, ctx_attr);
if (ob->egl.context == EGL_NO_CONTEXT)
{
ERR("eglCreateContext() fail. code=%#x", eglGetError());
goto err;
}
if (context == EGL_NO_CONTEXT) context = ob->egl.context;
if (eglMakeCurrent(ob->egl.disp, ob->egl.surface,
ob->egl.surface, ob->egl.context) == EGL_FALSE)
{
ERR("eglMakeCurrent() fail. code=%#x", eglGetError());
goto err;
}
exts = eglQueryString(ob->egl.disp, EGL_EXTENSIONS);
glsym_evas_gl_symbols(glsym_eglGetProcAddress, exts);
vendor = glGetString(GL_VENDOR);
renderer = glGetString(GL_RENDERER);
version = glGetString(GL_VERSION);
glslversion = glGetString(GL_SHADING_LANGUAGE_VERSION);
if (!vendor) vendor = (unsigned char *)"-UNKNOWN-";
if (!renderer) renderer = (unsigned char *)"-UNKNOWN-";
if (!version) version = (unsigned char *)"-UNKNOWN-";
if (!glslversion) glslversion = (unsigned char *)"-UNKNOWN-";
if (getenv("EVAS_GL_INFO"))
{
fprintf(stderr, "vendor : %s\n", vendor);
fprintf(stderr, "renderer: %s\n", renderer);
fprintf(stderr, "version : %s\n", version);
fprintf(stderr, "glsl ver: %s\n", glslversion);
}
if (strstr((const char *)vendor, "Mesa Project"))
{
if (strstr((const char *)renderer, "Software Rasterizer"))
blacklist = EINA_TRUE;
}
if (strstr((const char *)renderer, "softpipe"))
blacklist = EINA_TRUE;
if (strstr((const char *)renderer, "llvmpipe"))
blacklist = EINA_TRUE;
if ((blacklist) && (!getenv("EVAS_GL_NO_BLACKLIST")))
{
ERR("OpenGL Driver blacklisted:");
ERR("Vendor: %s", (const char *)vendor);
ERR("Renderer: %s", (const char *)renderer);
ERR("Version: %s", (const char *)version);
goto err;
}
ob->gl_context = glsym_evas_gl_common_context_new();
if (!ob->gl_context) goto err;
#ifdef GL_GLES
ob->gl_context->egldisp = ob->egl.disp;
ob->gl_context->eglctxt = ob->egl.context;
#endif
evas_outbuf_use(ob);
glsym_evas_gl_common_context_resize(ob->gl_context,
ob->w, ob->h, ob->rotation);
ob->surf = EINA_TRUE;
free(cfgs);
return EINA_TRUE;
err:
free(cfgs);
return EINA_FALSE;
}
Outbuf *
evas_outbuf_new(Evas_Engine_Info_GL_Drm *info, int w, int h, Render_Output_Swap_Mode swap_mode)
{
Outbuf *ob;
if (!info) return NULL;
/* try to allocate space for outbuf */
if (!(ob = calloc(1, sizeof(Outbuf)))) return NULL;
win_count++;
ob->w = w;
ob->h = h;
ob->info = info;
ob->depth = info->info.depth;
ob->rotation = info->info.rotation;
ob->destination_alpha = info->info.destination_alpha;
/* ob->vsync = info->info.vsync; */
ob->swap_mode = swap_mode;
ob->dev = info->info.dev;
ob->bpp = info->info.bpp;
ob->format = info->info.format;
ob->priv.output = info->info.output;
/* if ((num = getenv("EVAS_GL_DRM_VSYNC"))) */
/* ob->vsync = atoi(num); */
if ((ob->rotation == 0) || (ob->rotation == 180))
_evas_outbuf_gbm_surface_create(ob, w, h);
else if ((ob->rotation == 90) || (ob->rotation == 270))
_evas_outbuf_gbm_surface_create(ob, h, w);
if (!_evas_outbuf_egl_setup(ob))
{
evas_outbuf_free(ob);
return NULL;
}
return ob;
}
void
evas_outbuf_free(Outbuf *ob)
{
int ref = 0;
win_count--;
evas_outbuf_use(ob);
if (win_count == 0) evas_common_font_ext_clear();
if (ob == _evas_gl_drm_window) _evas_gl_drm_window = NULL;
if (ob->gl_context)
{
ref = ob->gl_context->references - 1;
glsym_evas_gl_common_context_free(ob->gl_context);
}
eglMakeCurrent(ob->egl.disp, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (ob->egl.context != context)
eglDestroyContext(ob->egl.disp, ob->egl.context);
if (ob->egl.surface != EGL_NO_SURFACE)
eglDestroySurface(ob->egl.disp, ob->egl.surface);
_evas_outbuf_gbm_surface_destroy(ob);
if (ref == 0)
{
if (context) eglDestroyContext(ob->egl.disp, context);
eglTerminate(ob->egl.disp);
eglReleaseThread();
context = EGL_NO_CONTEXT;
}
free(ob);
}
void
evas_outbuf_use(Outbuf *ob)
{
Eina_Bool force = EINA_FALSE;
glsym_evas_gl_preload_render_lock(_evas_outbuf_make_current, ob);
if (_evas_gl_drm_window)
{
if (eglGetCurrentContext() != _evas_gl_drm_window->egl.context)
force = EINA_TRUE;
}
if ((_evas_gl_drm_window != ob) || (force))
{
if (_evas_gl_drm_window)
{
glsym_evas_gl_common_context_use(_evas_gl_drm_window->gl_context);
glsym_evas_gl_common_context_flush(_evas_gl_drm_window->gl_context);
}
_evas_gl_drm_window = ob;
if (ob)
{
if (ob->egl.surface != EGL_NO_SURFACE)
{
if (eglMakeCurrent(ob->egl.disp, ob->egl.surface,
ob->egl.surface,
ob->egl.context) == EGL_FALSE)
ERR("eglMakeCurrent() failed!");
}
}
}
if (ob) glsym_evas_gl_common_context_use(ob->gl_context);
}
void
evas_outbuf_resurf(Outbuf *ob)
{
if (ob->surf) return;
if (getenv("EVAS_GL_INFO")) printf("resurf %p\n", ob);
if (ob->egl.surface != EGL_NO_SURFACE)
eglDestroySurface(ob->egl.disp, ob->egl.surface);
ob->egl.surface =
eglCreateWindowSurface(ob->egl.disp, ob->egl.config,
(EGLNativeWindowType)ob->surface, NULL);
if (ob->egl.surface == EGL_NO_SURFACE)
{
ERR("eglCreateWindowSurface() fail for %p. code=%#x",
ob->surface, eglGetError());
return;
}
if (eglMakeCurrent(ob->egl.disp, ob->egl.surface, ob->egl.surface,
ob->egl.context) == EGL_FALSE)
ERR("eglMakeCurrent() failed!");
ob->surf = EINA_TRUE;
}
void
evas_outbuf_unsurf(Outbuf *ob)
{
if (!ob->surf) return;
if (!getenv("EVAS_GL_WIN_RESURF")) return;
if (getenv("EVAS_GL_INFO")) printf("unsurf %p\n", ob);
if (_evas_gl_drm_window)
glsym_evas_gl_common_context_flush(_evas_gl_drm_window->gl_context);
if (_evas_gl_drm_window == ob)
{
eglMakeCurrent(ob->egl.disp, EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (ob->egl.surface != EGL_NO_SURFACE)
eglDestroySurface(ob->egl.disp, ob->egl.surface);
ob->egl.surface = EGL_NO_SURFACE;
_evas_gl_drm_window = NULL;
}
ob->surf = EINA_FALSE;
}
void
evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth)
{
if (depth == OUTBUF_DEPTH_INHERIT) depth = ob->depth;
while (ecore_drm2_fb_release(ob->priv.output, EINA_TRUE));
ob->w = w;
ob->h = h;
ob->rotation = rot;
_evas_outbuf_gbm_surface_destroy(ob);
if ((ob->rotation == 0) || (ob->rotation == 180))
_evas_outbuf_gbm_surface_create(ob, w, h);
else if ((ob->rotation == 90) || (ob->rotation == 270))
_evas_outbuf_gbm_surface_create(ob, h, w);
_evas_outbuf_egl_setup(ob);
}
Render_Output_Swap_Mode
evas_outbuf_buffer_state_get(Outbuf *ob)
{
/* check for valid output buffer */
if (!ob) return MODE_FULL;
ecore_drm2_fb_release(ob->priv.output, EINA_FALSE);
if (ob->swap_mode == MODE_AUTO && _extn_have_buffer_age)
{
Render_Output_Swap_Mode swap_mode;
EGLint age = 0;
eina_evlog("+gl_query_surf_swap_mode", ob, 0.0, NULL);
if (!eglQuerySurface(ob->egl.disp, ob->egl.surface,
EGL_BUFFER_AGE_EXT, &age))
age = 0;
if (age == 1) swap_mode = MODE_COPY;
else if (age == 2) swap_mode = MODE_DOUBLE;
else if (age == 3) swap_mode = MODE_TRIPLE;
else if (age == 4) swap_mode = MODE_QUADRUPLE;
else swap_mode = MODE_FULL;
if ((int)age != ob->prev_age)
{
char buf[16];
snprintf(buf, sizeof(buf), "! %i", (int)age);
eina_evlog("!gl_buffer_age", ob, 0.0, buf);
swap_mode = MODE_FULL;
}
else
{
char buf[16];
snprintf(buf, sizeof(buf), "%i", (int)age);
eina_evlog("!gl_buffer_age", ob, 0.0, buf);
}
ob->prev_age = age;
eina_evlog("-gl_query_surf_swap_mode", ob, 0.0, NULL);
return swap_mode;
}
else
return MODE_FULL;
}
int
evas_outbuf_rot_get(Outbuf *ob)
{
return ob->rotation;
}
Eina_Bool
evas_outbuf_update_region_first_rect(Outbuf *ob)
{
/* ob->gl_context->preserve_bit = GL_COLOR_BUFFER_BIT0_QCOM; */
glsym_evas_gl_preload_render_lock(_evas_outbuf_make_current, ob);
evas_outbuf_use(ob);
if (!_re_wincheck(ob)) return EINA_TRUE;
glsym_evas_gl_common_context_resize(ob->gl_context, ob->w, ob->h, ob->rotation);
glsym_evas_gl_common_context_flush(ob->gl_context);
glsym_evas_gl_common_context_newframe(ob->gl_context);
return EINA_FALSE;
}
static void
_glcoords_convert(int *result, Outbuf *ob, int x, int y, int w, int h)
{
switch (ob->rotation)
{
case 0:
result[0] = x;
result[1] = ob->gl_context->h - (y + h);
result[2] = w;
result[3] = h;
break;
case 90:
result[0] = y;
result[1] = x;
result[2] = h;
result[3] = w;
break;
case 180:
result[0] = ob->gl_context->w - (x + w);
result[1] = y;
result[2] = w;
result[3] = h;
break;
case 270:
result[0] = ob->gl_context->h - (y + h);
result[1] = ob->gl_context->w - (x + w);
result[2] = h;
result[3] = w;
break;
default:
result[0] = x;
result[1] = ob->gl_context->h - (y + h);
result[2] = w;
result[3] = h;
break;
}
}
void
evas_outbuf_damage_region_set(Outbuf *ob, Tilebuf_Rect *damage)
{
if (glsym_eglSetDamageRegionKHR)
{
Tilebuf_Rect *tr;
int *rect, *rects, count;
count = eina_inlist_count(EINA_INLIST_GET(damage));
rects = alloca(sizeof(int) * 4 * count);
rect = rects;
EINA_INLIST_FOREACH(damage, tr)
{
_glcoords_convert(rect, ob, tr->x, tr->y, tr->w, tr->h);
rect += 4;
}
glsym_eglSetDamageRegionKHR(ob->egl.disp, ob->egl.surface, rects, count);
}
}
void *
evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx EINA_UNUSED, int *cy EINA_UNUSED, int *cw EINA_UNUSED, int *ch EINA_UNUSED)
{
if ((w == ob->w) && (h == ob->h))
ob->gl_context->master_clip.enabled = EINA_FALSE;
else
{
ob->gl_context->master_clip.enabled = EINA_TRUE;
ob->gl_context->master_clip.x = x;
ob->gl_context->master_clip.y = y;
ob->gl_context->master_clip.w = w;
ob->gl_context->master_clip.h = h;
}
return ob->gl_context->def_surface;
}
void
evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update EINA_UNUSED, int x EINA_UNUSED, int y EINA_UNUSED, int w EINA_UNUSED, int h EINA_UNUSED)
{
/* Is it really necessary to flush per region ? Shouldn't we be able to
still do that for the full canvas when doing partial update */
if (!_re_wincheck(ob)) return;
ob->drew = EINA_TRUE;
glsym_evas_gl_common_context_flush(ob->gl_context);
}
void
evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *surface_damage, Tilebuf_Rect *buffer_damage EINA_UNUSED, Evas_Render_Mode render_mode)
{
if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end;
if (!_re_wincheck(ob)) goto end;
if (!ob->drew) goto end;
ob->drew = EINA_FALSE;
evas_outbuf_use(ob);
glsym_evas_gl_common_context_done(ob->gl_context);
if (!ob->vsync)
{
if (ob->info->info.vsync) eglSwapInterval(ob->egl.disp, 1);
else eglSwapInterval(ob->egl.disp, 0);
ob->vsync = 1;
}
/* if (ob->info->callback.pre_swap) */
/* ob->info->callback.pre_swap(ob->info->callback.data, ob->evas); */
if ((glsym_eglSwapBuffersWithDamage) && (surface_damage) &&
(ob->swap_mode != MODE_FULL))
{
EGLint num = 0, *result = NULL, i = 0;
Tilebuf_Rect *r;
// if partial swaps can be done use surface_damage
num = eina_inlist_count(EINA_INLIST_GET(surface_damage));
if (num > 0)
{
result = alloca(sizeof(EGLint) * 4 * num);
EINA_INLIST_FOREACH(EINA_INLIST_GET(surface_damage), r)
{
_glcoords_convert(&result[i], ob, r->x, r->y, r->w, r->h);
i += 4;
}
glsym_eglSwapBuffersWithDamage(ob->egl.disp, ob->egl.surface,
result, num);
}
}
else
eglSwapBuffers(ob->egl.disp, ob->egl.surface);
/* if (ob->info->callback.post_swap) */
/* ob->info->callback.post_swap(ob->info->callback.data, ob->evas); */
_evas_outbuf_buffer_swap(ob);
end:
//TODO: Need render unlock after drm page flip?
glsym_evas_gl_preload_render_unlock(_evas_outbuf_make_current, ob);
}
Evas_Engine_GL_Context *
evas_outbuf_gl_context_get(Outbuf *ob)
{
return ob->gl_context;
}
void *
evas_outbuf_egl_display_get(Outbuf *ob)
{
return ob->egl.disp;
}
Context_3D *
evas_outbuf_gl_context_new(Outbuf *ob)
{
Context_3D *ctx;
int context_attrs[3] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
if (!ob) return NULL;
ctx = calloc(1, sizeof(Context_3D));
if (!ctx) return NULL;
ctx->context = eglCreateContext(ob->egl.disp, ob->egl.config,
ob->egl.context, context_attrs);
if (!ctx->context)
{
ERR("EGL context creation failed.");
goto error;
}
ctx->display = ob->egl.disp;
ctx->surface = ob->egl.surface;
return ctx;
error:
free(ctx);
return NULL;
}
void
evas_outbuf_gl_context_free(Context_3D *ctx)
{
eglDestroyContext(ctx->display, ctx->context);
free(ctx);
}
void
evas_outbuf_gl_context_use(Context_3D *ctx)
{
if (eglMakeCurrent(ctx->display, ctx->surface,
ctx->surface, ctx->context) == EGL_FALSE)
ERR("eglMakeCurrent() failed.");
}