RutGaussianBlurrer *
rut_gaussian_blurrer_new (RutContext *ctx, int n_taps)
{
  RutGaussianBlurrer *blurrer = g_slice_new0 (RutGaussianBlurrer);
  CoglPipeline *base_pipeline;

  /* validation */
  if (n_taps < 5 || n_taps > 17 || n_taps % 2 == 0 )
    {
      g_critical ("blur: the numbers of taps must belong to the {5, 7, 9, "
                  "11, 13, 14, 17, 19} set");
      g_assert_not_reached ();
      return NULL;
    }

  blurrer->ctx = ctx;
  blurrer->n_taps = n_taps;

  base_pipeline = create_1d_gaussian_blur_pipeline (ctx, n_taps);

  blurrer->x_pass_pipeline = cogl_pipeline_copy (base_pipeline);
  set_blurrer_pipeline_factors (blurrer->x_pass_pipeline, n_taps);
  blurrer->y_pass_pipeline = cogl_pipeline_copy (base_pipeline);
  set_blurrer_pipeline_factors (blurrer->x_pass_pipeline, n_taps);

  cogl_object_unref (base_pipeline);

  return blurrer;
}
Exemple #2
0
static CoglBool
_cogl_polygon_validate_layer_cb (CoglPipeline *pipeline,
                                 int layer_index,
                                 void *user_data)
{
  ValidateState *state = user_data;

  /* By default COGL_PIPELINE_WRAP_MODE_AUTOMATIC becomes
   * GL_CLAMP_TO_EDGE but we want the polygon API to use GL_REPEAT to
   * maintain compatibility with previous releases
   */

  if (cogl_pipeline_get_layer_wrap_mode_s (pipeline, layer_index) ==
      COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
    {
      if (state->original_pipeline == state->pipeline)
        state->pipeline = cogl_pipeline_copy (pipeline);

      cogl_pipeline_set_layer_wrap_mode_s (state->pipeline, layer_index,
                                           COGL_PIPELINE_WRAP_MODE_REPEAT);
    }

  if (cogl_pipeline_get_layer_wrap_mode_t (pipeline, layer_index) ==
      COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
    {
      if (state->original_pipeline == state->pipeline)
        state->pipeline = cogl_pipeline_copy (pipeline);

      cogl_pipeline_set_layer_wrap_mode_t (state->pipeline, layer_index,
                                           COGL_PIPELINE_WRAP_MODE_REPEAT);
    }

  return TRUE;
}
static void
init_state (TestState *state)
{
  int uniform_location;

  state->pipeline_red = create_pipeline_for_shader (state, color_source);

  uniform_location =
    cogl_pipeline_get_uniform_location (state->pipeline_red, "red");
  cogl_pipeline_set_uniform_1f (state->pipeline_red, uniform_location, 1.0f);
  uniform_location =
    cogl_pipeline_get_uniform_location (state->pipeline_red, "green");
  cogl_pipeline_set_uniform_1f (state->pipeline_red, uniform_location, 0.0f);
  uniform_location =
    cogl_pipeline_get_uniform_location (state->pipeline_red, "blue");
  cogl_pipeline_set_uniform_1f (state->pipeline_red, uniform_location, 0.0f);

  state->pipeline_green = cogl_pipeline_copy (state->pipeline_red);
  uniform_location =
    cogl_pipeline_get_uniform_location (state->pipeline_green, "green");
  cogl_pipeline_set_uniform_1f (state->pipeline_green, uniform_location, 1.0f);

  state->pipeline_blue = cogl_pipeline_copy (state->pipeline_red);
  uniform_location =
    cogl_pipeline_get_uniform_location (state->pipeline_blue, "blue");
  cogl_pipeline_set_uniform_1f (state->pipeline_blue, uniform_location, 1.0f);

  state->matrix_pipeline = create_pipeline_for_shader (state, matrix_source);
  state->vector_pipeline = create_pipeline_for_shader (state, vector_source);
  state->int_pipeline = create_pipeline_for_shader (state, int_source);

  state->long_pipeline = NULL;
}
void
test_wrap_rectangle_textures (void)
{
  float fb_width = cogl_framebuffer_get_width (test_fb);
  float fb_height = cogl_framebuffer_get_height (test_fb);
  CoglPipeline *base_pipeline;
  CoglPipeline *clamp_pipeline;
  CoglPipeline *repeat_pipeline;
  /* The textures are drawn with the texture coordinates from
   * -0.5→1.5. That means we get one complete copy of the texture and
   * an extra half of the texture surrounding it. The drawing is
   * tested against a 4x4 grid of colors. The center 2x2 colours
   * specify the normal texture colors and the other colours specify
   * what the wrap mode should generate */
  static const uint8_t clamp_colors[] =
    {
      0x44, 0x44, 0x88, 0x88,
      0x44, 0x44, 0x88, 0x88,
      0xcc, 0xcc, 0xff, 0xff,
      0xcc, 0xcc, 0xff, 0xff
    };
  static const uint8_t repeat_colors[] =
    {
      0xff, 0xcc, 0xff, 0xcc,
      0x88, 0x44, 0x88, 0x44,
      0xff, 0xcc, 0xff, 0xcc,
      0x88, 0x44, 0x88, 0x44
    };

  cogl_framebuffer_orthographic (test_fb,
                                 0, 0, /* x_1, y_1 */
                                 fb_width, /* x_2 */
                                 fb_height /* y_2 */,
                                 -1, 100 /* near/far */);

  base_pipeline = create_base_pipeline ();

  clamp_pipeline = cogl_pipeline_copy (base_pipeline);
  cogl_pipeline_set_layer_wrap_mode (clamp_pipeline,
                                     0, /* layer */
                                     COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);

  repeat_pipeline = cogl_pipeline_copy (base_pipeline);
  cogl_pipeline_set_layer_wrap_mode (repeat_pipeline,
                                     0, /* layer */
                                     COGL_PIPELINE_WRAP_MODE_REPEAT);

  test_pipeline (clamp_pipeline,
                 0, 0, /* x/y offset */
                 clamp_colors);

  test_pipeline (repeat_pipeline,
                 0, DRAW_SIZE * 2, /* x/y offset */
                 repeat_colors);

  cogl_object_unref (repeat_pipeline);
  cogl_object_unref (clamp_pipeline);
  cogl_object_unref (base_pipeline);
}
static void
clutter_desaturate_effect_init (ClutterDesaturateEffect *self)
{
  ClutterDesaturateEffectClass *klass = CLUTTER_DESATURATE_EFFECT_GET_CLASS (self);

  if (G_UNLIKELY (klass->base_pipeline == NULL))
    {
      CoglContext *ctx =
        clutter_backend_get_cogl_context (clutter_get_default_backend ());
      CoglSnippet *snippet;

      klass->base_pipeline = cogl_pipeline_new (ctx);

      snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
                                  desaturate_glsl_declarations,
                                  desaturate_glsl_source);
      cogl_pipeline_add_snippet (klass->base_pipeline, snippet);
      cogl_object_unref (snippet);

      cogl_pipeline_set_layer_null_texture (klass->base_pipeline,
                                            0, /* layer number */
                                            COGL_TEXTURE_TYPE_2D);
    }

  self->pipeline = cogl_pipeline_copy (klass->base_pipeline);

  self->factor_uniform =
    cogl_pipeline_get_uniform_location (self->pipeline, "factor");

  self->factor = 1.0;

  update_factor_uniform (self);
}
static void
shell_glsl_quad_constructed (GObject *object)
{
  ShellGLSLQuad *self;
  ShellGLSLQuadClass *klass;
  ShellGLSLQuadPrivate *priv;
  CoglContext *ctx =
    clutter_backend_get_cogl_context (clutter_get_default_backend ());

  G_OBJECT_CLASS (shell_glsl_quad_parent_class)->constructed (object);

  /* Note that, differently from ClutterBlurEffect, we are calling
     this inside constructed, not init, so klass points to the most-derived
     GTypeClass, not ShellGLSLQuadClass.
  */
  klass = SHELL_GLSL_QUAD_GET_CLASS (object);
  self = SHELL_GLSL_QUAD (object);
  priv = shell_glsl_quad_get_instance_private (self);

  if (G_UNLIKELY (klass->base_pipeline == NULL))
    {
      klass->base_pipeline = cogl_pipeline_new (ctx);
      cogl_pipeline_set_blend (klass->base_pipeline, "RGBA = ADD (SRC_COLOR * (SRC_COLOR[A]), DST_COLOR * (1-SRC_COLOR[A]))", NULL);

      if (klass->build_pipeline != NULL)
        klass->build_pipeline (self);
    }

  priv->pipeline = cogl_pipeline_copy (klass->base_pipeline);

  cogl_pipeline_set_layer_null_texture (priv->pipeline, 0, COGL_TEXTURE_TYPE_2D);
}
Exemple #7
0
static void
paint_color_pipelines (TestState *state)
{
  CoglPipeline *temp_pipeline;
  int uniform_location;
  int i;

  /* Paint with the first pipeline that sets the uniforms to bright
     red */
  paint_pipeline (state->pipeline_red, 0);

  /* Paint with the two other pipelines. These inherit from the red
     pipeline and only override one other component. The values for
     the two other components should be inherited from the red
     pipeline. */
  paint_pipeline (state->pipeline_green, 1);
  paint_pipeline (state->pipeline_blue, 2);

  /* Try modifying a single pipeline for multiple rectangles */
  temp_pipeline = cogl_pipeline_copy (state->pipeline_green);
  uniform_location = cogl_pipeline_get_uniform_location (temp_pipeline,
                                                         "green");

  for (i = 0; i <= 8; i++)
    {
      cogl_pipeline_set_uniform_1f (temp_pipeline, uniform_location,
                                    i / 8.0f);
      paint_pipeline (temp_pipeline, i + 3);
    }

  cogl_object_unref (temp_pipeline);
}
static CoglPipeline *
get_base_texture_alpha_pipeline (CoglPangoPipelineCache *cache)
{
  if (cache->base_texture_alpha_pipeline == NULL)
    {
      CoglPipeline *pipeline;

      pipeline = cogl_pipeline_copy (get_base_texture_rgba_pipeline (cache));
      cache->base_texture_alpha_pipeline = pipeline;

      /* The default combine mode of materials is to modulate (A x B)
       * the texture RGBA channels with the RGBA channels of the
       * previous layer (which in our case is just the font color)
       *
       * Since the RGB for an alpha texture is defined as 0, this gives us:
       *
       *  result.rgb = color.rgb * 0
       *  result.a = color.a * texture.a
       *
       * What we want is premultiplied rgba values:
       *
       *  result.rgba = color.rgb * texture.a
       *  result.a = color.a * texture.a
       */
      cogl_pipeline_set_layer_combine (pipeline, 0, /* layer */
                                       "RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
                                       NULL);
    }

  return cache->base_texture_alpha_pipeline;
}
static void
clutter_colorize_effect_init (ClutterColorizeEffect *self)
{
  ClutterColorizeEffectClass *klass = CLUTTER_COLORIZE_EFFECT_GET_CLASS (self);

  if (G_UNLIKELY (klass->base_pipeline == NULL))
    {
      CoglSnippet *snippet;
      CoglContext *ctx =
        clutter_backend_get_cogl_context (clutter_get_default_backend ());

      klass->base_pipeline = cogl_pipeline_new (ctx);

      snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
                                  colorize_glsl_declarations,
                                  colorize_glsl_source);
      cogl_pipeline_add_snippet (klass->base_pipeline, snippet);
      cogl_object_unref (snippet);

      cogl_pipeline_set_layer_null_texture (klass->base_pipeline, 0);
    }

  self->pipeline = cogl_pipeline_copy (klass->base_pipeline);

  self->tint_uniform =
    cogl_pipeline_get_uniform_location (self->pipeline, "tint");

  self->tint = default_tint;

  update_tint_uniform (self);
}
Exemple #10
0
CoglPipeline *
cogl_gst_video_sink_get_pipeline (CoglGstVideoSink *vt)
{
  CoglGstVideoSinkPrivate *priv;

  g_return_val_if_fail (COGL_GST_IS_VIDEO_SINK (vt), NULL);

  priv = vt->priv;

  if (priv->pipeline == NULL)
    {
      priv->pipeline = cogl_pipeline_new (priv->ctx);
      cogl_gst_video_sink_setup_pipeline (vt, priv->pipeline);
      cogl_gst_video_sink_attach_frame (vt, priv->pipeline);
      priv->frame_dirty = FALSE;
    }
  else if (priv->frame_dirty)
    {
      CoglPipeline *pipeline = cogl_pipeline_copy (priv->pipeline);
      cogl_object_unref (priv->pipeline);
      priv->pipeline = pipeline;

      cogl_gst_video_sink_attach_frame (vt, pipeline);
      priv->frame_dirty = FALSE;
    }

  return priv->pipeline;
}
Exemple #11
0
/**
 * _st_create_texture_pipeline:
 * @src_texture: The CoglTexture for the pipeline
 *
 * Creates a simple pipeline which contains the given texture as a
 * single layer.
 */
CoglPipeline *
_st_create_texture_pipeline (CoglTexture *src_texture)
{
    static CoglPipeline *texture_pipeline_template = NULL;
    CoglPipeline *pipeline;

    g_return_val_if_fail (src_texture != NULL, NULL);

    /* The only state used in the pipeline that would affect the shader
       generation is the texture type on the layer. Therefore we create
       a template pipeline which sets this state and all texture
       pipelines are created as a copy of this. That way Cogl can find
       the shader state for the pipeline more quickly by looking at the
       pipeline ancestry instead of resorting to the shader cache. */
    if (G_UNLIKELY (texture_pipeline_template == NULL))
    {
        CoglContext *ctx =
            clutter_backend_get_cogl_context (clutter_get_default_backend ());

        texture_pipeline_template = cogl_pipeline_new (ctx);
        cogl_pipeline_set_layer_null_texture (texture_pipeline_template,
                                              0, /* layer */
                                              COGL_TEXTURE_TYPE_2D);
    }

    pipeline = cogl_pipeline_copy (texture_pipeline_template);

    if (src_texture != NULL)
        cogl_pipeline_set_layer_texture (pipeline, 0, src_texture);

    return pipeline;
}
static void
shell_anamorphosis_effect_init (ShellAnamorphosisEffect *self)
{
  static CoglPipeline *pipeline_template;

  ShellAnamorphosisEffectPrivate *priv = shell_anamorphosis_effect_get_instance_private (self);

  if (G_UNLIKELY (pipeline_template == NULL))
    {
      CoglSnippet *snippet;
      CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());

      pipeline_template = cogl_pipeline_new (ctx);

      snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP, anamorphosis_decls, NULL);
      cogl_snippet_set_pre (snippet, anamorphosis_pre);
      cogl_pipeline_add_layer_snippet (pipeline_template, 0, snippet);
      cogl_object_unref (snippet);

      cogl_pipeline_set_layer_null_texture (pipeline_template,
                                            0, /* layer number */
                                            COGL_TEXTURE_TYPE_2D);
    }

  priv->pipeline = cogl_pipeline_copy (pipeline_template);
  priv->tex_width_uniform = cogl_pipeline_get_uniform_location (priv->pipeline, "tex_width");
  priv->tex_height_uniform = cogl_pipeline_get_uniform_location (priv->pipeline, "tex_height");
  priv->_x_uniform = cogl_pipeline_get_uniform_location (priv->pipeline, "_x");
  priv->_y_uniform = cogl_pipeline_get_uniform_location (priv->pipeline, "_y");
  priv->_z_uniform = cogl_pipeline_get_uniform_location (priv->pipeline, "_z");

  update_uniforms (self);
}
Exemple #13
0
CoglPipeline *
_st_create_shadow_pipeline (StShadow    *shadow_spec,
                            CoglTexture *src_texture)
{
    ClutterBackend *backend = clutter_get_default_backend ();
    CoglContext *ctx = clutter_backend_get_cogl_context (backend);

    static CoglPipeline *shadow_pipeline_template = NULL;

    CoglPipeline *pipeline;
    CoglTexture *texture;
    guchar *pixels_in, *pixels_out;
    gint width_in, height_in, rowstride_in;
    gint width_out, height_out, rowstride_out;

    g_return_val_if_fail (shadow_spec != NULL, NULL);
    g_return_val_if_fail (src_texture != NULL, NULL);

    width_in  = cogl_texture_get_width  (src_texture);
    height_in = cogl_texture_get_height (src_texture);
    rowstride_in = (width_in + 3) & ~3;

    pixels_in  = g_malloc0 (rowstride_in * height_in);

    cogl_texture_get_data (src_texture, COGL_PIXEL_FORMAT_A_8,
                           rowstride_in, pixels_in);

    pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in,
                              shadow_spec->blur,
                              &width_out, &height_out, &rowstride_out);
    g_free (pixels_in);

    texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (ctx, width_out, height_out,
                            COGL_PIXEL_FORMAT_A_8,
                            rowstride_out,
                            pixels_out,
                            NULL));

    g_free (pixels_out);

    if (G_UNLIKELY (shadow_pipeline_template == NULL))
    {
        CoglContext *ctx =
            clutter_backend_get_cogl_context (clutter_get_default_backend ());

        shadow_pipeline_template = cogl_pipeline_new (ctx);

        /* We set up the pipeline to blend the shadow texture with the combine
         * constant, but defer setting the latter until painting, so that we can
         * take the actor's overall opacity into account. */
        cogl_pipeline_set_layer_combine (shadow_pipeline_template, 0,
                                         "RGBA = MODULATE (CONSTANT, TEXTURE[A])",
                                         NULL);
    }

    pipeline = cogl_pipeline_copy (shadow_pipeline_template);
    cogl_pipeline_set_layer_texture (pipeline, 0, texture);
    cogl_object_unref (texture);
    return pipeline;
}
CoglPipeline *
_cogl_pango_pipeline_cache_get (CoglPangoPipelineCache *cache,
                                CoglHandle texture)
{
  CoglPangoPipelineCacheEntry *entry;
  PipelineDestroyNotifyData *destroy_data;
  static CoglUserDataKey pipeline_destroy_notify_key;

  /* Look for an existing entry */
  entry = g_hash_table_lookup (cache->hash_table, texture);

  if (entry)
    return cogl_object_ref (entry->pipeline);

  /* No existing pipeline was found so let's create another */
  entry = g_slice_new (CoglPangoPipelineCacheEntry);

  if (texture)
    {
      CoglPipeline *base;

      entry->texture = cogl_object_ref (texture);

      if (cogl_texture_get_format (entry->texture) == COGL_PIXEL_FORMAT_A_8)
        base = get_base_texture_alpha_pipeline (cache);
      else
        base = get_base_texture_rgba_pipeline (cache);

      entry->pipeline = cogl_pipeline_copy (base);

      cogl_pipeline_set_layer_texture (entry->pipeline, 0 /* layer */, texture);
    }
  else
    {
      entry->texture = NULL;
      entry->pipeline = cogl_pipeline_new ();
    }

  /* Add a weak reference to the pipeline so we can remove it from the
     hash table when it is destroyed */
  destroy_data = g_slice_new (PipelineDestroyNotifyData);
  destroy_data->cache = cache;
  destroy_data->texture = texture;
  cogl_object_set_user_data (entry->pipeline,
                             &pipeline_destroy_notify_key,
                             destroy_data,
                             pipeline_destroy_notify_cb);

  g_hash_table_insert (cache->hash_table,
                       texture ? cogl_object_ref (texture) : NULL,
                       entry);

  /* This doesn't take a reference on the pipeline so that it will use
     the newly created reference */
  return entry->pipeline;
}
Exemple #15
0
static CoglBool
validate_first_layer_cb (CoglPipeline *pipeline,
                         int layer_index,
                         void *user_data)
{
  ValidateFirstLayerState *state = user_data;
  CoglPipelineWrapMode clamp_to_edge =
    COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE;
  CoglPipelineWrapMode wrap_s;
  CoglPipelineWrapMode wrap_t;

  /* We can't use hardware repeat so we need to set clamp to edge
   * otherwise it might pull in edge pixels from the other side. By
   * default WRAP_MODE_AUTOMATIC becomes CLAMP_TO_EDGE so we only need
   * to override if the wrap mode isn't already automatic or
   * clamp_to_edge.
   */
  wrap_s = cogl_pipeline_get_layer_wrap_mode_s (pipeline, layer_index);
  if (wrap_s != COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE &&
      wrap_s != COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
    {
      if (!state->override_pipeline)
        state->override_pipeline = cogl_pipeline_copy (pipeline);
      cogl_pipeline_set_layer_wrap_mode_s (state->override_pipeline,
                                           layer_index, clamp_to_edge);
    }

  wrap_t = cogl_pipeline_get_layer_wrap_mode_t (pipeline, layer_index);
  if (wrap_t != COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE &&
      wrap_t != COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
    {
      if (!state->override_pipeline)
        state->override_pipeline = cogl_pipeline_copy (pipeline);
      cogl_pipeline_set_layer_wrap_mode_t (state->override_pipeline,
                                           layer_index, clamp_to_edge);
    }

  return FALSE;
}
Exemple #16
0
void
cogl_path_stroke (CoglPath *path,
                  CoglFramebuffer *framebuffer,
                  CoglPipeline *pipeline)
{
  CoglPathData *data;
  CoglPipeline *copy = NULL;
  unsigned int path_start;
  int path_num = 0;
  CoglPathNode *node;

  _COGL_RETURN_IF_FAIL (cogl_is_path (path));
  _COGL_RETURN_IF_FAIL (cogl_is_framebuffer (framebuffer));
  _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline));

  data = path->data;

  if (data->path_nodes->len == 0)
    return;

  if (cogl_pipeline_get_n_layers (pipeline) != 0)
    {
      copy = cogl_pipeline_copy (pipeline);
      _cogl_pipeline_prune_to_n_layers (copy, 0);
      pipeline = copy;
    }

  _cogl_path_build_stroke_attribute_buffer (path);

  for (path_start = 0;
       path_start < data->path_nodes->len;
       path_start += node->path_size)
    {
      CoglPrimitive *primitive;

      node = &g_array_index (data->path_nodes, CoglPathNode, path_start);

      primitive =
        cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_LINE_STRIP,
                                            node->path_size,
                                            &data->stroke_attributes[path_num],
                                            1);
      cogl_primitive_draw (primitive, framebuffer, pipeline);
      cogl_object_unref (primitive);

      path_num++;
    }

  if (copy)
    cogl_object_unref (copy);
}
Exemple #17
0
static void
paint (CoglFramebuffer *fb,
       const CoglGstRectangle *video_output,
       void *user_data)
{
  Data *data = user_data;
  CoglPipeline *pipeline;

  pipeline = cogl_pipeline_copy (data->pipeline);
  cogl_gst_video_sink_attach_frame (data->sink, pipeline);
  cogl_object_unref (data->pipeline);
  data->pipeline = pipeline;

  if (data->last_output_width != video_output->width ||
      data->last_output_height != video_output->height)
    {
      int location =
        cogl_pipeline_get_uniform_location (pipeline, "pixel_step");

      if (location != -1)
        {
          float value[2] =
            {
              1.0f / video_output->width,
              1.0f / video_output->height
            };

          cogl_pipeline_set_uniform_float (pipeline,
                                           location,
                                           2, /* n_components */
                                           1, /* count */
                                           value);
        }

      data->last_output_width = video_output->width;
      data->last_output_height = video_output->height;
    }


  borders_draw (data->borders, fb, video_output);

  cogl_framebuffer_draw_rectangle (fb,
                                   pipeline,
                                   video_output->x,
                                   video_output->y,
                                   video_output->x +
                                   video_output->width,
                                   video_output->y +
                                   video_output->height);
}
Exemple #18
0
static void
texture_tower_revalidate_fbo (MetaTextureTower *tower,
                              int               level)
{
  CoglTexture *source_texture = tower->textures[level - 1];
  int source_texture_width = cogl_texture_get_width (source_texture);
  int source_texture_height = cogl_texture_get_height (source_texture);
  CoglTexture *dest_texture = tower->textures[level];
  int dest_texture_width = cogl_texture_get_width (dest_texture);
  int dest_texture_height = cogl_texture_get_height (dest_texture);
  Box *invalid = &tower->invalid[level];
  CoglFramebuffer *fb;
  CoglError *catch_error = NULL;
  CoglPipeline *pipeline;

  if (tower->fbos[level] == NULL)
    tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture);

  fb = COGL_FRAMEBUFFER (tower->fbos[level]);

  if (!cogl_framebuffer_allocate (fb, &catch_error))
    {
      cogl_error_free (catch_error);
      return;
    }

  cogl_framebuffer_orthographic (fb, 0, 0, dest_texture_width, dest_texture_height, -1., 1.);

  if (!tower->pipeline_template)
    {
      CoglContext *ctx =
        clutter_backend_get_cogl_context (clutter_get_default_backend ());
      tower->pipeline_template = cogl_pipeline_new (ctx);
      cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL);
    }

  pipeline = cogl_pipeline_copy (tower->pipeline_template);
  cogl_pipeline_set_layer_texture (pipeline, 0, tower->textures[level - 1]);

  cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
                                            invalid->x1, invalid->y1,
                                            invalid->x2, invalid->y2,
                                            (2. * invalid->x1) / source_texture_width,
                                            (2. * invalid->y1) / source_texture_height,
                                            (2. * invalid->x2) / source_texture_width,
                                            (2. * invalid->y2) / source_texture_height);

  cogl_object_unref (pipeline);
}
Exemple #19
0
static void
set_up_pipeline (CoglGstVideoSink *sink,
                 void *user_data)
{
  Data *data = (Data *) user_data;

  if (data->pipeline)
    cogl_object_unref (data->pipeline);

  data->pipeline = cogl_pipeline_copy (data->base_pipeline);
  cogl_gst_video_sink_setup_pipeline (data->sink, data->pipeline);

  data->last_output_width = 0;
  data->last_output_height = 0;
}
Exemple #20
0
static gpointer
clutter_gst_frame_copy (gpointer data)
{
  if (G_LIKELY (data))
    {
      ClutterGstFrame *frame = g_slice_dup (ClutterGstFrame, data);

      if (frame->pipeline != COGL_INVALID_HANDLE)
        frame->pipeline = cogl_pipeline_copy (frame->pipeline);

      return frame;
    }

  return NULL;
}
Exemple #21
0
static void
_cogl_path_stroke_nodes (CoglPath *path)
{
  CoglPathData *data = path->data;
  CoglPipeline *copy = NULL;
  CoglPipeline *source;
  unsigned int path_start;
  int path_num = 0;
  CoglPathNode *node;

  _COGL_GET_CONTEXT (ctx, NO_RETVAL);

  source = cogl_get_source ();

  if (cogl_pipeline_get_n_layers (source) != 0)
    {
      copy = cogl_pipeline_copy (source);
      _cogl_pipeline_prune_to_n_layers (copy, 0);
      source = copy;
    }

  _cogl_path_build_stroke_attribute_buffer (path);

  cogl_push_source (source);

  for (path_start = 0;
       path_start < data->path_nodes->len;
       path_start += node->path_size)
    {
      node = &g_array_index (data->path_nodes, CoglPathNode, path_start);

      cogl_framebuffer_vdraw_attributes (cogl_get_draw_framebuffer (),
                                         source,
                                         COGL_VERTICES_MODE_LINE_STRIP,
                                         0, node->path_size,
                                         data->stroke_attributes[path_num],
                                         NULL);

      path_num++;
    }

  cogl_pop_source ();

  if (copy)
    cogl_object_unref (copy);
}
Exemple #22
0
static void
test_short_verts (TestState *state, int offset_x, int offset_y)
{
  CoglAttribute *attributes[2];
  CoglAttributeBuffer *buffer;
  CoglPipeline *pipeline, *pipeline2;
  CoglSnippet *snippet;
  CoglPrimitive *primitive;

  static const ShortVert short_verts[] =
    {
      { -10, -10, /**/ 0xffff, 0, 0, 0xffff },
      { -1, -10,  /**/ 0xffff, 0, 0, 0xffff },
      { -5, -1, /**/ 0xffff, 0, 0, 0xffff }
    };


  pipeline = cogl_pipeline_copy (state->pipeline);

  cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255);

  buffer = cogl_attribute_buffer_new (test_ctx,
                                      sizeof (short_verts), short_verts);
  attributes[0] = cogl_attribute_new (buffer,
                                      "cogl_position_in",
                                      sizeof (ShortVert),
                                      G_STRUCT_OFFSET (ShortVert, x),
                                      2, /* n_components */
                                      COGL_ATTRIBUTE_TYPE_SHORT);
  attributes[1] = cogl_attribute_new (buffer,
                                      "color",
                                      sizeof (ShortVert),
                                      G_STRUCT_OFFSET (ShortVert, r),
                                      4, /* n_components */
                                      COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT);
  cogl_attribute_set_normalized (attributes[1], TRUE);

  cogl_framebuffer_push_matrix (test_fb);
  cogl_framebuffer_translate (test_fb,
                              offset_x + 10.0f,
                              offset_y + 10.0f,
                              0.0f);

  primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES,
                                                  3, /* n_vertices */
                                                  attributes,
                                                  2); /* n_attributes */
  cogl_primitive_draw (primitive, test_fb, pipeline);
  cogl_object_unref (primitive);

  cogl_framebuffer_pop_matrix (test_fb);

  cogl_object_unref (attributes[0]);

  /* Test again treating the attribute as unsigned */
  attributes[0] = cogl_attribute_new (buffer,
                                      "cogl_position_in",
                                      sizeof (ShortVert),
                                      G_STRUCT_OFFSET (ShortVert, x),
                                      2, /* n_components */
                                      COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT);

  /* XXX: this is a hack to force the pipeline to use the glsl backend
   * because we know it's not possible to test short vertex position
   * components with the legacy GL backend since which might otherwise
   * be used internally... */
  pipeline2 = cogl_pipeline_new (test_ctx);
  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX,
                              "attribute vec4 color;",
                              "cogl_color_out = vec4 (0.0, 1.0, 0.0, 1.0);");
  cogl_pipeline_add_snippet (pipeline2, snippet);

  cogl_framebuffer_push_matrix (test_fb);
  cogl_framebuffer_translate (test_fb,
                              offset_x + 10.0f - 65525.0f,
                              offset_y - 65525,
                              0.0f);

  primitive = cogl_primitive_new_with_attributes (COGL_VERTICES_MODE_TRIANGLES,
                                                  3, /* n_vertices */
                                                  attributes,
                                                  1); /* n_attributes */
  cogl_primitive_draw (primitive, test_fb, pipeline2);
  cogl_object_unref (primitive);

  cogl_framebuffer_pop_matrix (test_fb);

  cogl_object_unref (attributes[0]);

  cogl_object_unref (pipeline2);
  cogl_object_unref (pipeline);
  cogl_object_unref (buffer);

  test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff);
  test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff);
}
Exemple #23
0
static void
do_test (CoglBool check_orientation,
         CoglBool use_glsl)
{
  int fb_width = cogl_framebuffer_get_width (test_fb);
  int fb_height = cogl_framebuffer_get_height (test_fb);
  CoglPrimitive *prim;
  CoglError *error = NULL;
  CoglTexture2D *tex_2d;
  CoglPipeline *pipeline, *solid_pipeline;
  int tex_height;

  cogl_framebuffer_orthographic (test_fb,
                                 0, 0, /* x_1, y_1 */
                                 fb_width, /* x_2 */
                                 fb_height /* y_2 */,
                                 -1, 100 /* near/far */);

  cogl_framebuffer_clear4f (test_fb,
                            COGL_BUFFER_BIT_COLOR,
                            1.0f, 1.0f, 1.0f, 1.0f);

  /* If we're not checking the orientation of the point sprite then
   * we'll set the height of the texture to 1 so that the vertical
   * orientation does not matter */
  if (check_orientation)
    tex_height = 2;
  else
    tex_height = 1;

  tex_2d = cogl_texture_2d_new_from_data (test_ctx,
                                          2, tex_height, /* width/height */
                                          COGL_PIXEL_FORMAT_RGB_888,
                                          COGL_PIXEL_FORMAT_ANY,
                                          6, /* row stride */
                                          tex_data,
                                          &error);
  g_assert (tex_2d != NULL);
  g_assert (error == NULL);

  pipeline = cogl_pipeline_new (test_ctx);
  cogl_pipeline_set_layer_texture (pipeline, 0, tex_2d);

  cogl_pipeline_set_layer_filters (pipeline,
                                   0, /* layer_index */
                                   COGL_PIPELINE_FILTER_NEAREST,
                                   COGL_PIPELINE_FILTER_NEAREST);
  cogl_pipeline_set_point_size (pipeline, POINT_SIZE);

  /* If we're using GLSL then we don't need to enable point sprite
   * coords and we can just directly reference cogl_point_coord in the
   * snippet */
  if (use_glsl)
    {
      CoglSnippet *snippet =
        cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
                          NULL, /* declarations */
                          NULL /* post */);
      static const char source[] =
        "  cogl_texel = texture2D (cogl_sampler, cogl_point_coord);\n";

      cogl_snippet_set_replace (snippet, source);

      /* Keep a reference to the original pipeline because there is no
       * way to remove a snippet in order to recreate the solid
       * pipeline */
      solid_pipeline = cogl_pipeline_copy (pipeline);

      cogl_pipeline_add_layer_snippet (pipeline, 0, snippet);

      cogl_object_unref (snippet);
    }
  else
    {
      CoglBool res =
        cogl_pipeline_set_layer_point_sprite_coords_enabled (pipeline,
                                                             /* layer_index */
                                                             0,
                                                             /* enable */
                                                             TRUE,
                                                             &error);
      g_assert (res == TRUE);
      g_assert (error == NULL);

      solid_pipeline = cogl_pipeline_copy (pipeline);

      res =
        cogl_pipeline_set_layer_point_sprite_coords_enabled (solid_pipeline,
                                                             /* layer_index */
                                                             0,
                                                             /* enable */
                                                             FALSE,
                                                             &error);

      g_assert (res == TRUE);
      g_assert (error == NULL);
    }

  prim = cogl_primitive_new_p2t2 (test_ctx,
                                  COGL_VERTICES_MODE_POINTS,
                                  1, /* n_vertices */
                                  &point);

  cogl_primitive_draw (prim, test_fb, pipeline);

  /* Render the primitive again without point sprites to make sure
     disabling it works */

  cogl_framebuffer_push_matrix (test_fb);
  cogl_framebuffer_translate (test_fb,
                              POINT_SIZE * 2, /* x */
                              0.0f, /* y */
                              0.0f /* z */);
  cogl_primitive_draw (prim, test_fb, solid_pipeline);
  cogl_framebuffer_pop_matrix (test_fb);

  cogl_object_unref (prim);
  cogl_object_unref (solid_pipeline);
  cogl_object_unref (pipeline);
  cogl_object_unref (tex_2d);

  test_utils_check_pixel (test_fb,
                          POINT_SIZE - POINT_SIZE / 4,
                          POINT_SIZE - POINT_SIZE / 4,
                          0x0000ffff);
  test_utils_check_pixel (test_fb,
                          POINT_SIZE + POINT_SIZE / 4,
                          POINT_SIZE - POINT_SIZE / 4,
                          0x00ff00ff);
  test_utils_check_pixel (test_fb,
                          POINT_SIZE - POINT_SIZE / 4,
                          POINT_SIZE + POINT_SIZE / 4,
                          check_orientation ?
                          0x00ffffff :
                          0x0000ffff);
  test_utils_check_pixel (test_fb,
                          POINT_SIZE + POINT_SIZE / 4,
                          POINT_SIZE + POINT_SIZE / 4,
                          check_orientation ?
                          0xff0000ff :
                          0x00ff00ff);

  /* When rendering without the point sprites all of the texture
     coordinates should be 0,0 so it should get the top-left texel
     which is blue */
  test_utils_check_region (test_fb,
                           POINT_SIZE * 3 - POINT_SIZE / 2 + 1,
                           POINT_SIZE - POINT_SIZE / 2 + 1,
                           POINT_SIZE - 2, POINT_SIZE - 2,
                           0x0000ffff);

  if (cogl_test_verbose ())
    g_print ("OK\n");
}
static void
test_short_verts (TestState *state, int offset_x, int offset_y)
{
  CoglAttribute *attributes[1];
  CoglAttributeBuffer *buffer;
  CoglPipeline *pipeline, *pipeline2;
  CoglSnippet *snippet;

  static const ShortVert short_verts[] =
    {
      { -10, -10 },
      { -1, -10 },
      { -5, -1 }
    };

  pipeline = cogl_pipeline_new (test_ctx);
  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_TRANSFORM,
                              "attribute vec2 pos;",
                              NULL);
  cogl_snippet_set_replace (snippet,
                            "cogl_position_out = "
                            "cogl_modelview_projection_matrix * "
                            "vec4 (pos, 0.0, 1.0);");
  cogl_pipeline_add_snippet (pipeline, snippet);
  cogl_object_unref (snippet);

  cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255);

  buffer = cogl_attribute_buffer_new (test_ctx,
                                      sizeof (short_verts), short_verts);
  attributes[0] = cogl_attribute_new (buffer,
                                      "pos",
                                      sizeof (ShortVert),
                                      G_STRUCT_OFFSET (ShortVert, x),
                                      2, /* n_components */
                                      COGL_ATTRIBUTE_TYPE_SHORT);

  cogl_framebuffer_push_matrix (test_fb);
  cogl_framebuffer_translate (test_fb,
                              offset_x + 10.0f,
                              offset_y + 10.0f,
                              0.0f);

  cogl_framebuffer_draw_attributes (test_fb,
                                    pipeline,
                                    COGL_VERTICES_MODE_TRIANGLES,
                                    0, /* first_vertex */
                                    3, /* n_vertices */
                                    attributes,
                                    1 /* n_attributes */);

  cogl_framebuffer_pop_matrix (test_fb);

  cogl_object_unref (attributes[0]);

  /* Test again treating the attribute as unsigned */
  attributes[0] = cogl_attribute_new (buffer,
                                      "pos",
                                      sizeof (ShortVert),
                                      G_STRUCT_OFFSET (ShortVert, x),
                                      2, /* n_components */
                                      COGL_ATTRIBUTE_TYPE_UNSIGNED_SHORT);

  pipeline2 = cogl_pipeline_copy (pipeline);
  cogl_pipeline_set_color4ub (pipeline2, 0, 255, 0, 255);

  cogl_framebuffer_push_matrix (test_fb);
  cogl_framebuffer_translate (test_fb,
                              offset_x + 10.0f - 65525.0f,
                              offset_y - 65525,
                              0.0f);

  cogl_framebuffer_draw_attributes (test_fb,
                                    pipeline2,
                                    COGL_VERTICES_MODE_TRIANGLES,
                                    0, /* first_vertex */
                                    3, /* n_vertices */
                                    attributes,
                                    1 /* n_attributes */);

  cogl_framebuffer_pop_matrix (test_fb);

  cogl_object_unref (attributes[0]);

  cogl_object_unref (pipeline2);
  cogl_object_unref (pipeline);
  cogl_object_unref (buffer);

  test_utils_check_pixel (test_fb, offset_x + 5, offset_y + 5, 0xff0000ff);
  test_utils_check_pixel (test_fb, offset_x + 15, offset_y + 5, 0x00ff00ff);
}
void
_cogl_gl_flush_attributes_state (CoglFramebuffer *framebuffer,
                                 CoglPipeline *pipeline,
                                 CoglFlushLayerState *layers_state,
                                 CoglDrawFlags flags,
                                 CoglAttribute **attributes,
                                 int n_attributes)
{
  CoglContext *ctx = framebuffer->context;
  int i;
  CoglBool skip_gl_color = FALSE;
  CoglPipeline *copy = NULL;

  /* Iterate the attributes to work out whether blending needs to be
     enabled and how many texture coords there are. We need to do this
     before flushing the pipeline. */
  for (i = 0; i < n_attributes; i++)
    switch (attributes[i]->name_state->name_id)
      {
      case COGL_ATTRIBUTE_NAME_ID_COLOR_ARRAY:
        if ((flags & COGL_DRAW_COLOR_ATTRIBUTE_IS_OPAQUE) == 0 &&
            !_cogl_pipeline_get_real_blend_enabled (pipeline))
          {
            CoglPipelineBlendEnable blend_enable =
              COGL_PIPELINE_BLEND_ENABLE_ENABLED;
            copy = cogl_pipeline_copy (pipeline);
            _cogl_pipeline_set_blend_enabled (copy, blend_enable);
            pipeline = copy;
          }
        skip_gl_color = TRUE;
        break;

      default:
        break;
      }

  if (G_UNLIKELY (layers_state->options.flags))
    {
      /* If we haven't already created a derived pipeline... */
      if (!copy)
        {
          copy = cogl_pipeline_copy (pipeline);
          pipeline = copy;
        }
      _cogl_pipeline_apply_overrides (pipeline, &layers_state->options);

      /* TODO:
       * overrides = cogl_pipeline_get_data (pipeline,
       *                                     last_overrides_key);
       * if (overrides)
       *   {
       *     age = cogl_pipeline_get_age (pipeline);
       *     XXX: actually we also need to check for legacy_state
       *     and blending overrides for use of glColorPointer...
       *     if (overrides->ags != age ||
       *         memcmp (&overrides->options, &options,
       *                 sizeof (options) != 0)
       *       {
       *         cogl_object_unref (overrides->weak_pipeline);
       *         g_slice_free (Overrides, overrides);
       *         overrides = NULL;
       *       }
       *   }
       * if (!overrides)
       *   {
       *     overrides = g_slice_new (Overrides);
       *     overrides->weak_pipeline =
       *       cogl_pipeline_weak_copy (pipeline);
       *     _cogl_pipeline_apply_overrides (overrides->weak_pipeline,
       *                                     &options);
       *
       *     cogl_pipeline_set_data (pipeline, last_overrides_key,
       *                             weak_overrides,
       *                             free_overrides_cb,
       *                             NULL);
       *   }
       * pipeline = overrides->weak_pipeline;
       */
    }

  _cogl_pipeline_flush_gl_state (pipeline,
                                 framebuffer,
                                 skip_gl_color);

  _cogl_bitmask_clear_all (&ctx->enable_builtin_attributes_tmp);
  _cogl_bitmask_clear_all (&ctx->enable_texcoord_attributes_tmp);
  _cogl_bitmask_clear_all (&ctx->enable_custom_attributes_tmp);

  /* Bind the attribute pointers. We need to do this after the
   * pipeline is flushed because when using GLSL that is the only
   * point when we can determine the attribute locations */

  for (i = 0; i < n_attributes; i++)
    {
      CoglAttribute *attribute = attributes[i];
      CoglAttributeBuffer *attribute_buffer;
      CoglBuffer *buffer;
      uint8_t *base;

      if (attribute->is_buffered)
        {
          attribute_buffer = cogl_attribute_get_buffer (attribute);
          buffer = COGL_BUFFER (attribute_buffer);

          /* Note: we don't try and catch errors with binding buffers
           * here since OOM errors at this point indicate that nothing
           * has yet been uploaded to attribute buffer which we
           * consider to be a programmer error.
           */
          base =
            _cogl_buffer_gl_bind (buffer,
                                  COGL_BUFFER_BIND_TARGET_ATTRIBUTE_BUFFER,
                                  NULL);

          if (pipeline->progend == COGL_PIPELINE_PROGEND_GLSL)
            setup_generic_buffered_attribute (ctx, pipeline, attribute, base);
          else
            setup_legacy_buffered_attribute (ctx, pipeline, attribute, base);

          _cogl_buffer_gl_unbind (buffer);
        }
      else
        {
          if (pipeline->progend == COGL_PIPELINE_PROGEND_GLSL)
            setup_generic_const_attribute (ctx, pipeline, attribute);
          else
            setup_legacy_const_attribute (ctx, pipeline, attribute);
        }
    }

  apply_attribute_enable_updates (ctx, pipeline);

  if (copy)
    cogl_object_unref (copy);
}
Exemple #26
0
static void
paint_test_backface_culling (TestState *state)
{
  int draw_num;
  CoglPipeline *base_pipeline = cogl_pipeline_new ();
  CoglColor clear_color;

  cogl_ortho (0, state->width, /* left, right */
              state->height, 0, /* bottom, top */
              -1, 100 /* z near, far */);

  cogl_color_init_from_4ub (&clear_color, 0x00, 0x00, 0x00, 0xff);
  cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_STENCIL);

  cogl_pipeline_set_layer_texture (base_pipeline, 0, state->texture);

  cogl_pipeline_set_layer_filters (base_pipeline, 0,
                                   COGL_PIPELINE_FILTER_NEAREST,
                                   COGL_PIPELINE_FILTER_NEAREST);

  /* Render the scene sixteen times to test all of the combinations of
     cull face mode, legacy state and winding orders */
  for (draw_num = 0; draw_num < 16; draw_num++)
    {
      float x1 = 0, x2, y1 = 0, y2 = (float)(TEXTURE_RENDER_SIZE);
      CoglTextureVertex verts[4];
      CoglPipeline *pipeline;

      cogl_push_matrix ();
      cogl_translate (0, TEXTURE_RENDER_SIZE * draw_num, 0);

      pipeline = cogl_pipeline_copy (base_pipeline);

      cogl_set_backface_culling_enabled (USE_LEGACY_STATE (draw_num));
      cogl_pipeline_set_front_face_winding (pipeline, FRONT_WINDING (draw_num));
      cogl_pipeline_set_cull_face_mode (pipeline, CULL_FACE_MODE (draw_num));

      cogl_push_source (pipeline);

      memset (verts, 0, sizeof (verts));

      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a front-facing texture */
      cogl_rectangle (x1, y1, x2, y2);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a front-facing texture with flipped texcoords */
      cogl_rectangle_with_texture_coords (x1, y1, x2, y2,
                                          1.0, 0.0, 0.0, 1.0);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a back-facing texture */
      cogl_rectangle (x2, y1, x1, y2);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* If the texture is sliced then cogl_polygon doesn't work so
         we'll just use a solid color instead */
      if (cogl_texture_is_sliced (state->texture))
        cogl_set_source_color4ub (255, 0, 0, 255);

      /* Draw a front-facing polygon */
      verts[0].x = x1;    verts[0].y = y2;
      verts[1].x = x2;    verts[1].y = y2;
      verts[2].x = x2;    verts[2].y = y1;
      verts[3].x = x1;    verts[3].y = y1;
      verts[0].tx = 0;    verts[0].ty = 0;
      verts[1].tx = 1.0;  verts[1].ty = 0;
      verts[2].tx = 1.0;  verts[2].ty = 1.0;
      verts[3].tx = 0;    verts[3].ty = 1.0;
      cogl_polygon (verts, 4, FALSE);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a back-facing polygon */
      verts[0].x = x1;    verts[0].y = y1;
      verts[1].x = x2;    verts[1].y = y1;
      verts[2].x = x2;    verts[2].y = y2;
      verts[3].x = x1;    verts[3].y = y2;
      verts[0].tx = 0;    verts[0].ty = 0;
      verts[1].tx = 1.0;  verts[1].ty = 0;
      verts[2].tx = 1.0;  verts[2].ty = 1.0;
      verts[3].tx = 0;    verts[3].ty = 1.0;
      cogl_polygon (verts, 4, FALSE);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      cogl_pop_matrix ();

      cogl_pop_source ();
      cogl_object_unref (pipeline);
    }

  cogl_object_unref (base_pipeline);
}
static void
st_background_effect_init (StBackgroundEffect *self)
{
  CoglContext *ctx;
  StBackgroundEffectClass *klass = ST_BACKGROUND_EFFECT_GET_CLASS (self);

  if (G_UNLIKELY (klass->base_pipeline == NULL))
    {
      ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());

      klass->base_pipeline = cogl_pipeline_new (ctx);
    }
    
  self->pipeline0 = cogl_pipeline_copy (klass->base_pipeline);
  self->pipeline1 = cogl_pipeline_copy (klass->base_pipeline);
  self->pipeline2 = cogl_pipeline_copy (klass->base_pipeline);
  self->pipeline3 = cogl_pipeline_copy (klass->base_pipeline);
  self->pipeline4 = cogl_pipeline_copy (klass->base_pipeline);

  CoglSnippet *snippet;
  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
                              box_blur_glsl_declarations,
                              NULL);

  cogl_snippet_set_replace (snippet, box_blur_glsl_shader);
  cogl_pipeline_add_layer_snippet (self->pipeline0, 0, snippet);
  cogl_pipeline_add_layer_snippet (self->pipeline1, 0, snippet);
  cogl_pipeline_add_layer_snippet (self->pipeline3, 0, snippet);
  cogl_object_unref (snippet);

  cogl_pipeline_set_layer_wrap_mode (self->pipeline0, 0,
                                     COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE);

  cogl_pipeline_set_layer_wrap_mode (self->pipeline0, 1,
                                     COGL_PIPELINE_WRAP_MODE_REPEAT);

  cogl_pipeline_set_layer_wrap_mode (self->pipeline1, 0,
                                     COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE);

  cogl_pipeline_set_layer_wrap_mode (self->pipeline2, 0,
                                     COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE);

  cogl_pipeline_set_layer_wrap_mode (self->pipeline3, 0,
                                     COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE);

  cogl_pipeline_set_layer_wrap_mode (self->pipeline4, 0,
                                     COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE);

  cogl_pipeline_set_cull_face_mode (self->pipeline0,
                                    COGL_PIPELINE_CULL_FACE_MODE_NONE);

  cogl_pipeline_set_cull_face_mode (self->pipeline1,
                                    COGL_PIPELINE_CULL_FACE_MODE_NONE);

  cogl_pipeline_set_cull_face_mode (self->pipeline2,
                                    COGL_PIPELINE_CULL_FACE_MODE_NONE);

  cogl_pipeline_set_cull_face_mode (self->pipeline3,
                                    COGL_PIPELINE_CULL_FACE_MODE_NONE);

  cogl_pipeline_set_cull_face_mode (self->pipeline4,
                                    COGL_PIPELINE_CULL_FACE_MODE_NONE);

  cogl_pipeline_set_layer_filters (self->pipeline0, 0,
                                   COGL_PIPELINE_FILTER_LINEAR,
                                   COGL_PIPELINE_FILTER_LINEAR);

  cogl_pipeline_set_layer_filters (self->pipeline0, 1,
                                   COGL_PIPELINE_FILTER_NEAREST,
                                   COGL_PIPELINE_FILTER_NEAREST);

  cogl_pipeline_set_layer_filters (self->pipeline1, 0,
                                   COGL_PIPELINE_FILTER_LINEAR,
                                   COGL_PIPELINE_FILTER_LINEAR);

  cogl_pipeline_set_layer_filters (self->pipeline2, 0,
                                   COGL_PIPELINE_FILTER_LINEAR,
                                   COGL_PIPELINE_FILTER_LINEAR);

  cogl_pipeline_set_layer_filters (self->pipeline3, 0,
                                   COGL_PIPELINE_FILTER_LINEAR,
                                   COGL_PIPELINE_FILTER_LINEAR);

  cogl_pipeline_set_layer_filters (self->pipeline4, 0,
                                   COGL_PIPELINE_FILTER_LINEAR,
                                   COGL_PIPELINE_FILTER_LINEAR);

  cogl_pipeline_set_layer_null_texture (self->pipeline0,
                                        0,
                                        COGL_TEXTURE_TYPE_2D);

  cogl_pipeline_set_layer_null_texture (self->pipeline1,
                                        0,
                                        COGL_TEXTURE_TYPE_2D);

  cogl_pipeline_set_layer_null_texture (self->pipeline2,
                                        0,
                                        COGL_TEXTURE_TYPE_2D);

  cogl_pipeline_set_layer_null_texture (self->pipeline3,
                                        0,
                                        COGL_TEXTURE_TYPE_2D);
  
  cogl_pipeline_set_layer_null_texture (self->pipeline4,
                                        0,
                                        COGL_TEXTURE_TYPE_2D);

  self->pixel_step_uniform0 =
    cogl_pipeline_get_uniform_location (self->pipeline0, "pixel_step");

  self->BumpTex_uniform =
    cogl_pipeline_get_uniform_location (self->pipeline0, "BumpTex");

  self->bump_step_uniform =
    cogl_pipeline_get_uniform_location (self->pipeline0, "bump_step");

  self->pixel_step_uniform1 =
    cogl_pipeline_get_uniform_location (self->pipeline1, "pixel_step");

  self->pixel_step_uniform2 =
    cogl_pipeline_get_uniform_location (self->pipeline3, "pixel_step");

  cogl_pipeline_set_blend (self->pipeline0,
                           "RGBA = ADD(SRC_COLOR, DST_COLOR*0)",
                           NULL);

  cogl_pipeline_set_blend (self->pipeline1,
                           "RGBA = ADD (SRC_COLOR*DST_COLOR[A], DST_COLOR*(1-DST_COLOR[A]))",
                           NULL);

  cogl_pipeline_set_color4ub (self->pipeline1,
                              0xff,
                              0xff,
                              0xff,
                              0xff);

  cogl_pipeline_set_alpha_test_function (self->pipeline2,
                                         COGL_PIPELINE_ALPHA_FUNC_LESS,
                                         0.004f);

  cogl_pipeline_set_color_mask (self->pipeline2,
                                COGL_COLOR_MASK_ALPHA);

  cogl_pipeline_set_blend (self->pipeline2,
                           "RGBA = ADD(SRC_COLOR, DST_COLOR*0)",
                           NULL);

  cogl_pipeline_set_alpha_test_function (self->pipeline3,
                                         COGL_PIPELINE_ALPHA_FUNC_GEQUAL,
                                         0.004f);
    
  cogl_pipeline_set_color_mask (self->pipeline3,
                                COGL_COLOR_MASK_ALL);

  cogl_pipeline_set_blend (self->pipeline3,
                           "RGBA = ADD (SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))",
                           NULL);

  cogl_pipeline_set_alpha_test_function (self->pipeline4,
                                         COGL_PIPELINE_ALPHA_FUNC_GEQUAL,
                                         0.004f);
    
  cogl_pipeline_set_color_mask (self->pipeline4,
                                COGL_COLOR_MASK_ALL);

  cogl_pipeline_set_blend (self->pipeline4,
                           "RGBA = ADD (SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))",
                           NULL);


  self->bg_texture = NULL;

  self->bg_sub_texture = NULL;

  self->bumpmap_location = "/usr/share/cinnamon/bumpmaps/frost.png";

  self->bg_bumpmap = st_cogl_texture_new_from_file_wrapper (self->bumpmap_location,
                                                            COGL_TEXTURE_NO_SLICING,
                                                            COGL_PIXEL_FORMAT_RGBA_8888_PRE);
  if (self->bg_bumpmap != NULL)
    {
      self->bumptex_width_i = cogl_texture_get_width (self->bg_bumpmap);
      self->bumptex_height_i = cogl_texture_get_height (self->bg_bumpmap);

      cogl_pipeline_set_layer_texture (self->pipeline0, 1, self->bg_bumpmap);
    }
  else
    {
      cogl_pipeline_set_layer_null_texture (self->pipeline0,
                                            1,
                                            COGL_TEXTURE_TYPE_2D);
    }

  cogl_pipeline_set_layer_combine (self->pipeline0,1,
                                   "RGBA = REPLACE (PREVIOUS)",
                                   NULL);

  self->old_time = 0;

  self->opacity = 0;

}
static void
paint_test_backface_culling (TestState *state,
                             CoglFramebuffer *framebuffer)
{
  int draw_num;
  CoglPipeline *base_pipeline = cogl_pipeline_new (test_ctx);

  cogl_framebuffer_orthographic (framebuffer,
                                 0, 0,
                                 state->width,
                                 state->height,
                                 -1,
                                 100);

  cogl_framebuffer_clear4f (framebuffer,
                            COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_STENCIL,
                            0, 0, 0, 1);

  cogl_pipeline_set_layer_texture (base_pipeline, 0, state->texture);

  cogl_pipeline_set_layer_filters (base_pipeline, 0,
                                   COGL_PIPELINE_FILTER_NEAREST,
                                   COGL_PIPELINE_FILTER_NEAREST);

  /* Render the scene eight times to test all of the combinations of
     cull face mode and winding orders */
  for (draw_num = 0; draw_num < 8; draw_num++)
    {
      float x1 = 0, x2, y1 = 0, y2 = (float)(TEXTURE_RENDER_SIZE);
      CoglTextureVertex verts[4];
      CoglPipeline *pipeline;

      cogl_framebuffer_push_matrix (framebuffer);
      cogl_framebuffer_translate (framebuffer,
                                  0, TEXTURE_RENDER_SIZE * draw_num, 0);

      pipeline = cogl_pipeline_copy (base_pipeline);

      cogl_pipeline_set_front_face_winding (pipeline, FRONT_WINDING (draw_num));
      cogl_pipeline_set_cull_face_mode (pipeline, CULL_FACE_MODE (draw_num));

      memset (verts, 0, sizeof (verts));

      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a front-facing texture */
      cogl_framebuffer_draw_rectangle (framebuffer, pipeline, x1, y1, x2, y2);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a front-facing texture with flipped texcoords */
      cogl_framebuffer_draw_textured_rectangle (framebuffer,
                                                pipeline,
                                                x1, y1, x2, y2,
                                                1.0, 0.0, 0.0, 1.0);

      x1 = x2;
      x2 = x1 + (float)(TEXTURE_RENDER_SIZE);

      /* Draw a back-facing texture */
      cogl_framebuffer_draw_rectangle (framebuffer, pipeline, x2, y1, x1, y2);

      cogl_framebuffer_pop_matrix (framebuffer);

      cogl_object_unref (pipeline);
    }

  cogl_object_unref (base_pipeline);
}
Exemple #29
0
static void
do_test (CoglBool check_orientation)
{
  int fb_width = cogl_framebuffer_get_width (test_fb);
  int fb_height = cogl_framebuffer_get_height (test_fb);
  CoglPrimitive *prim;
  CoglError *error = NULL;
  CoglTexture2D *tex_2d;
  CoglPipeline *pipeline, *solid_pipeline;
  CoglBool res;
  int tex_height;

  cogl_framebuffer_orthographic (test_fb,
                                 0, 0, /* x_1, y_1 */
                                 fb_width, /* x_2 */
                                 fb_height /* y_2 */,
                                 -1, 100 /* near/far */);

  cogl_framebuffer_clear4f (test_fb,
                            COGL_BUFFER_BIT_COLOR,
                            1.0f, 1.0f, 1.0f, 1.0f);

  /* If we're not checking the orientation of the point sprite then
   * we'll set the height of the texture to 1 so that the vertical
   * orientation does not matter */
  if (check_orientation)
    tex_height = 2;
  else
    tex_height = 1;

  tex_2d = cogl_texture_2d_new_from_data (test_ctx,
                                          2, tex_height, /* width/height */
                                          COGL_PIXEL_FORMAT_RGB_888,
                                          COGL_PIXEL_FORMAT_ANY,
                                          6, /* row stride */
                                          tex_data,
                                          &error);
  g_assert (tex_2d != NULL);
  g_assert (error == NULL);

  pipeline = cogl_pipeline_new (test_ctx);
  cogl_pipeline_set_layer_texture (pipeline, 0, COGL_TEXTURE (tex_2d));

  res = cogl_pipeline_set_layer_point_sprite_coords_enabled (pipeline,
                                                             /* layer_index */
                                                             0,
                                                             /* enable */
                                                             TRUE,
                                                             &error);
  g_assert (res == TRUE);
  g_assert (error == NULL);

  cogl_pipeline_set_layer_filters (pipeline,
                                   0, /* layer_index */
                                   COGL_PIPELINE_FILTER_NEAREST,
                                   COGL_PIPELINE_FILTER_NEAREST);
  cogl_pipeline_set_point_size (pipeline, POINT_SIZE);

  prim = cogl_primitive_new_p2t2 (test_ctx,
                                  COGL_VERTICES_MODE_POINTS,
                                  1, /* n_vertices */
                                  &point);

  cogl_primitive_draw (prim, test_fb, pipeline);

  /* Render the primitive again without point sprites to make sure
     disabling it works */
  solid_pipeline = cogl_pipeline_copy (pipeline);
  cogl_pipeline_set_layer_point_sprite_coords_enabled (solid_pipeline,
                                                       /* layer_index */
                                                       0,
                                                       /* enable */
                                                       FALSE,
                                                       &error);
  cogl_framebuffer_push_matrix (test_fb);
  cogl_framebuffer_translate (test_fb,
                              POINT_SIZE * 2, /* x */
                              0.0f, /* y */
                              0.0f /* z */);
  cogl_primitive_draw (prim, test_fb, solid_pipeline);
  cogl_framebuffer_pop_matrix (test_fb);

  cogl_object_unref (prim);
  cogl_object_unref (solid_pipeline);
  cogl_object_unref (pipeline);
  cogl_object_unref (tex_2d);

  test_utils_check_pixel (test_fb,
                          POINT_SIZE - POINT_SIZE / 4,
                          POINT_SIZE - POINT_SIZE / 4,
                          0x0000ffff);
  test_utils_check_pixel (test_fb,
                          POINT_SIZE + POINT_SIZE / 4,
                          POINT_SIZE - POINT_SIZE / 4,
                          0x00ff00ff);
  test_utils_check_pixel (test_fb,
                          POINT_SIZE - POINT_SIZE / 4,
                          POINT_SIZE + POINT_SIZE / 4,
                          check_orientation ?
                          0x00ffffff :
                          0x0000ffff);
  test_utils_check_pixel (test_fb,
                          POINT_SIZE + POINT_SIZE / 4,
                          POINT_SIZE + POINT_SIZE / 4,
                          check_orientation ?
                          0xff0000ff :
                          0x00ff00ff);

  /* When rendering without the point sprites all of the texture
     coordinates should be 0,0 so it should get the top-left texel
     which is blue */
  test_utils_check_region (test_fb,
                           POINT_SIZE * 3 - POINT_SIZE / 2 + 1,
                           POINT_SIZE - POINT_SIZE / 2 + 1,
                           POINT_SIZE - 2, POINT_SIZE - 2,
                           0x0000ffff);

  if (cogl_test_verbose ())
    g_print ("OK\n");
}
static void
clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect)
{
  ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect);
  ClutterDeformEffectPrivate *priv = self->priv;
  CoglHandle material;
  CoglPipeline *pipeline;
  CoglDepthState depth_state;
  CoglFramebuffer *fb = cogl_get_draw_framebuffer ();

  if (priv->is_dirty)
    {
      ClutterRect rect;
      gboolean mapped_buffer;
      CoglVertexP3T2C4 *verts;
      ClutterActor *actor;
      gfloat width, height;
      guint opacity;
      gint i, j;

      actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
      opacity = clutter_actor_get_paint_opacity (actor);

      /* if we don't have a target size, fall back to the actor's
       * allocation, though wrong it might be
       */
      if (clutter_offscreen_effect_get_target_rect (effect, &rect))
        {
          width = clutter_rect_get_width (&rect);
          height = clutter_rect_get_height (&rect);
        }
      else
        clutter_actor_get_size (actor, &width, &height);

      /* XXX ideally, the sub-classes should tell us what they
       * changed in the texture vertices; we then would be able to
       * avoid resubmitting the same data, if it did not change. for
       * the time being, we resubmit everything
       */
      verts = cogl_buffer_map (COGL_BUFFER (priv->buffer),
                               COGL_BUFFER_ACCESS_WRITE,
                               COGL_BUFFER_MAP_HINT_DISCARD);

      /* If the map failed then we'll resort to allocating a temporary
         buffer */
      if (verts == NULL)
        {
          mapped_buffer = FALSE;
          verts = g_malloc (sizeof (*verts) * priv->n_vertices);
        }
      else
        mapped_buffer = TRUE;

      for (i = 0; i < priv->y_tiles + 1; i++)
        {
          for (j = 0; j < priv->x_tiles + 1; j++)
            {
              CoglVertexP3T2C4 *vertex_out;
              CoglTextureVertex vertex;

              /* CoglTextureVertex isn't an ideal structure to use for
                 this because it contains a CoglColor. The internal
                 layout of CoglColor is mean to be private so Clutter
                 can not pass a pointer to it as a vertex
                 attribute. Also it contains padding so we end up
                 storing more data in the vertex buffer than we need
                 to. Instead we let the application modify a dummy
                 vertex and then copy the details back out to a more
                 well-defined struct */

              vertex.tx = (float) j / priv->x_tiles;
              vertex.ty = (float) i / priv->y_tiles;

              vertex.x = width * vertex.tx;
              vertex.y = height * vertex.ty;
              vertex.z = 0.0f;

              cogl_color_init_from_4ub (&vertex.color, 255, 255, 255, opacity);

              clutter_deform_effect_deform_vertex (self,
                                                   width, height,
                                                   &vertex);

              vertex_out = verts + i * (priv->x_tiles + 1) + j;

              vertex_out->x = vertex.x;
              vertex_out->y = vertex.y;
              vertex_out->z = vertex.z;
              vertex_out->s = vertex.tx;
              vertex_out->t = vertex.ty;
              vertex_out->r = cogl_color_get_red_byte (&vertex.color);
              vertex_out->g = cogl_color_get_green_byte (&vertex.color);
              vertex_out->b = cogl_color_get_blue_byte (&vertex.color);
              vertex_out->a = cogl_color_get_alpha_byte (&vertex.color);
            }
        }

      if (mapped_buffer)
        cogl_buffer_unmap (COGL_BUFFER (priv->buffer));
      else
        {
          cogl_buffer_set_data (COGL_BUFFER (priv->buffer),
                                0, /* offset */
                                verts,
                                sizeof (*verts) * priv->n_vertices);
          g_free (verts);
        }

      priv->is_dirty = FALSE;
    }

  material = clutter_offscreen_effect_get_target (effect);
  pipeline = COGL_PIPELINE (material);

  /* enable depth testing */
  cogl_depth_state_init (&depth_state);
  cogl_depth_state_set_test_enabled (&depth_state, TRUE);
  cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL);

  /* enable backface culling if we have a back material */
  if (priv->back_pipeline != NULL)
    cogl_pipeline_set_cull_face_mode (pipeline,
                                      COGL_PIPELINE_CULL_FACE_MODE_BACK);

  /* draw the front */
  if (material != NULL)
    cogl_framebuffer_draw_primitive (fb, pipeline, priv->primitive);

  /* draw the back */
  if (priv->back_pipeline != NULL)
    {
      CoglPipeline *back_pipeline;

      /* We probably shouldn't be modifying the user's material so
         instead we make a temporary copy */
      back_pipeline = cogl_pipeline_copy (priv->back_pipeline);
      cogl_pipeline_set_depth_state (back_pipeline, &depth_state, NULL);
      cogl_pipeline_set_cull_face_mode (back_pipeline,
                                        COGL_PIPELINE_CULL_FACE_MODE_FRONT);

      cogl_framebuffer_draw_primitive (fb, back_pipeline, priv->primitive);

      cogl_object_unref (back_pipeline);
    }

  if (G_UNLIKELY (priv->lines_primitive != NULL))
    {
      CoglContext *ctx =
        clutter_backend_get_cogl_context (clutter_get_default_backend ());
      CoglPipeline *lines_pipeline = cogl_pipeline_new (ctx);
      cogl_pipeline_set_color4f (lines_pipeline, 1.0, 0, 0, 1.0);
      cogl_framebuffer_draw_primitive (fb, lines_pipeline,
                                       priv->lines_primitive);
      cogl_object_unref (lines_pipeline);
    }
}