From 0f7f4b6de07707031482f6e3e7f7c69f7fb7e855 Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Mon, 28 Mar 2016 12:06:46 -0500 Subject: [PATCH] gl_common: Add API for redirecting render to texture New API allows a context to be redirected to texture. When rendering is complete the texture can be unbound from the frame buffer and used for post-processing effects. Signed-off-by: Derek Foreman Signed-off-by: Mike Blumenkrantz --- .../evas/engines/gl_common/evas_gl_common.h | 15 +++++ .../evas/engines/gl_common/evas_gl_context.c | 68 +++++++++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) 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 4acb119..e16076d 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_common.h @@ -348,6 +348,13 @@ struct _Evas_Engine_GL_Context int gles_version; RGBA_Image *font_surface; + + struct { + GLuint fb; + GLuint texture; + GLuint depth_buffer; + Eina_Bool active : 1; + } redirect; }; struct _Evas_GL_Texture_Pool @@ -525,6 +532,7 @@ 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); @@ -534,6 +542,13 @@ 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); + + void evas_gl_common_tiling_start(Evas_Engine_GL_Context *gc, int rot, int gw, int gh, int cx, int cy, int cw, int ch, 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 9d5ffb0..53810b7 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_context.c +++ b/src/modules/evas/engines/gl_common/evas_gl_context.c @@ -1164,6 +1164,7 @@ 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; @@ -1172,6 +1173,68 @@ evas_gl_common_context_resize(Evas_Engine_GL_Context *gc, int w, int h, int rot) if (_evas_gl_common_context == gc) _evas_gl_common_viewport_set(gc); } +EAPI void +evas_gl_common_context_unredirect(Evas_Engine_GL_Context *gc) +{ + 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; +} + +EAPI void +evas_gl_common_context_redirect(Evas_Engine_GL_Context *gc) +{ + if (gc->redirect.active) evas_gl_common_context_unredirect(gc); + + /* Create a framebuffer object for RTT */ + glGenTextures(1, &gc->redirect.texture); + glBindTexture(GL_TEXTURE_2D, gc->redirect.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); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + 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); + + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, gc->redirect.texture, 0); + + glGenRenderbuffers(1, &gc->redirect.depth_buffer); + glBindRenderbuffer(GL_RENDERBUFFER, gc->redirect.depth_buffer); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, gc->w, gc->h); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, gc->redirect.depth_buffer); + + glBindFramebuffer(GL_FRAMEBUFFER, gc->redirect.fb); + gc->redirect.active = EINA_TRUE; +} + +EAPI GLuint +evas_gl_common_context_redirect_texture_get(Evas_Engine_GL_Context *gc) +{ + if (!gc->redirect.active) return 0; + return gc->redirect.texture; +} + +EAPI void +evas_gl_common_context_redirect_bind(Evas_Engine_GL_Context *gc) +{ + if (!gc->redirect.active) return; + glBindFramebuffer(GL_FRAMEBUFFER, gc->redirect.fb); +} + +EAPI void +evas_gl_common_context_redirect_unbind(Evas_Engine_GL_Context *gc EINA_UNUSED) +{ + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + void evas_gl_common_tiling_start(Evas_Engine_GL_Context *gc EINA_UNUSED, int rot, int gw, int gh, @@ -1262,7 +1325,10 @@ evas_gl_common_context_target_surface_set(Evas_Engine_GL_Context *gc, # endif #endif if (gc->pipe[0].shader.surface == gc->def_surface) - glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0); + { + if (gc->redirect.active) glBindFramebuffer(GL_FRAMEBUFFER, gc->redirect.fb); + else glsym_glBindFramebuffer(GL_FRAMEBUFFER, 0); + } else glsym_glBindFramebuffer(GL_FRAMEBUFFER, surface->tex->pt->fb); _evas_gl_common_viewport_set(gc); -- 2.7.4