|
Packit |
d345d1 |
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
/**
|
|
Packit |
d345d1 |
* SECTION:shell-glsl-quad
|
|
Packit |
d345d1 |
* @short_description: Draw a rectangle using GLSL
|
|
Packit |
d345d1 |
*
|
|
Packit |
d345d1 |
* A #ShellGLSLQuad draws one single rectangle, sized to the allocation
|
|
Packit |
d345d1 |
* box, but allows running custom GLSL to the vertex and fragment
|
|
Packit |
d345d1 |
* stages of the graphic pipeline.
|
|
Packit |
d345d1 |
*
|
|
Packit |
d345d1 |
* To ease writing the shader, a single texture layer is also used.
|
|
Packit |
d345d1 |
*/
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
#include "config.h"
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
#include <cogl/cogl.h>
|
|
Packit |
d345d1 |
#include "shell-glsl-quad.h"
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
typedef struct _ShellGLSLQuadPrivate ShellGLSLQuadPrivate;
|
|
Packit |
d345d1 |
struct _ShellGLSLQuadPrivate
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
CoglPipeline *pipeline;
|
|
Packit |
d345d1 |
};
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
G_DEFINE_TYPE_WITH_PRIVATE (ShellGLSLQuad, shell_glsl_quad, CLUTTER_TYPE_ACTOR);
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
static gboolean
|
|
Packit |
d345d1 |
shell_glsl_quad_get_paint_volume (ClutterActor *actor,
|
|
Packit |
d345d1 |
ClutterPaintVolume *volume)
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
return clutter_paint_volume_set_from_allocation (volume, actor);
|
|
Packit |
d345d1 |
}
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
static void
|
|
Packit |
d345d1 |
shell_glsl_quad_paint (ClutterActor *actor)
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
ShellGLSLQuad *self = SHELL_GLSL_QUAD (actor);
|
|
Packit |
d345d1 |
ShellGLSLQuadPrivate *priv;
|
|
Packit |
d345d1 |
guint8 paint_opacity;
|
|
Packit |
d345d1 |
ClutterActorBox box;
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
priv = shell_glsl_quad_get_instance_private (self);
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
paint_opacity = clutter_actor_get_paint_opacity (actor);
|
|
Packit |
d345d1 |
clutter_actor_get_allocation_box (actor, &box);
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
cogl_pipeline_set_color4ub (priv->pipeline,
|
|
Packit |
d345d1 |
paint_opacity,
|
|
Packit |
d345d1 |
paint_opacity,
|
|
Packit |
d345d1 |
paint_opacity,
|
|
Packit |
d345d1 |
paint_opacity);
|
|
Packit |
d345d1 |
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
|
|
Packit |
d345d1 |
priv->pipeline,
|
|
Packit |
d345d1 |
box.x1, box.y1,
|
|
Packit |
d345d1 |
box.x2, box.y2);
|
|
Packit |
d345d1 |
}
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
/**
|
|
Packit |
d345d1 |
* shell_glsl_quad_add_glsl_snippet:
|
|
Packit |
d345d1 |
* @quad: a #ShellGLSLQuad
|
|
Packit |
d345d1 |
* @hook: where to insert the code
|
|
Packit |
d345d1 |
* @declarations: GLSL declarations
|
|
Packit |
d345d1 |
* @code: GLSL code
|
|
Packit |
d345d1 |
* @is_replace: wheter Cogl code should be replaced by the custom shader
|
|
Packit |
d345d1 |
*
|
|
Packit |
d345d1 |
* Adds a GLSL snippet to the pipeline used for drawing the actor texture.
|
|
Packit |
d345d1 |
* See #CoglSnippet for details.
|
|
Packit |
d345d1 |
*
|
|
Packit |
d345d1 |
* This is only valid inside the a call to the build_pipeline() virtual
|
|
Packit |
d345d1 |
* function.
|
|
Packit |
d345d1 |
*/
|
|
Packit |
d345d1 |
void
|
|
Packit |
d345d1 |
shell_glsl_quad_add_glsl_snippet (ShellGLSLQuad *quad,
|
|
Packit |
d345d1 |
ShellSnippetHook hook,
|
|
Packit |
d345d1 |
const char *declarations,
|
|
Packit |
d345d1 |
const char *code,
|
|
Packit |
d345d1 |
gboolean is_replace)
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
ShellGLSLQuadClass *klass = SHELL_GLSL_QUAD_GET_CLASS (quad);
|
|
Packit |
d345d1 |
CoglSnippet *snippet;
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
g_return_if_fail (klass->base_pipeline != NULL);
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
if (is_replace)
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
snippet = cogl_snippet_new ((CoglSnippetHook)hook, declarations, NULL);
|
|
Packit |
d345d1 |
cogl_snippet_set_replace (snippet, code);
|
|
Packit |
d345d1 |
}
|
|
Packit |
d345d1 |
else
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
snippet = cogl_snippet_new ((CoglSnippetHook)hook, declarations, code);
|
|
Packit |
d345d1 |
}
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
if (hook == SHELL_SNIPPET_HOOK_VERTEX ||
|
|
Packit |
d345d1 |
hook == SHELL_SNIPPET_HOOK_FRAGMENT)
|
|
Packit |
d345d1 |
cogl_pipeline_add_snippet (klass->base_pipeline, snippet);
|
|
Packit |
d345d1 |
else
|
|
Packit |
d345d1 |
cogl_pipeline_add_layer_snippet (klass->base_pipeline, 0, snippet);
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
cogl_object_unref (snippet);
|
|
Packit |
d345d1 |
}
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
static void
|
|
Packit |
d345d1 |
shell_glsl_quad_dispose (GObject *gobject)
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
ShellGLSLQuad *self = SHELL_GLSL_QUAD (gobject);
|
|
Packit |
d345d1 |
ShellGLSLQuadPrivate *priv;
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
priv = shell_glsl_quad_get_instance_private (self);
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
g_clear_pointer (&priv->pipeline, cogl_object_unref);
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
G_OBJECT_CLASS (shell_glsl_quad_parent_class)->dispose (gobject);
|
|
Packit |
d345d1 |
}
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
static void
|
|
Packit |
d345d1 |
shell_glsl_quad_init (ShellGLSLQuad *quad)
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
}
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
static void
|
|
Packit |
d345d1 |
shell_glsl_quad_constructed (GObject *object)
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
ShellGLSLQuad *self;
|
|
Packit |
d345d1 |
ShellGLSLQuadClass *klass;
|
|
Packit |
d345d1 |
ShellGLSLQuadPrivate *priv;
|
|
Packit |
d345d1 |
CoglContext *ctx =
|
|
Packit |
d345d1 |
clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
G_OBJECT_CLASS (shell_glsl_quad_parent_class)->constructed (object);
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
/* Note that, differently from ClutterBlurEffect, we are calling
|
|
Packit |
d345d1 |
this inside constructed, not init, so klass points to the most-derived
|
|
Packit |
d345d1 |
GTypeClass, not ShellGLSLQuadClass.
|
|
Packit |
d345d1 |
*/
|
|
Packit |
d345d1 |
klass = SHELL_GLSL_QUAD_GET_CLASS (object);
|
|
Packit |
d345d1 |
self = SHELL_GLSL_QUAD (object);
|
|
Packit |
d345d1 |
priv = shell_glsl_quad_get_instance_private (self);
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
if (G_UNLIKELY (klass->base_pipeline == NULL))
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
klass->base_pipeline = cogl_pipeline_new (ctx);
|
|
Packit |
d345d1 |
cogl_pipeline_set_blend (klass->base_pipeline, "RGBA = ADD (SRC_COLOR * (SRC_COLOR[A]), DST_COLOR * (1-SRC_COLOR[A]))", NULL);
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
if (klass->build_pipeline != NULL)
|
|
Packit |
d345d1 |
klass->build_pipeline (self);
|
|
Packit |
d345d1 |
}
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
priv->pipeline = cogl_pipeline_copy (klass->base_pipeline);
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
cogl_pipeline_set_layer_null_texture (priv->pipeline, 0, COGL_TEXTURE_TYPE_2D);
|
|
Packit |
d345d1 |
}
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
static void
|
|
Packit |
d345d1 |
shell_glsl_quad_class_init (ShellGLSLQuadClass *klass)
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
|
Packit |
d345d1 |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
gobject_class->constructed = shell_glsl_quad_constructed;
|
|
Packit |
d345d1 |
gobject_class->dispose = shell_glsl_quad_dispose;
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
actor_class->get_paint_volume = shell_glsl_quad_get_paint_volume;
|
|
Packit |
d345d1 |
actor_class->paint = shell_glsl_quad_paint;
|
|
Packit |
d345d1 |
}
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
/**
|
|
Packit |
d345d1 |
* shell_glsl_quad_get_uniform_location:
|
|
Packit |
d345d1 |
* @quad: a #ShellGLSLQuad
|
|
Packit |
d345d1 |
* @name: the uniform name
|
|
Packit |
d345d1 |
*
|
|
Packit |
d345d1 |
* Returns: the location of the uniform named @name, that can be
|
|
Packit |
d345d1 |
* passed to shell_glsl_quad_set_uniform_float().
|
|
Packit |
d345d1 |
*/
|
|
Packit |
d345d1 |
int
|
|
Packit |
d345d1 |
shell_glsl_quad_get_uniform_location (ShellGLSLQuad *quad,
|
|
Packit |
d345d1 |
const char *name)
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
ShellGLSLQuadPrivate *priv = shell_glsl_quad_get_instance_private (quad);
|
|
Packit |
d345d1 |
return cogl_pipeline_get_uniform_location (priv->pipeline, name);
|
|
Packit |
d345d1 |
}
|
|
Packit |
d345d1 |
|
|
Packit |
d345d1 |
/**
|
|
Packit |
d345d1 |
* shell_glsl_quad_set_uniform_float:
|
|
Packit |
d345d1 |
* @quad: a #ShellGLSLQuad
|
|
Packit |
d345d1 |
* @uniform: the uniform location (as returned by shell_glsl_quad_get_uniform_location())
|
|
Packit |
d345d1 |
* @n_components: the number of components in the uniform (eg. 3 for a vec3)
|
|
Packit |
d345d1 |
* @total_count: the total number of floats in @value
|
|
Packit |
d345d1 |
* @value: (array length=total_count): the array of floats to set @uniform
|
|
Packit |
d345d1 |
*/
|
|
Packit |
d345d1 |
void
|
|
Packit |
d345d1 |
shell_glsl_quad_set_uniform_float (ShellGLSLQuad *quad,
|
|
Packit |
d345d1 |
int uniform,
|
|
Packit |
d345d1 |
int n_components,
|
|
Packit |
d345d1 |
int total_count,
|
|
Packit |
d345d1 |
const float *value)
|
|
Packit |
d345d1 |
{
|
|
Packit |
d345d1 |
ShellGLSLQuadPrivate *priv = shell_glsl_quad_get_instance_private (quad);
|
|
Packit |
d345d1 |
cogl_pipeline_set_uniform_float (priv->pipeline, uniform,
|
|
Packit |
d345d1 |
n_components, total_count / n_components,
|
|
Packit |
d345d1 |
value);
|
|
Packit |
d345d1 |
}
|