wayland_egl: Fix redirect to texture
authorDerek Foreman <derekf@osg.samsung.com>
Mon, 4 Apr 2016 16:12:06 +0000 (11:12 -0500)
committerMike Blumenkrantz <zmike@osg.samsung.com>
Mon, 4 Apr 2016 16:13:23 +0000 (12:13 -0400)
Previous redirect to texture approach broke multiple window applications
by having only a single redirect per context.  This approach allows
multiple redirections.

src/modules/evas/engines/gl_common/evas_gl_common.h
src/modules/evas/engines/gl_common/evas_gl_context.c
src/modules/evas/engines/wayland_egl/evas_engine.c
src/modules/evas/engines/wayland_egl/evas_engine.h
src/modules/evas/engines/wayland_egl/evas_wl_main.c
src/modules/evas/engines/wayland_egl/www.c
src/modules/evas/engines/wayland_egl/www.h

index e16076d..48aa56c 100644 (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,
index 53810b7..ab2d283 100644 (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);
index aef2120..4945a70 100644 (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;
index a7bc7c7..357c9df 100644 (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);
 
index 59806cf..00c0f90 100644 (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);
index c6bb5ca..80c0936 100644 (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);
index 99fd09f..c3c0272 100644 (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);