wayland_egl: Fix redirect to texture

Previous redirect to texture approach broke multiple window applications
by having only a single redirect per context.  This approach allows
multiple redirections.
This commit is contained in:
Derek Foreman 2016-04-04 11:12:06 -05:00 committed by Mike Blumenkrantz
parent 0ed9d246e5
commit c937248eac
7 changed files with 85 additions and 64 deletions

View File

@ -62,6 +62,7 @@
typedef struct _Evas_GL_Program Evas_GL_Program;
typedef struct _Evas_GL_Shared Evas_GL_Shared;
typedef struct _Evas_Engine_GL_Context Evas_Engine_GL_Context;
typedef struct _Evas_GL_Redirect Evas_GL_Redirect;
typedef struct _Evas_GL_Texture_Pool Evas_GL_Texture_Pool;
typedef struct _Evas_GL_Texture_Alloca Evas_GL_Texture_Alloca;
typedef struct _Evas_GL_Texture Evas_GL_Texture;
@ -349,12 +350,16 @@ struct _Evas_Engine_GL_Context
RGBA_Image *font_surface;
struct {
GLuint current_fb;
};
struct _Evas_GL_Redirect
{
Evas_Engine_GL_Context *gc;
GLuint fb;
GLuint texture;
GLuint depth_buffer;
Eina_Bool active : 1;
} redirect;
};
struct _Evas_GL_Texture_Pool
@ -532,7 +537,6 @@ EAPI void *evas_gl_common_current_context_get(void);
typedef int (*Evas_GL_Preload)(void);
typedef void (*Evas_GL_Common_Image_Call)(Evas_GL_Image *im);
typedef void (*Evas_GL_Common_Context_Call)(Evas_Engine_GL_Context *gc);
typedef GLuint (*Evas_GL_Common_Context_Call_GLuint_Return)(Evas_Engine_GL_Context *gc);
typedef Evas_GL_Image *(*Evas_GL_Common_Image_New_From_Data)(Evas_Engine_GL_Context *gc, unsigned int w, unsigned int h, DATA32 *data, int alpha, Evas_Colorspace cspace);
typedef void (*Evas_GL_Preload_Render_Call)(evas_gl_make_current_cb make_current, void *engine_data);
typedef Evas_Engine_GL_Context *(*Evas_GL_Common_Context_New)(void);
@ -542,11 +546,11 @@ typedef void (*Evas_Gl_Symbols)(void *(*GetProcAddress)(const char *sym));
EAPI void __evas_gl_err(int err, const char *file, const char *func, int line, const char *op);
EAPI void evas_gl_common_context_unredirect(Evas_Engine_GL_Context *gc);
EAPI void evas_gl_common_context_redirect(Evas_Engine_GL_Context *gc);
EAPI GLuint evas_gl_common_context_redirect_texture_get(Evas_Engine_GL_Context *gc);
EAPI void evas_gl_common_context_redirect_bind(Evas_Engine_GL_Context *gc);
EAPI void evas_gl_common_context_redirect_unbind(Evas_Engine_GL_Context *gc);
EAPI Evas_GL_Redirect *evas_gl_common_context_redirect(Evas_Engine_GL_Context *gc);
EAPI void evas_gl_common_context_unredirect(Evas_GL_Redirect *re);
EAPI GLuint evas_gl_common_context_redirect_texture_get(Evas_GL_Redirect *re);
EAPI void evas_gl_common_context_redirect_bind(Evas_GL_Redirect *re);
EAPI void evas_gl_common_context_redirect_unbind(Evas_GL_Redirect *re);
void evas_gl_common_tiling_start(Evas_Engine_GL_Context *gc,

View File

@ -1164,7 +1164,6 @@ EAPI void
evas_gl_common_context_resize(Evas_Engine_GL_Context *gc, int w, int h, int rot)
{
if ((gc->w == w) && (gc->h == h) && (gc->rot == rot)) return;
if (gc->redirect.active) evas_gl_common_context_redirect(gc);
evas_gl_common_context_flush(gc);
gc->change.size = 1;
gc->rot = rot;
@ -1174,23 +1173,27 @@ evas_gl_common_context_resize(Evas_Engine_GL_Context *gc, int w, int h, int rot)
}
EAPI void
evas_gl_common_context_unredirect(Evas_Engine_GL_Context *gc)
evas_gl_common_context_unredirect(Evas_GL_Redirect *re)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteTextures(1, &gc->redirect.texture);
glDeleteRenderbuffers(1, &gc->redirect.depth_buffer);
glDeleteFramebuffers(1, &gc->redirect.fb);
gc->redirect.active = EINA_FALSE;
glDeleteTextures(1, &re->texture);
glDeleteRenderbuffers(1, &re->depth_buffer);
glDeleteFramebuffers(1, &re->fb);
re->gc->current_fb = 0;
re->active = EINA_FALSE;
free(re);
}
EAPI void
EAPI Evas_GL_Redirect *
evas_gl_common_context_redirect(Evas_Engine_GL_Context *gc)
{
if (gc->redirect.active) evas_gl_common_context_unredirect(gc);
Evas_GL_Redirect *out;
out = calloc(1, sizeof(Evas_GL_Redirect));
/* Create a framebuffer object for RTT */
glGenTextures(1, &gc->redirect.texture);
glBindTexture(GL_TEXTURE_2D, gc->redirect.texture);
glGenTextures(1, &out->texture);
glBindTexture(GL_TEXTURE_2D, out->texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@ -1199,40 +1202,49 @@ evas_gl_common_context_redirect(Evas_Engine_GL_Context *gc)
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gc->w, gc->h,
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glGenFramebuffers(1, &gc->redirect.fb);
glBindFramebuffer(GL_FRAMEBUFFER, gc->redirect.fb);
glGenFramebuffers(1, &out->fb);
glBindFramebuffer(GL_FRAMEBUFFER, out->fb);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, gc->redirect.texture, 0);
GL_TEXTURE_2D, out->texture, 0);
glGenRenderbuffers(1, &gc->redirect.depth_buffer);
glBindRenderbuffer(GL_RENDERBUFFER, gc->redirect.depth_buffer);
glGenRenderbuffers(1, &out->depth_buffer);
glBindRenderbuffer(GL_RENDERBUFFER, out->depth_buffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, gc->w, gc->h);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, gc->redirect.depth_buffer);
GL_RENDERBUFFER, out->depth_buffer);
glBindFramebuffer(GL_FRAMEBUFFER, gc->redirect.fb);
gc->redirect.active = EINA_TRUE;
glBindFramebuffer(GL_FRAMEBUFFER, out->fb);
out->gc = gc;
gc->current_fb = out->fb;
out->active = EINA_TRUE;
return out;
}
EAPI GLuint
evas_gl_common_context_redirect_texture_get(Evas_Engine_GL_Context *gc)
evas_gl_common_context_redirect_texture_get(Evas_GL_Redirect *re)
{
if (!gc->redirect.active) return 0;
return gc->redirect.texture;
return re->texture;
}
EAPI void
evas_gl_common_context_redirect_bind(Evas_Engine_GL_Context *gc)
evas_gl_common_context_redirect_bind(Evas_GL_Redirect *re)
{
if (!gc->redirect.active) return;
glBindFramebuffer(GL_FRAMEBUFFER, gc->redirect.fb);
if (re->active) return;
glBindFramebuffer(GL_FRAMEBUFFER, re->fb);
re->gc->current_fb = re->fb;
re->active = EINA_TRUE;
}
EAPI void
evas_gl_common_context_redirect_unbind(Evas_Engine_GL_Context *gc EINA_UNUSED)
evas_gl_common_context_redirect_unbind(Evas_GL_Redirect *re EINA_UNUSED)
{
if (!re->active) return;
glBindFramebuffer(GL_FRAMEBUFFER, 0);
re->active = EINA_FALSE;
re->gc->current_fb = 0;
}
void
@ -1325,10 +1337,7 @@ evas_gl_common_context_target_surface_set(Evas_Engine_GL_Context *gc,
# endif
#endif
if (gc->pipe[0].shader.surface == gc->def_surface)
{
if (gc->redirect.active) glBindFramebuffer(GL_FRAMEBUFFER, gc->redirect.fb);
else glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
glsym_glBindFramebuffer(GL_FRAMEBUFFER, gc->current_fb);
else
glsym_glBindFramebuffer(GL_FRAMEBUFFER, surface->tex->pt->fb);
_evas_gl_common_viewport_set(gc);

View File

@ -62,11 +62,11 @@ Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe = NULL;
Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done = NULL;
Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize = NULL;
Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump = NULL;
Evas_GL_Common_Context_Call glsym_evas_gl_common_context_unredirect = NULL;
Evas_GL_Common_Context_Call glsym_evas_gl_common_context_redirect = NULL;
Evas_GL_Common_Context_Call glsym_evas_gl_common_context_redirect_bind = NULL;
Evas_GL_Common_Context_Call glsym_evas_gl_common_context_redirect_unbind = NULL;
Evas_GL_Common_Context_Call_GLuint_Return glsym_evas_gl_common_context_redirect_texture_get = NULL;
Evas_GL_Redirect *(*glsym_evas_gl_common_context_redirect) (Evas_Engine_GL_Context *gc) = NULL;
void (*glsym_evas_gl_common_context_unredirect) (Evas_GL_Redirect *re) = NULL;
GLuint (*glsym_evas_gl_common_context_redirect_texture_get) (Evas_GL_Redirect *re) = NULL;
void (*glsym_evas_gl_common_context_redirect_bind) (Evas_GL_Redirect *re) = NULL;
void (*glsym_evas_gl_common_context_redirect_unbind) (Evas_GL_Redirect *re) = NULL;
Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock = NULL;
Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock = NULL;
Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_relax = NULL;

View File

@ -85,9 +85,10 @@ struct _Outbuf
Eina_Bool surf : 1;
Model *model;
Eina_Bool redirected : 1;
float offset_x, offset_y;
Evas_GL_Redirect *redirect;
};
struct _Context_3D
@ -107,15 +108,16 @@ extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_use;
extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_newframe;
extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_done;
extern Evas_GL_Common_Context_Resize_Call glsym_evas_gl_common_context_resize;
extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_unredirect;
extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_redirect;
extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_redirect_bind;
extern Evas_GL_Common_Context_Call glsym_evas_gl_common_context_redirect_unbind;
extern Evas_GL_Common_Context_Call_GLuint_Return glsym_evas_gl_common_context_redirect_texture_get;
extern Evas_GL_Common_Buffer_Dump_Call glsym_evas_gl_common_buffer_dump;
extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_lock;
extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock;
extern Evas_GL_Redirect *(*glsym_evas_gl_common_context_redirect) (Evas_Engine_GL_Context *gc);
extern void (*glsym_evas_gl_common_context_unredirect) (Evas_GL_Redirect *re);
extern GLuint (*glsym_evas_gl_common_context_redirect_texture_get) (Evas_GL_Redirect *re);
extern void (*glsym_evas_gl_common_context_redirect_bind) (Evas_GL_Redirect *re);
extern void (*glsym_evas_gl_common_context_redirect_unbind) (Evas_GL_Redirect *re);
extern unsigned int (*glsym_eglSwapBuffersWithDamage) (EGLDisplay a, void *b, const EGLint *d, EGLint c);
extern unsigned int (*glsym_eglSetDamageRegionKHR) (EGLDisplay a, EGLSurface b, EGLint *c, EGLint d);

View File

@ -241,6 +241,7 @@ eng_window_use(Outbuf *gw)
{
glsym_evas_gl_common_context_use(_evas_gl_wl_window->gl_context);
glsym_evas_gl_common_context_flush(_evas_gl_wl_window->gl_context);
if (_evas_gl_wl_window->redirect) glsym_evas_gl_common_context_redirect_unbind(_evas_gl_wl_window->redirect);
}
_evas_gl_wl_window = gw;
@ -261,6 +262,7 @@ eng_window_use(Outbuf *gw)
{
glsym_evas_gl_common_context_use(gw->gl_context);
glsym_evas_gl_common_context_resize(gw->gl_context, gw->w, gw->h, gw->rot);
if (gw->redirect) glsym_evas_gl_common_context_redirect_bind(gw->redirect);
}
}
@ -317,14 +319,16 @@ eng_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth EIN
{
if (!ob->model) ob->model = wobbly_create(0, 0, w, h);
wobbly_resize(ob->model, w, h);
glsym_evas_gl_common_context_unredirect(ob->gl_context);
ob->redirected = EINA_FALSE;
if (ob->redirect)
glsym_evas_gl_common_context_unredirect(ob->redirect);
ob->w = w;
ob->h = h;
ob->rot = rot;
eng_window_use(ob);
glsym_evas_gl_common_context_resize(ob->gl_context, w, h, rot);
if (ob->redirect)
ob->redirect = glsym_evas_gl_common_context_redirect(ob->gl_context);
if (ob->win)
{
@ -367,7 +371,7 @@ eng_outbuf_rotation_get(Outbuf *ob)
Render_Engine_Swap_Mode
eng_outbuf_swap_mode_get(Outbuf *ob)
{
if (ob->redirected)
if (ob->redirect)
{
ob->prev_age = 0;
return MODE_FULL;
@ -522,9 +526,9 @@ eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode)
if (ob->model) effect_continues = wobbly_process(ob->model, ob->info,
ob->w, ob->h,
ob->redirected);
!!ob->redirect);
if (ob->redirected)
if (ob->redirect)
{
float tlx, tly, brx, bry;
int w, h;
@ -538,12 +542,12 @@ eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode)
tly - ob->offset_y);
ob->offset_x = tlx;
ob->offset_y = tly;
glsym_evas_gl_common_context_redirect_unbind(ob->gl_context);
glsym_evas_gl_common_context_redirect_unbind(ob->redirect);
glViewport(0, 0, w, h);
wobbly_draw(ob->gl_context, ob->model);
wobbly_draw(ob->redirect, ob->model);
wl_surface_set_opaque_region(ob->info->info.surface, NULL);
eglSwapBuffers(ob->egl_disp, ob->egl_surface[0]);
glsym_evas_gl_common_context_redirect_bind(ob->gl_context);
glsym_evas_gl_common_context_redirect_bind(ob->redirect);
glViewport(0, 0, ob->w, ob->h);
}
else if ((glsym_eglSwapBuffersWithDamage) && (rects) &&
@ -569,20 +573,22 @@ eng_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode)
else
eglSwapBuffers(ob->egl_disp, ob->egl_surface[0]);
if (ob->redirected && !effect_continues) ob->info->wobbling = EINA_TRUE;
if (ob->redirect && !effect_continues) ob->info->wobbling = EINA_TRUE;
else ob->info->wobbling = effect_continues;
if (effect_continues)
{
glsym_evas_gl_common_context_redirect(ob->gl_context);
ob->redirected = EINA_TRUE;
if (ob->redirect)
glsym_evas_gl_common_context_unredirect(ob->redirect);
ob->redirect = glsym_evas_gl_common_context_redirect(ob->gl_context);
}
else
{
ob->offset_x = 0;
ob->offset_y = 0;
glsym_evas_gl_common_context_unredirect(ob->gl_context);
ob->redirected = EINA_FALSE;
if (ob->redirect)
glsym_evas_gl_common_context_unredirect(ob->redirect);
ob->redirect = NULL;
}
if (ob->info->callback.post_swap)
ob->info->callback.post_swap(ob->info->callback.data, ob->evas);

View File

@ -812,14 +812,14 @@ wobbly_resize(Model *m, int dwidth, int dheight)
}
void
wobbly_draw(Evas_Engine_GL_Context *gl_context, Model *m)
wobbly_draw(Evas_GL_Redirect *re, Model *m)
{
GLuint tex;
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(m->prog);
tex = glsym_evas_gl_common_context_redirect_texture_get(gl_context);
tex = glsym_evas_gl_common_context_redirect_texture_get(re);
glBindTexture(GL_TEXTURE_2D, tex);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), m->vertices);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), m->vertices + 2);

View File

@ -41,7 +41,7 @@ void
wobbly_resize(Model *m, int dw, int dh);
void
wobbly_draw(Evas_Engine_GL_Context *gl_context, Model *m);
wobbly_draw(Evas_GL_Redirect *re, Model *m);
Eina_Bool
wobbly_process(Model *m, Evas_Engine_Info_Wayland_Egl *info, int w, int h, Eina_Bool redirected);