diff --git a/ChangeLog b/ChangeLog index 92565eb16..f71424c1d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-02-03 Matthew Allum + + * clutter/clutter-shader.c: + Minor formatting cleanups to fit in 80 cols. + + * clutter/clutter-texture.c: + More safety checks, clean ups in clutter_texture_new_from_actor() + + * clutter/cogl/gl/cogl.c: + Always clear the FBO initially when rendering + + * tests/test-fbo.c: + Overhall the test as to be more useful (and show current issues) + 2008-02-02 Matthew Allum * clutter/clutter-timeline.c: diff --git a/clutter/clutter-shader.c b/clutter/clutter-shader.c index ffc4b1f54..edcf2df03 100644 --- a/clutter/clutter-shader.c +++ b/clutter/clutter-shader.c @@ -93,8 +93,6 @@ enum PROP_ENABLED }; - - G_DEFINE_TYPE (ClutterShader, clutter_shader, G_TYPE_OBJECT); G_CONST_RETURN gchar *clutter_shader_get_source (ClutterShader *shader, @@ -130,10 +128,12 @@ clutter_shader_set_property (GObject *object, switch (prop_id) { case PROP_VERTEX_SOURCE: - clutter_shader_set_vertex_source (shader, g_value_get_string (value), -1); + clutter_shader_set_vertex_source (shader, + g_value_get_string (value), -1); break; case PROP_FRAGMENT_SOURCE: - clutter_shader_set_fragment_source (shader, g_value_get_string (value), -1); + clutter_shader_set_fragment_source (shader, + g_value_get_string (value), -1); break; case PROP_ENABLED: clutter_shader_set_is_enabled (shader, g_value_get_boolean (value)); @@ -183,7 +183,10 @@ clutter_shader_constructor (GType type, { GObject *object; - object = G_OBJECT_CLASS (clutter_shader_parent_class)->constructor (type, n_params, params); + object + = G_OBJECT_CLASS (clutter_shader_parent_class)->constructor (type, + n_params, + params); /* add this instance to the global list of shaders */ clutter_shaders_list = g_list_prepend (clutter_shaders_list, object); @@ -211,13 +214,14 @@ clutter_shader_class_init (ClutterShaderClass *klass) * * Since: 0.6 */ - g_object_class_install_property (object_class, - PROP_VERTEX_SOURCE, - g_param_spec_string ("vertex-source", - "Vertex Source", - "Source of vertex shader", - NULL, - CLUTTER_PARAM_READWRITE)); + g_object_class_install_property + (object_class, + PROP_VERTEX_SOURCE, + g_param_spec_string ("vertex-source", + "Vertex Source", + "Source of vertex shader", + NULL, + CLUTTER_PARAM_READWRITE)); /** * ClutterShader:fragment-source: * @@ -225,27 +229,30 @@ clutter_shader_class_init (ClutterShaderClass *klass) * * Since: 0.6 */ - g_object_class_install_property (object_class, - PROP_FRAGMENT_SOURCE, - g_param_spec_string ("fragment-source", - "Fragment Source", - "Source of fragment shader", - NULL, - CLUTTER_PARAM_READWRITE)); + g_object_class_install_property + (object_class, + PROP_FRAGMENT_SOURCE, + g_param_spec_string ("fragment-source", + "Fragment Source", + "Source of fragment shader", + NULL, + CLUTTER_PARAM_READWRITE)); /** * ClutterShader:bound: * - * Whether the shader is bound (compiled and linked, ready for use in the GL context). + * Whether the shader is bound (compiled and linked, ready for use + * in the GL context). * * Since: 0.6 */ - g_object_class_install_property (object_class, - PROP_BOUND, - g_param_spec_boolean ("bound", - "Bound", - "Whether the shader is bound", - FALSE, - CLUTTER_PARAM_READABLE)); + g_object_class_install_property + (object_class, + PROP_BOUND, + g_param_spec_boolean ("bound", + "Bound", + "Whether the shader is bound", + FALSE, + CLUTTER_PARAM_READABLE)); /** * ClutterShader:enabled: * @@ -253,13 +260,14 @@ clutter_shader_class_init (ClutterShaderClass *klass) * * Since: 0.6 */ - g_object_class_install_property (object_class, - PROP_ENABLED, - g_param_spec_boolean ("enabled", - "Enabled", - "Whether the shader is enabled", - FALSE, - CLUTTER_PARAM_READWRITE)); + g_object_class_install_property + (object_class, + PROP_ENABLED, + g_param_spec_boolean ("enabled", + "Enabled", + "Whether the shader is enabled", + FALSE, + CLUTTER_PARAM_READWRITE)); } static void @@ -337,7 +345,8 @@ clutter_shader_set_fragment_source (ClutterShader *shader, g_free (priv->fragment_source); } - CLUTTER_NOTE (SHADER, "setting fragment shader (GLSL:%s, len:%" G_GSSIZE_FORMAT ")", + CLUTTER_NOTE (SHADER, "setting fragment shader (GLSL:%s, len:%" + G_GSSIZE_FORMAT ")", is_glsl ? "yes" : "no", length); @@ -345,7 +354,6 @@ clutter_shader_set_fragment_source (ClutterShader *shader, priv->fragment_is_glsl = is_glsl; } - /** * clutter_shader_set_vertex_source: * @shader: a #ClutterShader @@ -387,7 +395,8 @@ clutter_shader_set_vertex_source (ClutterShader *shader, g_free (priv->vertex_source); } - CLUTTER_NOTE (SHADER, "setting vertex shader (GLSL:%s, len:%" G_GSSIZE_FORMAT ")", + CLUTTER_NOTE (SHADER, "setting vertex shader (GLSL:%s, len:%" + G_GSSIZE_FORMAT ")", is_glsl ? "yes" : "no", length); @@ -548,7 +557,8 @@ clutter_shader_release (ClutterShader *shader) * clutter_shader_is_bound: * @shader: a #ClutterShader * - * Checks whether @shader is is currently compiled, linked and bound to the GL context. + * Checks whether @shader is is currently compiled, linked and bound + * to the GL context. * * Return value: %TRUE if the shader is compiled, linked and ready for use. * @@ -679,9 +689,9 @@ clutter_shader_release_all (void) * * Query the current GLSL fragment source set on @shader. * - * Return value: the source of the fragment shader for this ClutterShader object - * or %NULL. The returned string is owned by the shader object and should never - * be modified or freed + * Return value: the source of the fragment shader for this + * ClutterShader object or %NULL. The returned string is owned by the + * shader object and should never be modified or freed * * Since: 0.6 */ @@ -698,9 +708,9 @@ clutter_shader_get_fragment_source (ClutterShader *shader) * * Query the current GLSL vertex source set on @shader. * - * Return value: the source of the vertex shader for this ClutterShader object - * or %NULL. The returned string is owned by the shader object and should never - * be modified or freed + * Return value: the source of the vertex shader for this + * ClutterShader object or %NULL. The returned string is owned by the + * shader object and should never be modified or freed * * Since: 0.6 */ diff --git a/clutter/clutter-texture.c b/clutter/clutter-texture.c index e759c0dcf..949561ed1 100644 --- a/clutter/clutter-texture.c +++ b/clutter/clutter-texture.c @@ -2103,6 +2103,7 @@ clutter_texture_set_area_from_rgb_data (ClutterTexture *texture, return TRUE; } + /** * clutter_texture_new_from_actor: * @actor: A #ClutterActor @@ -2136,36 +2137,47 @@ clutter_texture_new_from_actor (ClutterActor *actor) * - Have the source actor as a prop? */ + g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL); + if (clutter_feature_available (CLUTTER_FEATURE_TEXTURE_RECTANGLE) == FALSE) return NULL; if (clutter_feature_available (CLUTTER_FEATURE_OFFSCREEN) == FALSE) return NULL; + if (!CLUTTER_ACTOR_IS_REALIZED (actor)) + { + clutter_actor_realize (actor); + + if (!CLUTTER_ACTOR_IS_REALIZED (actor)) + return NULL; + } + + /* FIXME abs size - usually fails with 0,0 */ + clutter_actor_get_abs_size (actor, &w, &h); + // printf("abs size is %ix%i\n", w, h); + + /* Wont work with any kind of transform on actor */ + clutter_actor_get_size (actor, &w, &h); + + if (w == 0 || h == 0) + return NULL; + + if (!cogl_texture_can_size (CGL_TEXTURE_RECTANGLE_ARB, + CGL_RGBA, PIXEL_TYPE, w, h)) + return NULL; + texture = g_object_new (CLUTTER_TYPE_TEXTURE, NULL); priv = texture->priv; - priv->fbo_source = actor; - - if (!CLUTTER_ACTOR_IS_REALIZED (priv->fbo_source)) - clutter_actor_realize (priv->fbo_source); - - - /* FIXME: just ref ? */ - clutter_actor_set_parent (actor, CLUTTER_ACTOR(texture)); - - /* FIXME abs size */ - /*clutter_actor_get_abs_size (priv->fbo_source, &w, &h);*/ - clutter_actor_get_size (actor, &w, &h); - - /* FIXME: Check we can actually create a texture this large */ - priv->width = w; - priv->height = h; + priv->fbo_source = g_object_ref(actor); + priv->width = w; + priv->height = h; priv->target_type = CGL_TEXTURE_RECTANGLE_ARB; priv->pixel_format = CGL_RGBA; - priv->pixel_type = PIXEL_TYPE; + priv->pixel_type = PIXEL_TYPE; priv->is_tiled = 0; priv->tiles = g_new (COGLuint, 1); @@ -2185,7 +2197,7 @@ clutter_texture_new_from_actor (ClutterActor *actor) priv->fbo_handle = cogl_offscreen_create (priv->tiles[0]); - clutter_actor_set_size (texture, w, h); + clutter_actor_set_size (CLUTTER_ACTOR(texture), w, h); return CLUTTER_ACTOR(texture); } diff --git a/clutter/cogl/gl/cogl.c b/clutter/cogl/gl/cogl.c index 02f8e4e4b..39a673551 100644 --- a/clutter/cogl/gl/cogl.c +++ b/clutter/cogl/gl/cogl.c @@ -909,6 +909,11 @@ cogl_offscreen_redirect_start (COGLuint offscreen_handle, glTranslatef (-1.0f, -1.0f, 0.0f); glScalef (2.0f / (float)width, 2.0f / (float)height, 1.0f); + + /* Clear the scene, appears needed on some backends - OSX */ + glClearColor (0.0, 0.0, 0.0, 0.0); + glClear (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + #endif } diff --git a/tests/test-fbo.c b/tests/test-fbo.c index 0bacced20..1a06ec21b 100644 --- a/tests/test-fbo.c +++ b/tests/test-fbo.c @@ -6,60 +6,36 @@ #include #include - -gint -main (gint argc, - gchar *argv[]) +ClutterActor* +make_source(void) { - ClutterColor color={0x33, 0x44, 0x55, 0xff}; - ClutterActor *fbo; - ClutterActor *actor; - ClutterActor *actor2; - ClutterActor *group; - ClutterShader *shader; - ClutterActor *stage; - ClutterActor *rectangle; - ClutterActor *clone; + ClutterActor *source, *actor; GdkPixbuf *pixbuf; GError *error = NULL; - clutter_init (&argc, &argv); - - stage = clutter_stage_get_default (); - clutter_stage_set_color (CLUTTER_STAGE (stage), &color); + ClutterColor yellow = {0xff, 0xff, 0x00, 0xff}; pixbuf = gdk_pixbuf_new_from_file ("redhand.png", &error); if (!pixbuf) g_error("pixbuf load failed: %s", error ? error->message : "Unknown"); - /* actor = clutter_texture_new_from_pixbuf (pixbuf);*/ + source = clutter_group_new(); + actor = clutter_texture_new_from_pixbuf (pixbuf); + clutter_group_add (source, actor); - group = clutter_group_new (); - { - ClutterColor nothing = {0, 0,0,0}; - rectangle = clutter_rectangle_new_with_color (¬hing); - clutter_actor_set_size (rectangle, 800, 270); - } - - actor2 = clutter_texture_new_from_pixbuf (pixbuf); - clutter_container_add_actor (CLUTTER_CONTAINER (group), actor2); - { - ClutterColor yellow = {0xff, 0xff, 0x00, 0xff}; - actor = clutter_label_new_with_text ("Sans 50px", "Hello hadyness"); - clutter_label_set_color (CLUTTER_LABEL (actor), &yellow); - } + actor = clutter_label_new_with_text ("Sans Bold 50px", "Clutter"); - clutter_container_add_actor (CLUTTER_CONTAINER (group), actor); - clutter_container_add_actor (CLUTTER_CONTAINER (group), rectangle); - clutter_actor_set_position (actor, 0, 15); + clutter_label_set_color (CLUTTER_LABEL (actor), &yellow); + clutter_actor_set_y (actor, clutter_actor_get_height(source) + 5); + clutter_group_add (source, actor); - clutter_actor_show_all (group); + return source; +} - fbo = clutter_texture_new_from_actor (group); - - clutter_container_add_actor (CLUTTER_CONTAINER (stage), fbo); - clutter_actor_set_position (fbo, 20, 120); - clutter_actor_set_position (actor2, 130, 20); +ClutterShader* +make_shader(void) +{ + ClutterShader *shader; shader = clutter_shader_new (); clutter_shader_set_fragment_source (shader, @@ -86,14 +62,113 @@ main (gint argc, -1 ); - clone = clutter_clone_texture_new (fbo); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), clone); - clutter_actor_set_position (clone, 40, 300); + return shader; +} + +gint +main (gint argc, + gchar *argv[]) +{ + ClutterColor blue = {0x33, 0x44, 0x55, 0xff}; + + ClutterActor *fbo; + ClutterActor *onscreen_source, *offscreen_source, *trans_source; + ClutterActor *foo_source; + ClutterActor *stage; + ClutterActor *clone; + ClutterShader *shader; + gint padx, pady; + + clutter_init (&argc, &argv); + + if (clutter_feature_available (CLUTTER_FEATURE_OFFSCREEN) == FALSE) + g_error("This test requires CLUTTER_FEATURE_OFFSCREEN"); + + stage = clutter_stage_get_default (); + clutter_stage_set_color (CLUTTER_STAGE (stage), &blue); + + /* Create the first source */ + onscreen_source = make_source(); + clutter_actor_show_all (onscreen_source); + clutter_group_add (stage, onscreen_source); + + /* Basic sizing for alignment */ + padx = clutter_actor_get_width (onscreen_source) + 10; + pady = clutter_actor_get_height (onscreen_source) + 10; + clutter_actor_set_size (stage, padx*4, pady*2); + + + /* Second hand from fbo onscreen */ + if ((fbo = clutter_texture_new_from_actor (onscreen_source)) == NULL) + g_error("onscreen fbo creation failed"); + + clutter_actor_set_position (fbo, padx, 0); + clutter_group_add (stage, fbo); + + /* apply a shader to it */ + shader = make_shader(); + clutter_actor_apply_shader (fbo, shader); + clutter_actor_set_shader_param (fbo, "radius", 2.0); + + + /* Third from cloning the fbo texture */ + clone = clutter_clone_texture_new (CLUTTER_TEXTURE(fbo)); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), clone); + clutter_actor_set_position (clone, padx*2, 0); + + + /* Forth - an offscreen source */ + offscreen_source = make_source(); + clutter_actor_show_all (offscreen_source); /* need to show() offscreen */ + if ((fbo = clutter_texture_new_from_actor (offscreen_source)) == NULL) + g_error("offscreen fbo creation failed"); + + clutter_actor_set_position (fbo, padx*3, 0); + clutter_group_add (stage, fbo); + + + /* 5th transformed */ + trans_source = make_source(); + clutter_actor_show_all (trans_source); /* need to show() offscreen */ + + clutter_actor_set_scale (trans_source, 2.5, 2.5); +#if 0 + /* Rotate about center by 90 degrees - FIXME: fbo seems to get nothing*/ + clutter_actor_move_anchor_point_from_gravity (trans_source, + CLUTTER_GRAVITY_CENTER); + clutter_actor_set_rotation (trans_source, CLUTTER_Z_AXIS, 90.0, 0, 0, 0); +#endif + + if ((fbo = clutter_texture_new_from_actor (trans_source)) == NULL) + g_error("transformed fbo creation failed"); + + clutter_actor_set_position (fbo, 0, pady); + clutter_group_add (stage, fbo); + + + /* 6th resized bigger, but after fbo creation */ + trans_source = make_source(); + clutter_actor_show_all (trans_source); /* need to show() offscreen */ + + if ((fbo = clutter_texture_new_from_actor (trans_source)) == NULL) + g_error("transformed fbo creation failed"); + + clutter_actor_set_width (trans_source, 2*padx); + clutter_actor_set_position (fbo, padx, pady); + clutter_group_add (stage, fbo); + + + /* non visual breaks */ + foo_source = make_source(); + clutter_actor_show_all (foo_source); + if ((fbo = clutter_texture_new_from_actor (foo_source)) == NULL) + g_error("foo fbo creation failed"); + + g_object_unref (foo_source); /* fbo should keep it around */ + + clutter_actor_set_position (fbo, padx*3, pady); + clutter_group_add (stage, fbo); - - if(1)clutter_actor_apply_shader (clone, shader); - if(1)clutter_actor_set_shader_param (clone, "radius", 2.0); - clutter_actor_show_all (stage); clutter_main ();