From 307a18860c1b9a23afb836825d7f74af1dd461fe Mon Sep 17 00:00:00 2001 From: Matthew Allum Date: Fri, 1 Feb 2008 15:29:00 +0000 Subject: [PATCH] 2008-02-01 Matthew Allum * clutter/clutter-feature.h: * clutter/clutter-texture.c: * clutter/clutter-texture.h: * clutter/cogl/cogl.h: * clutter/cogl/gl/cogl.c: * clutter/cogl/gles/cogl.c: * tests/Makefile.am: * tests/test.fbo.c: Add initial support for FBO's in Clutter (OpenGL only so far). See new clutter_texture_new_from_actor() Initial implementation, needs work. * clutter/x11/clutter-stage-x11.c: (clutter_stage_x11_set_cursor_visible): Fall back to again not relying on xfixes to hide cursor. *sigh* * clutter/clutter-deprecated.h: Add clutter_group_find_child_by_id --- cogl.h | 17 ++++++ gl/cogl.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++- gles/cogl.c | 30 +++++++++++ 3 files changed, 199 insertions(+), 1 deletion(-) diff --git a/cogl.h b/cogl.h index ae3d2a04f..c03717226 100644 --- a/cogl.h +++ b/cogl.h @@ -264,6 +264,23 @@ void cogl_program_uniform_1f (COGLint uniform_no, gfloat value); +/* Offscreen - FBO support */ + +COGLuint +cogl_offscreen_create (COGLuint target_texture); + +void +cogl_offscreen_destroy (COGLuint offscreen_handle); + +void +cogl_offscreen_redirect_start (COGLuint offscreen_handle, + gint width, + gint height); + +void +cogl_offscreen_redirect_end (COGLuint offscreen_handle, + gint width, + gint height); G_END_DECLS diff --git a/gl/cogl.c b/gl/cogl.c index a09914cb6..25f1f1da8 100644 --- a/gl/cogl.c +++ b/gl/cogl.c @@ -41,6 +41,21 @@ typedef CoglFuncPtr (*GLXGetProcAddressProc) (const guint8 *procName); static gulong __enable_flags = 0; +/* FBO Procs */ +typedef void (*GenFramebuffers) (GLsizei n, GLuint *ids); +typedef void (*BindFramebuffer) (GLenum target, GLuint framebuffer); +typedef void (*FramebufferTexture2D) (GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, + GLint level); +typedef GLenum (*CheckFramebufferStatus)(GLenum target); +typedef void (*DeleteFramebuffers) (GLsizei n, const GLuint *framebuffers); + +static GenFramebuffers _gen_framebuffers = NULL; +static BindFramebuffer _bind_framebuffer = NULL; +static FramebufferTexture2D _framebuffer_texture_2d = NULL; +static CheckFramebufferStatus _check_framebuffer_status = NULL; +static DeleteFramebuffers _delete_framebuffers = NULL; + #if COGL_DEBUG struct token_string { @@ -189,7 +204,6 @@ cogl_paint_init (const ClutterColor *color) glDepthFunc (GL_LEQUAL); cogl_enable (CGL_ENABLE_BLEND); - glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } @@ -295,6 +309,7 @@ cogl_enable (gulong flags) } #endif +#if 0 if (flags & CGL_ENABLE_ALPHA_TEST) { if (!(__enable_flags & CGL_ENABLE_ALPHA_TEST)) @@ -308,6 +323,7 @@ cogl_enable (gulong flags) glDisable (GL_ALPHA_TEST); __enable_flags &= ~CGL_ENABLE_ALPHA_TEST; } +#endif } void @@ -648,6 +664,35 @@ cogl_get_features () flags |= CLUTTER_FEATURE_SHADERS_GLSL; } + if (cogl_check_extension ("GL_EXT_framebuffer_object", gl_extensions) || + cogl_check_extension ("GL_ARB_framebuffer_object", gl_extensions)) + { + _gen_framebuffers = + (GenFramebuffers) cogl_get_proc_address ("glGenFramebuffersEXT"); + + _bind_framebuffer = + (BindFramebuffer) cogl_get_proc_address ("glBindFramebufferEXT"); + + _framebuffer_texture_2d = + (FramebufferTexture2D) + cogl_get_proc_address ("glFramebufferTexture2DEXT"); + + _check_framebuffer_status = + (CheckFramebufferStatus) + cogl_get_proc_address ("glCheckFramebufferStatusEXT"); + + _delete_framebuffers = + (DeleteFramebuffers) + cogl_get_proc_address ("glDeleteFramebuffersEXT"); + + if (_gen_framebuffers + && _bind_framebuffer + && _framebuffer_texture_2d + && _check_framebuffer_status + && _delete_framebuffers) + flags |= CLUTTER_FEATURE_OFFSCREEN; + } + return flags; } @@ -774,6 +819,112 @@ cogl_fog_set (const ClutterColor *fog_color, glFogf (GL_FOG_END, CLUTTER_FIXED_TO_FLOAT (stop)); } +/* FBOs - offscreen */ + +COGLuint +cogl_offscreen_create (COGLuint target_texture) +{ +#ifdef GL_FRAMEBUFFER_EXT + COGLuint handle; + GLenum status; + + if (_gen_framebuffers == NULL + || _bind_framebuffer == NULL + || _framebuffer_texture_2d == NULL + || _check_framebuffer_status == NULL) + { + /* tmp warning - need error reporting */ + g_warning("Missing GL_FRAMEBUFFER_EXT API\n"); + return 0; + } + + _gen_framebuffers (1, &handle); + _bind_framebuffer (GL_FRAMEBUFFER_EXT, handle); + + _framebuffer_texture_2d (GL_FRAMEBUFFER_EXT, + GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_RECTANGLE_ARB, + target_texture, + 0); + + status = _check_framebuffer_status (GL_FRAMEBUFFER_EXT); + + if (status != GL_FRAMEBUFFER_COMPLETE_EXT) + { + _delete_framebuffers (1, &handle); + return 0; + } + + _bind_framebuffer (GL_FRAMEBUFFER_EXT, 0); + + return handle; +#else + /* tmp warning - need error reporting */ + g_warning("No GL_FRAMEBUFFER_EXT\n"); + return 0; +#endif +} + +void +cogl_offscreen_destroy (COGLuint offscreen_handle) +{ + if (_delete_framebuffers) + _delete_framebuffers (1, &offscreen_handle); +} + +void +cogl_offscreen_redirect_start (COGLuint offscreen_handle, + gint width, + gint height) +{ + /* FIXME: silly we need to pass width / height to init viewport */ +#ifdef GL_FRAMEBUFFER_EXT + + if (_bind_framebuffer == NULL) + return; + + _bind_framebuffer (GL_FRAMEBUFFER_EXT, offscreen_handle); + + glViewport (0, 0, width, height); + + glMatrixMode (GL_PROJECTION); + glPushMatrix(); + glLoadIdentity (); + + glMatrixMode (GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity (); + + glTranslatef (-1.0f, -1.0f, 0.0f); + glScalef (2.0f / (float)width, 2.0f / (float)height, 1.0f); +#endif +} + +void +cogl_offscreen_redirect_end (COGLuint offscreen_handle, + gint width, + gint height) +{ + /* FIXME: silly we need to pass width / height to reset to */ + if (_bind_framebuffer == NULL) + return; + +#ifdef GL_FRAMEBUFFER_EXT + glViewport (0, 0, width, height); + + glMatrixMode (GL_PROJECTION); + glPopMatrix(); + + glMatrixMode (GL_MODELVIEW); + glPopMatrix(); + + _bind_framebuffer (GL_FRAMEBUFFER_EXT, 0); +#endif +} + + +/* Shader Magic follows */ + #ifdef __GNUC__ #define PROC(rettype, retval, procname, args...) \ diff --git a/gles/cogl.c b/gles/cogl.c index b1a15da98..f972dc922 100644 --- a/gles/cogl.c +++ b/gles/cogl.c @@ -645,6 +645,36 @@ cogl_fog_set (const ClutterColor *fog_color, glFogx (GL_FOG_END, (GLfixed) z_far); } +/* Offscreen - TODO: possible support from FBO's */ + +COGLuint +cogl_offscreen_create (COGLuint target_texture) +{ + return 0; +} + +void +cogl_offscreen_destroy (COGLuint offscreen_handle) +{ +} + +void +cogl_offscreen_redirect_start (COGLuint offscreen_handle, + gint width, + gint height) +{ +} + +void +cogl_offscreen_redirect_end (COGLuint offscreen_handle, + gint width, + gint height) +{ +} + + +/* Shaders, no support on regular OpenGL 1.1 */ + COGLhandle cogl_create_program (void) {