def __init__(self):
        self.stage = Clutter.Stage()

        r = Clutter.Texture.new_from_file("test.jpg")
        r.set_size(640, 480)
        self.stage.add_actor(r)
        shader = Clutter.Shader()
        source = open(__file__.replace(".py", ".glsl"), "r").read()
        shader.set_fragment_source(source, len(source))
        #shader.set_uniform("image", 0) # warning?
        r.set_shader(shader)
        self.stage.show()
def button_release_cb(actor, event, data):
    # If we've been run once, we'll figure out which one to use next.
    if hasattr(actor, "shader_name"):
        index = SHADER_KEYS.index(actor.shader_name)
        
        # Go back to the beginning.
        if index == len(SHADER_KEYS) - 1:
            actor.shader_name = next(iter(SHADERS))

        # Go to the next one.
        else:
            actor.shader_name = SHADER_KEYS[index + 1]

    # Otherwise, this must be the first time the callback has been run.
    # We'll start with the first iterative one.
    else:
        actor.shader_name = next(iter(SHADERS))

    print("Shader: %s" % actor.shader_name)

    # Shaders couldn't be easier to work with in Clutter. We'll start with our
    # basic brightness-contrast-1 example, and iterate from there when the user
    # clicks on the window.
    shader = Clutter.Shader()

    shader.set_fragment_source(SHADERS[actor.shader_name], -1)
    shader.compile()

    # We're going to "brute-force" the shaders here by setting every possible
    # parameter, rather than those only needed per each shader.
    actor.set_shader(shader)
    actor.set_shader_param_int("tex", 0)
    actor.set_shader_param_float("brightness", 0.4)
    actor.set_shader_param_float("contrast", -1.9)
    actor.set_shader_param_float("radius", 3.0)

    np2 = lambda n: 2 ** math.ceil(math.log(n, 2))

    actor.set_shader_param_float("x_step", 1.0 / np2(actor.get_width()))
    actor.set_shader_param_float("x_step", 1.0 / np2(actor.get_height()))