From c937248eac0d0996f3cbc31a348b92c8baac2ec3 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Mon, 4 Apr 2016 11:12:06 -0500 Subject: [PATCH] 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. --- .../evas/engines/gl_common/evas_gl_common.h | 20 ++++--- .../evas/engines/gl_common/evas_gl_context.c | 67 ++++++++++++---------- src/modules/evas/engines/wayland_egl/evas_engine.c | 10 ++-- src/modules/evas/engines/wayland_egl/evas_engine.h | 14 +++-- .../evas/engines/wayland_egl/evas_wl_main.c | 32 ++++++----- src/modules/evas/engines/wayland_egl/www.c | 4 +- src/modules/evas/engines/wayland_egl/www.h | 2 +- 7 files changed, 85 insertions(+), 64 deletions(-) diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h index e16076d..48aa56c 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -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, diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c b/src/modules/evas/engines/gl_common/evas_gl_context.c index 53810b7..ab2d283 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -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); diff --git a/src/modules/evas/engines/wayland_egl/evas_engine.c b/src/modules/evas/engines/wayland_egl/evas_engine.c index aef2120..4945a70 100644 --- a/src/modules/evas/engines/wayland_egl/evas_engine.c +++ b/src/modules/evas/engines/wayland_egl/evas_engine.c @@ -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; diff --git a/src/modules/evas/engines/wayland_egl/evas_engine.h b/src/modules/evas/engines/wayland_egl/evas_engine.h index a7bc7c7..357c9df 100644 --- a/src/modules/evas/engines/wayland_egl/evas_engine.h +++ b/src/modules/evas/engines/wayland_egl/evas_engine.h @@ -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); diff --git a/src/modules/evas/engines/wayland_egl/evas_wl_main.c b/src/modules/evas/engines/wayland_egl/evas_wl_main.c index 59806cf..00c0f908 100644 --- a/src/modules/evas/engines/wayland_egl/evas_wl_main.c +++ b/src/modules/evas/engines/wayland_egl/evas_wl_main.c @@ -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); diff --git a/src/modules/evas/engines/wayland_egl/www.c b/src/modules/evas/engines/wayland_egl/www.c index c6bb5ca..80c0936 100644 --- a/src/modules/evas/engines/wayland_egl/www.c +++ b/src/modules/evas/engines/wayland_egl/www.c @@ -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); diff --git a/src/modules/evas/engines/wayland_egl/www.h b/src/modules/evas/engines/wayland_egl/www.h index 99fd09f..c3c0272 100644 --- a/src/modules/evas/engines/wayland_egl/www.h +++ b/src/modules/evas/engines/wayland_egl/www.h @@ -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); -- 2.7.4