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 <derekf@osg.samsung.com>
Signed-off-by: Mike Blumenkrantz <zmike@osg.samsung.com>
This commit is contained in:
Derek Foreman 2016-03-28 12:06:46 -05:00 committed by Mike Blumenkrantz
parent 17bb2d60ca
commit 0f7f4b6de0
2 changed files with 82 additions and 1 deletions

View File

@ -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,

View File

@ -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);