static void clutter_shader_effect_set_actor (ClutterActorMeta *meta, ClutterActor *actor) { ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (meta); ClutterShaderEffectPrivate *priv = self->priv; ClutterActorMetaClass *parent; if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShaderEffect: the graphics hardware " "or the current GL driver does not implement support " "for the GLSL shading language."); clutter_actor_meta_set_enabled (meta, FALSE); return; } parent = CLUTTER_ACTOR_META_CLASS (clutter_shader_effect_parent_class); parent->set_actor (meta, actor); /* we keep a back pointer here */ priv->actor = clutter_actor_meta_get_actor (meta); if (priv->actor == NULL) return; CLUTTER_NOTE (SHADER, "Preparing shader effect of type '%s'", G_OBJECT_TYPE_NAME (meta)); }
static ClutterStageWindow * clutter_backend_real_create_stage (ClutterBackend *backend, ClutterStage *wrapper, GError **error) { ClutterBackendClass *klass; if (!clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE)) { ClutterStageManager *manager = clutter_stage_manager_get_default (); if (clutter_stage_manager_get_default_stage (manager) != NULL) { g_set_error (error, CLUTTER_INIT_ERROR, CLUTTER_INIT_ERROR_BACKEND, _("The backend of type '%s' does not support " "creating multiple stages"), G_OBJECT_TYPE_NAME (backend)); return NULL; } } klass = CLUTTER_BACKEND_GET_CLASS (backend); g_assert (klass->stage_window_type != G_TYPE_INVALID); return g_object_new (klass->stage_window_type, "backend", backend, "wrapper", wrapper, NULL); }
static gboolean clutter_stage_glx_realize (ClutterStageWindow *stage_window) { ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window); ClutterBackendX11 *backend_x11; ClutterBackendGLX *backend_glx; CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]", G_OBJECT_TYPE_NAME (stage_window), stage_window); if (!_clutter_stage_x11_create_window (stage_x11)) return FALSE; backend_x11 = stage_x11->backend; backend_glx = CLUTTER_BACKEND_GLX (backend_x11); if (stage_glx->glxwin == None) { int major; int minor; GLXFBConfig config; /* Try and create a GLXWindow to use with extensions dependent on * GLX versions >= 1.3 that don't accept regular X Windows as GLX * drawables. */ if (glXQueryVersion (backend_x11->xdpy, &major, &minor) && major == 1 && minor >= 3 && _clutter_backend_glx_get_fbconfig (backend_glx, &config)) { stage_glx->glxwin = glXCreateWindow (backend_x11->xdpy, config, stage_x11->xwin, NULL); } } #ifdef GLX_INTEL_swap_event if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)) { GLXDrawable drawable = stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin; /* we unconditionally select this event because we rely on it to * advance the master clock, and drive redraw/relayout, animations * and event handling. */ glXSelectEvent (backend_x11->xdpy, drawable, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); } #endif /* GLX_INTEL_swap_event */ /* chain up to the StageX11 implementation */ return clutter_stage_window_parent_iface->realize (stage_window); }
G_MODULE_EXPORT int test_fbo_main (int argc, char *argv[]) { ClutterColor blue = {0x33, 0x44, 0x55, 0xff}; ClutterActor *fbo; ClutterActor *onscreen_source; ClutterActor *stage; ClutterAnimation *animation; int x_pos = 200; int y_pos = 100; 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_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT); 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); y_pos = (STAGE_HEIGHT/2.0) - (clutter_actor_get_height (onscreen_source)/2.0); clutter_actor_set_position (onscreen_source, x_pos, y_pos); x_pos += clutter_actor_get_width (onscreen_source); animation = clutter_actor_animate (onscreen_source, CLUTTER_LINEAR, 5000, /* 1 second duration */ "rotation-angle-y", 360.0f, NULL); clutter_animation_set_loop (animation, TRUE); /* Second hand = actor from onscreen_source */ if ((fbo = clutter_texture_new_from_actor (onscreen_source)) == NULL) g_error("onscreen fbo creation failed"); clutter_actor_set_position (fbo, x_pos, y_pos); x_pos += clutter_actor_get_width (fbo); clutter_group_add (stage, fbo); /* Third hand = actor from Second hand */ if ((fbo = clutter_texture_new_from_actor (fbo)) == NULL) g_error("fbo from fbo creation failed"); clutter_actor_set_position (fbo, x_pos, y_pos); x_pos += clutter_actor_get_width (fbo); clutter_group_add (stage, fbo); clutter_actor_show_all (stage); clutter_main (); return 0; }
int main (int argc, char *argv[]) { ClutterActor *stage = NULL; Data data1, data2,data3; guint id_2 = 0; g_set_application_name ("AtkText"); if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; if (cally_util_a11y_init (&argc, &argv) == FALSE) { g_error ("This example requires the accessibility support, " "especifically AtkUtil implementation loaded, " "as it tries to register and remove event listeners"); } data1.value = 10; data2.value = 20; data3.value = 30; /* key event listeners */ atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data1); id_2 = atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data2); atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data3); atk_remove_key_event_listener (id_2); /* event listeners */ atk_add_global_event_listener (window_event_listener, "window:create"); atk_add_global_event_listener (window_event_listener, "window:destroy"); atk_add_global_event_listener (window_event_listener, "window:activate"); atk_add_global_event_listener (window_event_listener, "window:deactivate"); stage = clutter_stage_get_default (); make_ui (stage); clutter_actor_show_all (stage); if (clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE)) { stage = clutter_stage_new (); make_ui (stage); clutter_actor_show_all (stage); } clutter_main (); return 0; }
static void clutter_reflect_texture_paint (ClutterActor *self) { ClutterReflectTexturePrivate *priv; ClutterActor *parent_texture; gint x1, y1, x2, y2; GLenum target_type; priv = CLUTTER_REFLECT_TEXTURE (self)->priv; /* no need to paint stuff if we don't have a texture to reflect */ if (!clutter_clone_texture_get_parent_texture(CLUTTER_CLONE_TEXTURE(self))) return; /* parent texture may have been hidden, there for need to make sure its * realised with resources available. */ parent_texture = CLUTTER_ACTOR (clutter_clone_texture_get_parent_texture(CLUTTER_CLONE_TEXTURE(self))); if (!CLUTTER_ACTOR_IS_REALIZED (parent_texture)) clutter_actor_realize (parent_texture); /* FIXME: figure out nicer way of getting at this info... */ if (clutter_feature_available (CLUTTER_FEATURE_TEXTURE_RECTANGLE) && clutter_texture_is_tiled (CLUTTER_TEXTURE (parent_texture)) == FALSE) { target_type = CGL_TEXTURE_RECTANGLE_ARB; cogl_enable (CGL_ENABLE_TEXTURE_RECT | CGL_ENABLE_BLEND); } else { target_type = CGL_TEXTURE_2D; cogl_enable (CGL_ENABLE_TEXTURE_2D|CGL_ENABLE_BLEND); } cogl_push_matrix (); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4ub (255, 255, 255, clutter_actor_get_opacity (self)); clutter_actor_get_coords (self, &x1, &y1, &x2, &y2); /* Parent paint translated us into position */ reflect_texture_render_to_gl_quad (CLUTTER_REFLECT_TEXTURE (self), 0, 0, x2 - x1, y2 - y1); cogl_pop_matrix (); }
G_GNUC_BEGIN_IGNORE_DEPRECATIONS static void default_stage (void) { ClutterActor *stage, *def_stage; stage = clutter_test_get_stage (); def_stage = clutter_stage_get_default (); if (clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE)) g_assert (stage != def_stage); else g_assert (stage == def_stage); g_assert (CLUTTER_ACTOR_IS_REALIZED (def_stage)); }
int main (int argc, char *argv[]) { ClutterActor *stage = NULL; Data data1, data2,data3; guint id_2 = 0; g_set_application_name ("AtkText"); if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) return 1; cally_util_a11y_init (&argc, &argv); data1.value = 10; data2.value = 20; data3.value = 30; /* key event listeners */ atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data1); id_2 = atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data2); atk_add_key_event_listener ((AtkKeySnoopFunc)atk_key_listener, &data3); atk_remove_key_event_listener (id_2); /* event listeners */ atk_add_global_event_listener (window_event_listener, "window:create"); atk_add_global_event_listener (window_event_listener, "window:destroy"); atk_add_global_event_listener (window_event_listener, "window:activate"); atk_add_global_event_listener (window_event_listener, "window:deactivate"); stage = clutter_stage_get_default (); make_ui (stage); clutter_actor_show_all (stage); if (clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE)) { stage = clutter_stage_new (); make_ui (stage); clutter_actor_show_all (stage); } clutter_main (); return 0; }
static gboolean shell_grid_desaturate_effect_pre_paint (ClutterEffect *effect) { ShellGridDesaturateEffect *self = SHELL_GRID_DESATURATE_EFFECT (effect); ClutterEffectClass *parent_class; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) return FALSE; if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShaderEffect: the graphics hardware " "or the current GL driver does not implement support " "for the GLSL shading language."); clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); return FALSE; } parent_class = CLUTTER_EFFECT_CLASS (shell_grid_desaturate_effect_parent_class); if (parent_class->pre_paint (effect)) { ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect); CoglHandle texture; texture = clutter_offscreen_effect_get_texture (offscreen_effect); self->tex_width = cogl_texture_get_width (texture); self->tex_height = cogl_texture_get_height (texture); if (self->unshaded_uniform_dirty) update_unshaded_uniform (self); cogl_pipeline_set_layer_texture (self->pipeline, 0, texture); return TRUE; } else return FALSE; }
static gboolean shell_anamorphosis_effect_pre_paint (ClutterEffect *effect) { ShellAnamorphosisEffect *self = SHELL_ANAMORPHOSIS_EFFECT (effect); ShellAnamorphosisEffectPrivate *priv = shell_anamorphosis_effect_get_instance_private (self); if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) return FALSE; /* If we're not doing any bending, we're not needed. */ if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShellAnamorphosisEffect: the " "graphics hardware or the current GL driver does not " "implement support for the GLSL shading language. The " "effect will be disabled."); clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); return FALSE; } if (!CLUTTER_EFFECT_CLASS (shell_anamorphosis_effect_parent_class)->pre_paint (effect)) return FALSE; ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect); CoglObject *texture; texture = clutter_offscreen_effect_get_texture (offscreen_effect); cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture); priv->tex_width = cogl_texture_get_width (texture); priv->tex_height = cogl_texture_get_height (texture); cogl_pipeline_set_uniform_1i (priv->pipeline, priv->tex_width_uniform, priv->tex_width); cogl_pipeline_set_uniform_1i (priv->pipeline, priv->tex_height_uniform, priv->tex_height); return TRUE; }
static void st_scroll_view_fade_init (StScrollViewFade *self) { static CoglHandle shader = COGL_INVALID_HANDLE; if (shader == COGL_INVALID_HANDLE) { if (clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); cogl_shader_source (shader, fade_glsl_shader); cogl_shader_compile (shader); if (!cogl_shader_is_compiled (shader)) { gchar *log_buf = cogl_shader_get_info_log (shader); g_warning (G_STRLOC ": Unable to compile the fade shader: %s", log_buf); g_free (log_buf); cogl_handle_unref (shader); shader = COGL_INVALID_HANDLE; } } } self->shader = shader; self->is_attached = FALSE; self->tex_uniform = -1; self->height_uniform = -1; self->width_uniform = -1; self->scrollbar_width_uniform = -1; self->scrollbar_height_uniform = -1; self->rtl_uniform = -1; self->offset_top_uniform = -1; self->offset_bottom_uniform = -1; self->fade_offset = DEFAULT_FADE_OFFSET; if (shader != COGL_INVALID_HANDLE) cogl_handle_ref (self->shader); }
/** * clutter_shader_compile: * @shader: a #ClutterShader * @error: return location for a #GError, or %NULL * * Compiles and links GLSL sources set for vertex and fragment shaders for * a #ClutterShader. If the compilation fails and a #GError return location is * provided the error will contain the errors from the compiler, if any. * * Return value: returns TRUE if the shader was succesfully compiled. * * Since: 0.8 */ gboolean clutter_shader_compile (ClutterShader *shader, GError **error) { ClutterShaderPrivate *priv; g_return_val_if_fail (CLUTTER_IS_SHADER (shader), FALSE); priv = shader->priv; if (priv->compiled) return priv->compiled; if ((priv->vertex_source != COGL_INVALID_HANDLE && !priv->vertex_is_glsl) || (priv->fragment_source != COGL_INVALID_HANDLE && !priv->fragment_is_glsl)) { /* XXX: Could remove this check, since we only advertise support for GLSL * shaders anyways. */ g_set_error (error, CLUTTER_SHADER_ERROR, CLUTTER_SHADER_ERROR_NO_ASM, "ASM shaders not supported"); priv->compiled = FALSE; return priv->compiled; } if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { g_set_error (error, CLUTTER_SHADER_ERROR, CLUTTER_SHADER_ERROR_NO_GLSL, "GLSL shaders not supported"); priv->compiled = FALSE; return priv->compiled; } priv->compiled = bind_glsl_shader (shader, error); g_object_notify (G_OBJECT (shader), "compiled"); return priv->compiled; }
static gboolean st_background_effect_pre_paint (ClutterEffect *effect) { StBackgroundEffect *self = ST_BACKGROUND_EFFECT (effect); ClutterEffectClass *parent_class; gfloat width; gfloat height; gfloat posx; gfloat posy; guchar *data; guint size; guint rowstride; glong new_time; gdouble time_used; ClutterActor *stage; gfloat stage_width; gfloat stage_height; if (self->bg_bumpmap == NULL) return FALSE; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) return FALSE; self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); if (self->actor == NULL) return FALSE; if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShaderEffect: the graphics hardware " "or the current GL driver does not implement support " "for the GLSL shading language."); clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); return FALSE; } new_time = clock(); time_used = ((double) (new_time - self->old_time)*100) / (double) CLOCKS_PER_SEC; self->old_time = new_time; posx = 0.0f; posy = 0.0f; width = 0.0f; height = 0.0f; stage_width = 0.0f; stage_height = 0.0f; clutter_actor_get_transformed_position (self->actor, &posx, &posy); clutter_actor_get_transformed_size (self->actor, &width, &height); self->opacity = clutter_actor_get_paint_opacity (self->actor); stage = clutter_actor_get_stage (self->actor); clutter_actor_get_size (stage, &stage_width, &stage_height); if ((posx < 0) || (posy < 0) || ((posx + width) > stage_width) || ((posy + height) > stage_height)) return FALSE; if (( posx != self->posx_old) || ( posy != self->posy_old) || ( width != self->width_old) || ( height != self->height_old) || (time_used > 50.0)) { self->posx_old = posx; self->posy_old = posy; self->width_old = width; self->height_old = height; self->bg_posx_i = round(posx)+2; self->bg_posy_i = round(posy)+2; self->bg_width_i = round(width)-4; self->bg_height_i = round(height)-4; size = (self->bg_width_i) * (self->bg_height_i) * 4; if (((self->opacity == 0xff) || (self->bg_texture == NULL)) && (size > 400)) { rowstride = (self->bg_width_i) * 4; data = g_malloc (size); cogl_read_pixels (self->bg_posx_i, self->bg_posy_i, self->bg_width_i, self->bg_height_i, COGL_READ_PIXELS_COLOR_BUFFER, COGL_PIXEL_FORMAT_RGBA_8888_PRE, data); if (data != NULL) { if (self->bg_texture != NULL) { cogl_handle_unref (self->bg_texture); self->bg_texture = NULL; } self->bg_texture = st_cogl_texture_new_from_data_wrapper (self->bg_width_i, self->bg_height_i, COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_RGBA_8888_PRE, COGL_PIXEL_FORMAT_RGBA_8888_PRE, rowstride, data); g_free (data); } } } parent_class = CLUTTER_EFFECT_CLASS (st_background_effect_parent_class); if (parent_class->pre_paint (effect)) { ClutterOffscreenEffect *offscreen_effect = CLUTTER_OFFSCREEN_EFFECT (effect); CoglHandle fg_texture; fg_texture = clutter_offscreen_effect_get_texture (offscreen_effect); if (fg_texture != COGL_INVALID_HANDLE) { self->fg_width_i = cogl_texture_get_width (fg_texture); self->fg_height_i = cogl_texture_get_height (fg_texture); if ((self->bg_texture != NULL) && (self->opacity == 0xff)) { if (self->pixel_step_uniform0 > -1) { gfloat pixel_step[3]; pixel_step[0] = 1.0f / (self->bg_width_i); pixel_step[1] = 1.0f / (self->bg_height_i); pixel_step[2] = 0.0f; cogl_pipeline_set_uniform_float (self->pipeline0, self->pixel_step_uniform0, 3, 1, pixel_step); } if (self->BumpTex_uniform > -1) { cogl_pipeline_set_uniform_1i (self->pipeline0, self->BumpTex_uniform, 1); } if (self->bump_step_uniform > -1) { gfloat bump_step[2]; bump_step[0] = 1.0f / (self->bumptex_width_i); bump_step[1] = 1.0f / (self->bumptex_height_i); cogl_pipeline_set_uniform_float (self->pipeline0, self->bump_step_uniform, 2, 1, bump_step); } if (self->bg_sub_texture != NULL) { cogl_handle_unref (self->bg_sub_texture); self->bg_sub_texture = NULL; } self->bg_sub_texture = st_cogl_texture_new_with_size_wrapper (self->bg_width_i, self->bg_height_i, COGL_TEXTURE_NO_SLICING, COGL_PIXEL_FORMAT_RGBA_8888_PRE); cogl_pipeline_set_layer_texture (self->pipeline0, 0, self->bg_texture); if (self->pixel_step_uniform1 > -1) { gfloat pixel_step[3]; pixel_step[0] = 1.0f / (self->bg_width_i); pixel_step[1] = 1.0f / (self->bg_height_i); pixel_step[2] = 1.0f; cogl_pipeline_set_uniform_float (self->pipeline1, self->pixel_step_uniform1, 3, 1, pixel_step); } if (self->pixel_step_uniform2 > -1) { gfloat pixel_step[3]; pixel_step[0] = 1.0f / (self->fg_width_i); pixel_step[1] = 1.0f / (self->fg_height_i); pixel_step[2] = 2.0f; cogl_pipeline_set_uniform_float (self->pipeline3, self->pixel_step_uniform2, 3, 1, pixel_step); } } cogl_pipeline_set_layer_texture (self->pipeline2, 0, fg_texture); cogl_pipeline_set_layer_texture (self->pipeline3, 0, fg_texture); cogl_pipeline_set_layer_texture (self->pipeline4, 0, fg_texture); } return TRUE; } else { return FALSE; } }
static void tidy_texture_frame_paint (ClutterActor *self) { TidyTextureFramePrivate *priv; ClutterActor *parent_texture; guint width, height; gint pwidth, pheight, ex, ey; ClutterFixed tx1, ty1, tx2, ty2, tw, th; GLenum target_type; ClutterColor col = { 0xff, 0xff, 0xff, 0xff }; priv = TIDY_TEXTURE_FRAME (self)->priv; /* no need to paint stuff if we don't have a texture to reflect */ if (!clutter_clone_texture_get_parent_texture (CLUTTER_CLONE_TEXTURE(self))) return; /* parent texture may have been hidden, there for need to make sure its * realised with resources available. */ parent_texture = CLUTTER_ACTOR (clutter_clone_texture_get_parent_texture(CLUTTER_CLONE_TEXTURE(self))); if (!CLUTTER_ACTOR_IS_REALIZED (parent_texture)) clutter_actor_realize (parent_texture); if (clutter_texture_is_tiled (CLUTTER_TEXTURE (parent_texture))) { g_warning("tiled textures not yet supported..."); return; } cogl_push_matrix (); #define FX(x) CLUTTER_INT_TO_FIXED(x) clutter_texture_get_base_size (CLUTTER_TEXTURE(parent_texture), &pwidth, &pheight); clutter_actor_get_size (self, &width, &height); tx1 = FX (priv->left); tx2 = FX (pwidth - priv->right); ty1 = FX (priv->top); ty2 = FX (pheight - priv->bottom); tw = FX (pwidth); th = FX (pheight); if (clutter_feature_available (CLUTTER_FEATURE_TEXTURE_RECTANGLE)) { target_type = CGL_TEXTURE_RECTANGLE_ARB; cogl_enable (CGL_ENABLE_TEXTURE_RECT|CGL_ENABLE_BLEND); } else { target_type = CGL_TEXTURE_2D; cogl_enable (CGL_ENABLE_TEXTURE_2D|CGL_ENABLE_BLEND); tw = clutter_util_next_p2 (pwidth); th = clutter_util_next_p2 (pheight); tx1 = tx1/tw; tx2 = tx2/tw; ty1 = ty1/th; ty2 = ty2/th; tw = FX(pwidth)/tw; th = FX(pheight)/th; } col.alpha = clutter_actor_get_opacity (self); cogl_color (&col); clutter_texture_bind_tile (CLUTTER_TEXTURE(parent_texture), 0); ex = width - priv->right; if (ex < 0) ex = priv->right; /* FIXME */ ey = height - priv->bottom; if (ey < 0) ey = priv->bottom; /* FIXME */ /* top left corner */ cogl_texture_quad (0, priv->left, /* FIXME: clip if smaller */ 0, priv->top, 0, 0, tx1, ty1); /* top middle */ cogl_texture_quad (priv->left, ex, 0, priv->top, tx1, 0, tx2, ty1); /* top right */ cogl_texture_quad (ex, width, 0, priv->top, tx2, 0, tw, ty1); /* mid left */ cogl_texture_quad (0, priv->left, priv->top, ey, 0, ty1, tx1, ty2); /* center */ cogl_texture_quad (priv->left, ex, priv->top, ey, tx1, ty1, tx2, ty2); /* mid right */ cogl_texture_quad (ex, width, priv->top, ey, tx2, ty1, tw, ty2); /* bottom left */ cogl_texture_quad (0, priv->left, ey, height, 0, ty2, tx1, th); /* bottom center */ cogl_texture_quad (priv->left, ex, ey, height, tx1, ty2, tx2, th); /* bottom right */ cogl_texture_quad (ex, width, ey, height, tx2, ty2, tw, th); cogl_pop_matrix (); #undef FX }
static gboolean cd_icc_effect_pre_paint (ClutterEffect *effect) { CdIccEffect *self = CD_ICC_EFFECT (effect); ClutterEffectClass *parent_class; ClutterActorBox allocation; gfloat width, height; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) return FALSE; self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); if (self->actor == NULL) return FALSE; if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShaderEffect: the graphics hardware " "or the current GL driver does not implement support " "for the GLSL shading language."); clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); return FALSE; } clutter_actor_get_allocation_box (self->actor, &allocation); clutter_actor_box_get_size (&allocation, &width, &height); if (self->shader == COGL_INVALID_HANDLE) { self->shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); cogl_shader_source (self->shader, glsl_shader); self->is_compiled = FALSE; self->main_texture_uniform = -1; self->indirect_texture_uniform = -1; self->color_data1_uniform = -1; self->color_data2_uniform = -1; } if (self->program == COGL_INVALID_HANDLE) self->program = cogl_create_program (); if (!self->is_compiled) { g_assert (self->shader != COGL_INVALID_HANDLE); g_assert (self->program != COGL_INVALID_HANDLE); cogl_shader_compile (self->shader); if (!cogl_shader_is_compiled (self->shader)) { gchar *log_buf = cogl_shader_get_info_log (self->shader); g_warning (G_STRLOC ": Unable to compile the icc shader: %s", log_buf); g_free (log_buf); cogl_handle_unref (self->shader); cogl_handle_unref (self->program); self->shader = COGL_INVALID_HANDLE; self->program = COGL_INVALID_HANDLE; } else { cogl_program_attach_shader (self->program, self->shader); cogl_program_link (self->program); cogl_handle_unref (self->shader); self->is_compiled = TRUE; self->main_texture_uniform = cogl_program_get_uniform_location (self->program, "main_texture"); self->indirect_texture_uniform = cogl_program_get_uniform_location (self->program, "indirect_texture"); self->color_data1_uniform = cogl_program_get_uniform_location (self->program, "color_data1"); self->color_data2_uniform = cogl_program_get_uniform_location (self->program, "color_data2"); } } parent_class = CLUTTER_EFFECT_CLASS (cd_icc_effect_parent_class); return parent_class->pre_paint (effect); }
static gboolean on_timeout (gpointer data) { State *state = data; int test_num = 0; int y, x; ClutterActor *over_actor = NULL; /* This will cause an unclipped pick redraw that will get buffered. We'll check below that this buffer is discarded because we also need to pick non-reactive actors */ clutter_stage_get_actor_at_pos (CLUTTER_STAGE (state->stage), CLUTTER_PICK_REACTIVE, 10, 10); clutter_stage_get_actor_at_pos (CLUTTER_STAGE (state->stage), CLUTTER_PICK_REACTIVE, 10, 10); for (test_num = 0; test_num < 5; test_num++) { if (test_num == 0) { if (g_test_verbose ()) g_print ("No covering actor:\n"); } if (test_num == 1) { static const ClutterColor red = { 0xff, 0x00, 0x00, 0xff }; /* Create an actor that covers the whole stage but that isn't visible so it shouldn't affect the picking */ over_actor = clutter_rectangle_new_with_color (&red); clutter_actor_set_size (over_actor, STAGE_WIDTH, STAGE_HEIGHT); clutter_actor_add_child (state->stage, over_actor); clutter_actor_hide (over_actor); if (g_test_verbose ()) g_print ("Invisible covering actor:\n"); } else if (test_num == 2) { /* Make the actor visible but set a clip so that only some of the actors are accessible */ clutter_actor_show (over_actor); clutter_actor_set_clip (over_actor, state->actor_width * 2, state->actor_height * 2, state->actor_width * (ACTORS_X - 4), state->actor_height * (ACTORS_Y - 4)); if (g_test_verbose ()) g_print ("Clipped covering actor:\n"); } else if (test_num == 3) { if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) continue; clutter_actor_hide (over_actor); clutter_actor_add_effect_with_name (CLUTTER_ACTOR (state->stage), "blur", clutter_blur_effect_new ()); if (g_test_verbose ()) g_print ("With blur effect:\n"); } else if (test_num == 4) { if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) continue; clutter_actor_hide (over_actor); clutter_actor_remove_effect_by_name (CLUTTER_ACTOR (state->stage), "blur"); clutter_actor_add_effect_with_name (CLUTTER_ACTOR (state->stage), "shift", g_object_new (TYPE_SHIFT_EFFECT, NULL)); if (g_test_verbose ()) g_print ("With shift effect:\n"); } for (y = 0; y < ACTORS_Y; y++) { if (test_num == 4) x = 1; else x = 0; for (; x < ACTORS_X; x++) { gboolean pass = FALSE; gfloat pick_x; ClutterActor *actor; pick_x = x * state->actor_width + state->actor_width / 2; if (test_num == 4) pick_x -= SHIFT_STEP; actor = clutter_stage_get_actor_at_pos (CLUTTER_STAGE (state->stage), CLUTTER_PICK_ALL, pick_x, y * state->actor_height + state->actor_height / 2); if (g_test_verbose ()) g_print ("% 3i,% 3i / %p -> ", x, y, state->actors[y * ACTORS_X + x]); if (actor == NULL) { if (g_test_verbose ()) g_print ("NULL: FAIL\n"); } else if (actor == over_actor) { if (test_num == 2 && x >= 2 && x < ACTORS_X - 2 && y >= 2 && y < ACTORS_Y - 2) pass = TRUE; if (g_test_verbose ()) g_print ("over_actor: %s\n", pass ? "pass" : "FAIL"); } else { if (actor == state->actors[y * ACTORS_X + x] && (test_num != 2 || x < 2 || x >= ACTORS_X - 2 || y < 2 || y >= ACTORS_Y - 2)) pass = TRUE; if (g_test_verbose ()) g_print ("%p: %s\n", actor, pass ? "pass" : "FAIL"); } if (!pass) state->pass = FALSE; } } } clutter_main_quit (); return G_SOURCE_REMOVE; }
static gboolean clutter_stage_glx_realize (ClutterStageWindow *stage_window) { ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window); ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (stage_window); ClutterBackend *backend; ClutterBackendGLX *backend_glx; ClutterBackendX11 *backend_x11; GError *error; CLUTTER_NOTE (ACTOR, "Realizing stage '%s' [%p]", G_OBJECT_TYPE_NAME (stage_window), stage_window); backend = clutter_get_default_backend (); backend_glx = CLUTTER_BACKEND_GLX (backend); backend_x11 = CLUTTER_BACKEND_X11 (backend); if (stage_x11->xwin == None) { XSetWindowAttributes xattr; unsigned long mask; XVisualInfo *xvisinfo; gfloat width, height; CLUTTER_NOTE (MISC, "Creating stage X window"); xvisinfo = clutter_backend_x11_get_visual_info (backend_x11); if (xvisinfo == NULL) { g_critical ("Unable to find suitable GL visual."); return FALSE; } /* window attributes */ xattr.background_pixel = WhitePixel (backend_x11->xdpy, backend_x11->xscreen_num); xattr.border_pixel = 0; xattr.colormap = XCreateColormap (backend_x11->xdpy, backend_x11->xwin_root, xvisinfo->visual, AllocNone); mask = CWBorderPixel | CWColormap; /* Call get_size - this will either get the geometry size (which * before we create the window is set to 640x480), or if a size * is set, it will get that. This lets you set a size on the * stage before it's realized. */ clutter_actor_get_size (CLUTTER_ACTOR (stage_x11->wrapper), &width, &height); stage_x11->xwin_width = (gint)width; stage_x11->xwin_height = (gint)height; stage_x11->xwin = XCreateWindow (backend_x11->xdpy, backend_x11->xwin_root, 0, 0, stage_x11->xwin_width, stage_x11->xwin_height, 0, xvisinfo->depth, InputOutput, xvisinfo->visual, mask, &xattr); CLUTTER_NOTE (BACKEND, "Stage [%p], window: 0x%x, size: %dx%d", stage_window, (unsigned int) stage_x11->xwin, stage_x11->xwin_width, stage_x11->xwin_height); XFree (xvisinfo); } if (stage_glx->glxwin == None) { int major; int minor; GLXFBConfig config; /* Try and create a GLXWindow to use with extensions dependent on * GLX versions >= 1.3 that don't accept regular X Windows as GLX * drawables. */ if (glXQueryVersion (backend_x11->xdpy, &major, &minor) && major == 1 && minor >= 3 && _clutter_backend_glx_get_fbconfig (backend_glx, &config)) { stage_glx->glxwin = glXCreateWindow (backend_x11->xdpy, config, stage_x11->xwin, NULL); } } if (clutter_x11_has_event_retrieval ()) { if (clutter_x11_has_xinput ()) { XSelectInput (backend_x11->xdpy, stage_x11->xwin, StructureNotifyMask | FocusChangeMask | ExposureMask | KeyPressMask | KeyReleaseMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask); #ifdef HAVE_XINPUT _clutter_x11_select_events (stage_x11->xwin); #endif } else XSelectInput (backend_x11->xdpy, stage_x11->xwin, StructureNotifyMask | FocusChangeMask | ExposureMask | PointerMotionMask | KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask); #ifdef GLX_INTEL_swap_event if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)) { GLXDrawable drawable = stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin; glXSelectEvent (backend_x11->xdpy, drawable, GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK); } #endif /* GLX_INTEL_swap_event */ } /* no user resize.. */ clutter_stage_x11_fix_window_size (stage_x11, stage_x11->xwin_width, stage_x11->xwin_height); clutter_stage_x11_set_wm_protocols (stage_x11); /* ask for a context; a no-op, if a context already exists */ error = NULL; _clutter_backend_create_context (backend, &error); if (error) { g_critical ("Unable to realize stage: %s", error->message); g_error_free (error); return FALSE; } CLUTTER_NOTE (BACKEND, "Successfully realized stage"); /* chain up to the StageX11 implementation */ return clutter_stage_glx_parent_iface->realize (stage_window); }
static void clutter_stage_glx_redraw (ClutterStageWindow *stage_window) { ClutterBackendX11 *backend_x11; ClutterBackendGLX *backend_glx; ClutterStageX11 *stage_x11; ClutterStageGLX *stage_glx; GLXDrawable drawable; unsigned int video_sync_count; gboolean may_use_clipped_redraw; gboolean use_clipped_redraw; CLUTTER_STATIC_TIMER (painting_timer, "Redrawing", /* parent */ "Painting actors", "The time spent painting actors", 0 /* no application private data */); CLUTTER_STATIC_TIMER (swapbuffers_timer, "Redrawing", /* parent */ "glXSwapBuffers", "The time spent blocked by glXSwapBuffers", 0 /* no application private data */); CLUTTER_STATIC_TIMER (blit_sub_buffer_timer, "Redrawing", /* parent */ "glx_blit_sub_buffer", "The time spent in _glx_blit_sub_buffer", 0 /* no application private data */); stage_x11 = CLUTTER_STAGE_X11 (stage_window); if (stage_x11->xwin == None) return; stage_glx = CLUTTER_STAGE_GLX (stage_window); backend_x11 = stage_x11->backend; backend_glx = CLUTTER_BACKEND_GLX (backend_x11); CLUTTER_TIMER_START (_clutter_uprof_context, painting_timer); if (G_LIKELY (backend_glx->can_blit_sub_buffer) && /* NB: a zero width redraw clip == full stage redraw */ stage_glx->bounding_redraw_clip.width != 0 && /* some drivers struggle to get going and produce some junk * frames when starting up... */ G_LIKELY (stage_glx->frame_count > 3) && /* While resizing a window clipped redraws are disabled to avoid * artefacts. See clutter-event-x11.c:event_translate for a * detailed explanation */ G_LIKELY (stage_x11->clipped_redraws_cool_off == 0)) { may_use_clipped_redraw = TRUE; } else may_use_clipped_redraw = FALSE; if (may_use_clipped_redraw && G_LIKELY (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS))) use_clipped_redraw = TRUE; else use_clipped_redraw = FALSE; if (use_clipped_redraw) { CLUTTER_NOTE (CLIPPING, "Stage clip pushed: x=%d, y=%d, width=%d, height=%d\n", stage_glx->bounding_redraw_clip.x, stage_glx->bounding_redraw_clip.y, stage_glx->bounding_redraw_clip.width, stage_glx->bounding_redraw_clip.height); cogl_clip_push_window_rectangle (stage_glx->bounding_redraw_clip.x, stage_glx->bounding_redraw_clip.y, stage_glx->bounding_redraw_clip.width, stage_glx->bounding_redraw_clip.height); _clutter_stage_do_paint (stage_x11->wrapper, &stage_glx->bounding_redraw_clip); cogl_clip_pop (); } else { CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n"); _clutter_stage_do_paint (stage_x11->wrapper, NULL); } if (may_use_clipped_redraw && G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS))) { static CoglMaterial *outline = NULL; ClutterGeometry *clip = &stage_glx->bounding_redraw_clip; ClutterActor *actor = CLUTTER_ACTOR (stage_x11->wrapper); CoglHandle vbo; float x_1 = clip->x; float x_2 = clip->x + clip->width; float y_1 = clip->y; float y_2 = clip->y + clip->height; float quad[8] = { x_1, y_1, x_2, y_1, x_2, y_2, x_1, y_2 }; CoglMatrix modelview; if (outline == NULL) { outline = cogl_material_new (); cogl_material_set_color4ub (outline, 0xff, 0x00, 0x00, 0xff); } vbo = cogl_vertex_buffer_new (4); cogl_vertex_buffer_add (vbo, "gl_Vertex", 2, /* n_components */ COGL_ATTRIBUTE_TYPE_FLOAT, FALSE, /* normalized */ 0, /* stride */ quad); cogl_vertex_buffer_submit (vbo); cogl_push_matrix (); cogl_matrix_init_identity (&modelview); _clutter_actor_apply_modelview_transform (actor, &modelview); cogl_set_modelview_matrix (&modelview); cogl_set_source (outline); cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_LINE_LOOP, 0 , 4); cogl_pop_matrix (); cogl_object_unref (vbo); } cogl_flush (); CLUTTER_TIMER_STOP (_clutter_uprof_context, painting_timer); drawable = stage_glx->glxwin ? stage_glx->glxwin : stage_x11->xwin; /* If we might ever use _clutter_backend_glx_blit_sub_buffer then we * always need to keep track of the video_sync_count so that we can * throttle blits. * * Note: we get the count *before* we issue any glXCopySubBuffer or * blit_sub_buffer request in case the count would go up before * returning control to us. */ if (backend_glx->can_blit_sub_buffer && backend_glx->get_video_sync) backend_glx->get_video_sync (&video_sync_count); /* push on the screen */ if (use_clipped_redraw) { ClutterGeometry *clip = &stage_glx->bounding_redraw_clip; ClutterGeometry copy_area; ClutterActor *actor; CLUTTER_NOTE (BACKEND, "_glx_blit_sub_buffer (window: 0x%lx, " "x: %d, y: %d, " "width: %d, height: %d)", (unsigned long) drawable, stage_glx->bounding_redraw_clip.x, stage_glx->bounding_redraw_clip.y, stage_glx->bounding_redraw_clip.width, stage_glx->bounding_redraw_clip.height); /* XXX: It seems there will be a race here in that the stage * window may be resized before glXCopySubBufferMESA is handled * and so we may copy the wrong region. I can't really see how * we can handle this with the current state of X but at least * in this case a full redraw should be queued by the resize * anyway so it should only exhibit temporary artefacts. */ actor = CLUTTER_ACTOR (stage_x11->wrapper); copy_area.y = clutter_actor_get_height (actor) - clip->y - clip->height; copy_area.x = clip->x; copy_area.width = clip->width; copy_area.height = clip->height; /* glXCopySubBufferMESA and glBlitFramebuffer are not integrated * with the glXSwapIntervalSGI mechanism which we usually use to * throttle the Clutter framerate to the vertical refresh and so * we have to manually wait for the vblank period... */ /* Here 'is_synchronized' only means that the blit won't cause a * tear, ie it won't prevent multiple blits per retrace if they * can all be performed in the blanking period. If that's the * case then we still want to use the vblank sync menchanism but * we only need it to throttle redraws. */ if (!backend_glx->blit_sub_buffer_is_synchronized) { /* XXX: note that glXCopySubBuffer, at least for Intel, is * synchronized with the vblank but glBlitFramebuffer may * not be so we use the same scheme we do when calling * glXSwapBuffers without the swap_control extension and * call glFinish () before waiting for the vblank period. * * See where we call glXSwapBuffers for more details. */ glFinish (); wait_for_vblank (backend_glx); } else if (backend_glx->get_video_sync) { /* If we have the GLX_SGI_video_sync extension then we can * be a bit smarter about how we throttle blits by avoiding * any waits if we can see that the video sync count has * already progressed. */ if (backend_glx->last_video_sync_count == video_sync_count) wait_for_vblank (backend_glx); } else wait_for_vblank (backend_glx); CLUTTER_TIMER_START (_clutter_uprof_context, blit_sub_buffer_timer); _clutter_backend_glx_blit_sub_buffer (backend_glx, drawable, copy_area.x, copy_area.y, copy_area.width, copy_area.height); CLUTTER_TIMER_STOP (_clutter_uprof_context, blit_sub_buffer_timer); } else { CLUTTER_NOTE (BACKEND, "glXSwapBuffers (display: %p, window: 0x%lx)", backend_x11->xdpy, (unsigned long) drawable); /* If we have GLX swap buffer events then glXSwapBuffers will return * immediately and we need to track that there is a swap in * progress... */ if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS)) stage_glx->pending_swaps++; if (backend_glx->vblank_type != CLUTTER_VBLANK_GLX_SWAP && backend_glx->vblank_type != CLUTTER_VBLANK_NONE) { /* If we are going to wait for VBLANK manually, we not only * need to flush out pending drawing to the GPU before we * sleep, we need to wait for it to finish. Otherwise, we * may end up with the situation: * * - We finish drawing - GPU drawing continues * - We go to sleep - GPU drawing continues * VBLANK - We call glXSwapBuffers - GPU drawing continues * - GPU drawing continues * - Swap buffers happens * * Producing a tear. Calling glFinish() first will cause us * to properly wait for the next VBLANK before we swap. This * obviously does not happen when we use _GLX_SWAP and let * the driver do the right thing */ glFinish (); wait_for_vblank (backend_glx); } CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer); glXSwapBuffers (backend_x11->xdpy, drawable); CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer); _cogl_swap_buffers_notify (); } backend_glx->last_video_sync_count = video_sync_count; /* reset the redraw clipping for the next paint... */ stage_glx->initialized_redraw_clip = FALSE; stage_glx->frame_count++; }
static gboolean clutter_colorize_effect_pre_paint (ClutterEffect *effect) { ClutterColorizeEffect *self = CLUTTER_COLORIZE_EFFECT (effect); ClutterEffectClass *parent_class; if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (effect))) return FALSE; self->actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect)); if (self->actor == NULL) return FALSE; if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL)) { /* if we don't have support for GLSL shaders then we * forcibly disable the ActorMeta */ g_warning ("Unable to use the ShaderEffect: the graphics hardware " "or the current GL driver does not implement support " "for the GLSL shading language."); clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (effect), FALSE); return FALSE; } if (self->shader == COGL_INVALID_HANDLE) { self->shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT); cogl_shader_source (self->shader, colorize_glsl_shader); self->is_compiled = FALSE; self->tex_uniform = -1; self->tint_uniform = -1; } if (self->program == COGL_INVALID_HANDLE) self->program = cogl_create_program (); if (!self->is_compiled) { g_assert (self->shader != COGL_INVALID_HANDLE); g_assert (self->program != COGL_INVALID_HANDLE); cogl_shader_compile (self->shader); if (!cogl_shader_is_compiled (self->shader)) { gchar *log_buf = cogl_shader_get_info_log (self->shader); g_warning (G_STRLOC ": Unable to compile the colorize shader: %s", log_buf); g_free (log_buf); cogl_handle_unref (self->shader); cogl_handle_unref (self->program); self->shader = COGL_INVALID_HANDLE; self->program = COGL_INVALID_HANDLE; } else { cogl_program_attach_shader (self->program, self->shader); cogl_program_link (self->program); cogl_handle_unref (self->shader); self->is_compiled = TRUE; self->tex_uniform = cogl_program_get_uniform_location (self->program, "tex"); self->tint_uniform = cogl_program_get_uniform_location (self->program, "tint"); } } parent_class = CLUTTER_EFFECT_CLASS (clutter_colorize_effect_parent_class); return parent_class->pre_paint (effect); }
/* * master_clock_next_frame_delay: * @master_clock: a #ClutterMasterClock * * Computes the number of delay before we need to draw the next frame. * * Return value: -1 if there is no next frame pending, otherwise the * number of millseconds before the we need to draw the next frame */ static gint master_clock_next_frame_delay (ClutterMasterClock *master_clock) { gint64 now, next; if (!master_clock_is_running (master_clock)) return -1; /* When we have sync-to-vblank, we count on swap-buffer requests (or * swap-buffer-complete events if supported in the backend) to throttle our * frame rate so no additional delay is needed to start the next frame. * * If the master-clock has become idle due to no timeline progression causing * redraws then we can no longer rely on vblank synchronization because the * last real stage update/redraw may have happened a long time ago and so we * fallback to polling for timeline progressions every 1/frame_rate seconds. * * (NB: if there aren't even any timelines running then the master clock will * be completely stopped in master_clock_is_running()) */ if (clutter_feature_available (CLUTTER_FEATURE_SYNC_TO_VBLANK) && !master_clock->idle) { CLUTTER_NOTE (SCHEDULER, "vblank available and updated stages"); return 0; } if (master_clock->prev_tick == 0) { /* If we weren't previously running, then draw the next frame * immediately */ CLUTTER_NOTE (SCHEDULER, "draw the first frame immediately"); return 0; } /* Otherwise, wait at least 1/frame_rate seconds since we last * started a frame */ #if GLIB_CHECK_VERSION (2, 27, 3) now = g_source_get_time (master_clock->source); #else { GTimeVal source_time; g_source_get_current_time (master_clock->source, &source_time); now = source_time.tv_sec * 1000000L + source_time.tv_usec; } #endif next = master_clock->prev_tick; /* If time has gone backwards then there's no way of knowing how long we should wait so let's just dispatch immediately */ if (now <= next) { CLUTTER_NOTE (SCHEDULER, "Time has gone backwards"); return 0; } next += (1000000L / clutter_get_default_frame_rate ()); if (next <= now) { CLUTTER_NOTE (SCHEDULER, "Less than %lu microsecs", 1000000L / (gulong) clutter_get_default_frame_rate ()); return 0; } else { CLUTTER_NOTE (SCHEDULER, "Waiting %" G_GINT64_FORMAT " msecs", (next - now) / 1000); return (next - now) / 1000; } }
static void reflect_texture_render_to_gl_quad (ClutterReflectTexture *ctexture, int x1, int y1, int x2, int y2) { gint qx1 = 0, qx2 = 0, qy1 = 0, qy2 = 0; gint qwidth = 0, qheight = 0; gint x, y, i =0, lastx = 0, lasty = 0; gint n_x_tiles, n_y_tiles; gint pwidth, pheight, rheight; float tx, ty, ty2 = 0.0; ClutterReflectTexturePrivate *priv = ctexture->priv; ClutterActor *parent_texture = CLUTTER_ACTOR(clutter_clone_texture_get_parent_texture(CLUTTER_CLONE_TEXTURE(ctexture))); priv = ctexture->priv; qwidth = x2 - x1; qheight = y2 - y1; rheight = priv->reflection_height; if (rheight > qheight) rheight = qheight; if (!CLUTTER_ACTOR_IS_REALIZED (parent_texture)) clutter_actor_realize (parent_texture); /* Only paint if parent is in a state to do so */ if (!clutter_texture_has_generated_tiles (CLUTTER_TEXTURE(parent_texture))) return; clutter_texture_get_base_size (CLUTTER_TEXTURE(parent_texture), &pwidth, &pheight); if (!clutter_texture_is_tiled (CLUTTER_TEXTURE(parent_texture))) { clutter_texture_bind_tile (CLUTTER_TEXTURE(parent_texture), 0); /* NPOTS textures *always* used if extension available */ if (clutter_feature_available (CLUTTER_FEATURE_TEXTURE_RECTANGLE)) { tx = (float) pwidth; ty = (float) pheight; ty2 = (float)(clutter_actor_get_height (CLUTTER_ACTOR(ctexture)) * rheight) / pheight; ty2 = pheight - ty2; } else { tx = (float) pwidth / clutter_util_next_p2 (pwidth); ty = (float) pheight / clutter_util_next_p2 (pheight); } qx1 = x1; qx2 = x2; qy1 = y1; qy2 = y1 + rheight; glBegin (GL_QUADS); glColor4ub (255, 255, 255, clutter_actor_get_opacity (CLUTTER_ACTOR(ctexture))); glTexCoord2f (0, ty); glVertex2i (qx1, qy1); glTexCoord2f (tx, ty); glVertex2i (qx2, qy1); glColor4ub (255, 255, 255, 0); glTexCoord2f (tx, ty2); glVertex2i (qx2, qy2); glTexCoord2f (0, ty2); glVertex2i (qx1, qy2); glEnd (); return; } clutter_texture_get_n_tiles (CLUTTER_TEXTURE(parent_texture), &n_x_tiles, &n_y_tiles); for (x = 0; x < n_x_tiles; x++) { lasty = 0; for (y = 0; y < n_y_tiles; y++) { gint actual_w, actual_h; gint xpos, ypos, xsize, ysize, ywaste, xwaste; clutter_texture_bind_tile (CLUTTER_TEXTURE(parent_texture), i); clutter_texture_get_x_tile_detail (CLUTTER_TEXTURE(parent_texture), x, &xpos, &xsize, &xwaste); clutter_texture_get_y_tile_detail (CLUTTER_TEXTURE(parent_texture), y, &ypos, &ysize, &ywaste); actual_w = xsize - xwaste; actual_h = ysize - ywaste; tx = (float) actual_w / xsize; ty = (float) actual_h / ysize; qx1 = x1 + lastx; qx2 = qx1 + ((qwidth * actual_w ) / pwidth ); qy1 = y1 + lasty; qy2 = qy1 + ((qheight * actual_h) / pheight ); glBegin (GL_QUADS); glTexCoord2f (tx, ty); glVertex2i (qx2, qy2); glTexCoord2f (0, ty); glVertex2i (qx1, qy2); glTexCoord2f (0, 0); glVertex2i (qx1, qy1); glTexCoord2f (tx, 0); glVertex2i (qx2, qy1); glEnd (); lasty += qy2 - qy1; i++; } lastx += qx2 - qx1; } }