Пример #1
0
static void
add_material_color_prop (ClutterActor *table,
                         const char *name,
                         CoglHandle material,
                         MaterialColorSetFunc set_func,
                         MaterialColorGetFunc get_func)
{
  ColorProp *prop = g_slice_new (ColorProp);
  ClutterColor value;
  CoglColor cogl_color;

  prop->prop_name = NULL;
  prop->material = cogl_handle_ref (material);
  prop->object = NULL;
  prop->set_func = set_func;
  prop->get_func = get_func;

  get_func (material, &cogl_color);
  value.red = cogl_color_get_red_byte (&cogl_color);
  value.green = cogl_color_get_green_byte (&cogl_color);
  value.blue = cogl_color_get_blue_byte (&cogl_color);
  value.alpha = cogl_color_get_alpha_byte (&cogl_color);

  add_color_prop_base (table, name, prop, &value);
}
Пример #2
0
void
_cogl_pango_display_list_render (CoglFramebuffer *fb,
                                 CoglPangoDisplayList *dl,
                                 const CoglColor *color)
{
  GSList *l;

  for (l = dl->nodes; l; l = l->next)
    {
      CoglPangoDisplayListNode *node = l->data;
      CoglColor draw_color;

      if (node->pipeline == NULL)
        {
          if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE)
            node->pipeline =
              _cogl_pango_pipeline_cache_get (dl->pipeline_cache,
                                              node->d.texture.texture);
          else
            node->pipeline =
              _cogl_pango_pipeline_cache_get (dl->pipeline_cache,
                                              NULL);
        }

      if (node->color_override)
        /* Use the override color but preserve the alpha from the
           draw color */
        cogl_color_init_from_4ub (&draw_color,
                                  cogl_color_get_red_byte (&node->color),
                                  cogl_color_get_green_byte (&node->color),
                                  cogl_color_get_blue_byte (&node->color),
                                  cogl_color_get_alpha_byte (color));
      else
        draw_color = *color;
      cogl_color_premultiply (&draw_color);

      cogl_pipeline_set_color (node->pipeline, &draw_color);

      switch (node->type)
        {
        case COGL_PANGO_DISPLAY_LIST_TEXTURE:
          _cogl_framebuffer_draw_display_list_texture (fb, node->pipeline, node);
          break;

        case COGL_PANGO_DISPLAY_LIST_RECTANGLE:
          cogl_framebuffer_draw_rectangle (fb,
                                           node->pipeline,
                                           node->d.rectangle.x_1,
                                           node->d.rectangle.y_1,
                                           node->d.rectangle.x_2,
                                           node->d.rectangle.y_2);
          break;

        case COGL_PANGO_DISPLAY_LIST_TRAPEZOID:
          cogl_primitive_draw (node->d.trapezoid.primitive,
                               fb, node->pipeline);
          break;
        }
    }
}
Пример #3
0
void
cogl_set_source_color (const CoglColor *color)
{
  CoglPipeline *pipeline;

  _COGL_GET_CONTEXT (ctx, NO_RETVAL);

  if (cogl_color_get_alpha_byte (color) == 0xff)
    {
      cogl_pipeline_set_color (ctx->opaque_color_pipeline, color);
      pipeline = ctx->opaque_color_pipeline;
    }
  else
    {
      CoglColor premultiplied = *color;
      cogl_color_premultiply (&premultiplied);
      cogl_pipeline_set_color (ctx->blended_color_pipeline, &premultiplied);
      pipeline = ctx->blended_color_pipeline;
    }

  cogl_set_source (pipeline);
}
Пример #4
0
/**
 * meta_create_color_texture_4ub:
 * @red:
 * @green:
 * @blue:
 * @alpha:
 * @flags: Optional flags for the texture, or %COGL_TEXTURE_NONE;
 *   %COGL_TEXTURE_NO_SLICING is useful if the texture will be
 *   repeated to create a constant color fill, since hardware
 *   repeat can't be used for a sliced texture.
 *
 * Creates a texture that is a single pixel with the specified
 * unpremultiplied color components.
 *
 * Return value: (transfer full): a newly created Cogl texture
 */
CoglHandle
meta_create_color_texture_4ub (guint8           red,
                               guint8           green,
                               guint8           blue,
                               guint8           alpha,
                               CoglTextureFlags flags)
{
  CoglColor color;
  guint8 pixel[4];

  cogl_color_set_from_4ub (&color, red, green, blue, alpha);
  cogl_color_premultiply (&color);

  pixel[0] = cogl_color_get_red_byte (&color);
  pixel[1] = cogl_color_get_green_byte (&color);
  pixel[2] = cogl_color_get_blue_byte (&color);
  pixel[3] = cogl_color_get_alpha_byte (&color);

  return cogl_texture_new_from_data (1, 1,
                                     flags,
                                     COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                                     COGL_PIXEL_FORMAT_ANY,
                                     4, pixel);
}
Пример #5
0
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);
    }
}
Пример #6
0
void
_cogl_pango_display_list_render (CoglPangoDisplayList *dl,
                                 const CoglColor *color)
{
  GSList *l;

  for (l = dl->nodes; l; l = l->next)
    {
      CoglPangoDisplayListNode *node = l->data;
      CoglColor draw_color;

      if (node->pipeline == NULL)
        {
          if (node->type == COGL_PANGO_DISPLAY_LIST_TEXTURE)
            node->pipeline =
              _cogl_pango_pipeline_cache_get (dl->pipeline_cache,
                                              node->d.texture.texture);
          else
            node->pipeline =
              _cogl_pango_pipeline_cache_get (dl->pipeline_cache,
                                              NULL);
        }

      if (node->color_override)
        /* Use the override color but preserve the alpha from the
           draw color */
        cogl_color_init_from_4ub (&draw_color,
                                  cogl_color_get_red_byte (&node->color),
                                  cogl_color_get_green_byte (&node->color),
                                  cogl_color_get_blue_byte (&node->color),
                                  cogl_color_get_alpha_byte (color));
      else
        draw_color = *color;
      cogl_color_premultiply (&draw_color);

      cogl_pipeline_set_color (node->pipeline, &draw_color);
      cogl_push_source (node->pipeline);

      switch (node->type)
        {
        case COGL_PANGO_DISPLAY_LIST_TEXTURE:
          _cogl_pango_display_list_render_texture (node);
          break;

        case COGL_PANGO_DISPLAY_LIST_RECTANGLE:
          cogl_rectangle (node->d.rectangle.x_1,
                          node->d.rectangle.y_1,
                          node->d.rectangle.x_2,
                          node->d.rectangle.y_2);
          break;

        case COGL_PANGO_DISPLAY_LIST_TRAPEZOID:
          {
            float points[8];
            CoglPath *path;

            points[0] =  node->d.trapezoid.x_11;
            points[1] =  node->d.trapezoid.y_1;
            points[2] =  node->d.trapezoid.x_12;
            points[3] =  node->d.trapezoid.y_2;
            points[4] =  node->d.trapezoid.x_22;
            points[5] =  node->d.trapezoid.y_2;
            points[6] =  node->d.trapezoid.x_21;
            points[7] =  node->d.trapezoid.y_1;

            path = cogl_path_new ();
            cogl_path_polygon (path, points, 4);
            cogl_path_fill (path);
            cogl_object_unref (path);
          }
          break;
        }

      cogl_pop_source ();
    }
}
Пример #7
0
static CoglBool
dump_pipeline_cb (CoglNode *node, void *user_data)
{
  CoglPipeline *pipeline = COGL_PIPELINE (node);
  PrintDebugState *state = user_data;
  int pipeline_id = *state->node_id_ptr;
  PrintDebugState state_out;
  GString *changes_label;
  CoglBool changes = FALSE;
  CoglBool layers = FALSE;

  if (state->parent_id >= 0)
    g_string_append_printf (state->graph, "%*spipeline%d -> pipeline%d;\n",
                            state->indent, "",
                            state->parent_id,
                            pipeline_id);

  g_string_append_printf (state->graph,
                          "%*spipeline%d [label=\"pipeline=0x%p\\n"
                          "ref count=%d\\n"
                          "breadcrumb=\\\"%s\\\"\" color=\"red\"];\n",
                          state->indent, "",
                          pipeline_id,
                          pipeline,
                          COGL_OBJECT (pipeline)->ref_count,
                          pipeline->has_static_breadcrumb ?
#ifdef COGL_DEBUG_ENABLED
                          pipeline->static_breadcrumb : "NULL"
#else
                          "NULL"
#endif
                          );

  changes_label = g_string_new ("");
  g_string_append_printf (changes_label,
                          "%*spipeline%d -> pipeline_state%d [weight=100];\n"
                          "%*spipeline_state%d [shape=box label=\"",
                          state->indent, "",
                          pipeline_id,
                          pipeline_id,
                          state->indent, "",
                          pipeline_id);


  if (pipeline->differences & COGL_PIPELINE_STATE_COLOR)
    {
      changes = TRUE;
      g_string_append_printf (changes_label,
                              "\\lcolor=0x%02X%02X%02X%02X\\n",
                              cogl_color_get_red_byte (&pipeline->color),
                              cogl_color_get_green_byte (&pipeline->color),
                              cogl_color_get_blue_byte (&pipeline->color),
                              cogl_color_get_alpha_byte (&pipeline->color));
    }

  if (pipeline->differences & COGL_PIPELINE_STATE_BLEND)
    {
      const char *blend_enable_name;

      changes = TRUE;

      switch (pipeline->blend_enable)
        {
        case COGL_PIPELINE_BLEND_ENABLE_AUTOMATIC:
          blend_enable_name = "AUTO";
          break;
        case COGL_PIPELINE_BLEND_ENABLE_ENABLED:
          blend_enable_name = "ENABLED";
          break;
        case COGL_PIPELINE_BLEND_ENABLE_DISABLED:
          blend_enable_name = "DISABLED";
          break;
        default:
          blend_enable_name = "UNKNOWN";
        }
      g_string_append_printf (changes_label,
                              "\\lblend=%s\\n",
                              blend_enable_name);
    }

  if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS)
    {
      changes = TRUE;
      layers = TRUE;
      g_string_append_printf (changes_label, "\\ln_layers=%d\\n",
                              pipeline->n_layers);
    }

  if (changes)
    {
      g_string_append_printf (changes_label, "\"];\n");
      g_string_append (state->graph, changes_label->str);
      g_string_free (changes_label, TRUE);
    }

  if (layers)
    {
      g_list_foreach (pipeline->layer_differences,
                      (GFunc)dump_layer_ref_cb,
                      state);
    }

  state_out.parent_id = pipeline_id;

  state_out.node_id_ptr = state->node_id_ptr;
  (*state_out.node_id_ptr)++;

  state_out.graph = state->graph;
  state_out.indent = state->indent + 2;

  _cogl_pipeline_node_foreach_child (COGL_NODE (pipeline),
                                     dump_pipeline_cb,
                                     &state_out);

  return TRUE;
}
Пример #8
0
void
cogl_polygon (const CoglTextureVertex *vertices,
              unsigned int n_vertices,
	      CoglBool use_color)
{
  CoglPipeline *pipeline;
  ValidateState validate_state;
  int n_layers;
  int n_attributes;
  CoglAttribute **attributes;
  int i;
  unsigned int stride;
  size_t stride_bytes;
  CoglAttributeBuffer *attribute_buffer;
  float *v;

  _COGL_GET_CONTEXT (ctx, NO_RETVAL);

  pipeline = cogl_get_source ();

  validate_state.original_pipeline = pipeline;
  validate_state.pipeline = pipeline;
  cogl_pipeline_foreach_layer (pipeline,
                               _cogl_polygon_validate_layer_cb,
                               &validate_state);
  pipeline = validate_state.pipeline;

  n_layers = cogl_pipeline_get_n_layers (pipeline);

  n_attributes = 1 + n_layers + (use_color ? 1 : 0);
  attributes = g_alloca (sizeof (CoglAttribute *) * n_attributes);

  /* Our data is arranged like:
   * [X, Y, Z, TX0, TY0, TX1, TY1..., R, G, B, A,...] */
  stride = 3 + (2 * n_layers) + (use_color ? 1 : 0);
  stride_bytes = stride * sizeof (float);

  /* Make sure there is enough space in the global vertex array. This
   * is used so we can render the polygon with a single call to OpenGL
   * but still support any number of vertices */
  g_array_set_size (ctx->polygon_vertices, n_vertices * stride);

  attribute_buffer =
    cogl_attribute_buffer_new (ctx, n_vertices * stride_bytes, NULL);

  attributes[0] = cogl_attribute_new (attribute_buffer,
                                      "cogl_position_in",
                                      stride_bytes,
                                      0,
                                      3,
                                      COGL_ATTRIBUTE_TYPE_FLOAT);

  for (i = 0; i < n_layers; i++)
    {
      static const char *names[] = {
          "cogl_tex_coord0_in",
          "cogl_tex_coord1_in",
          "cogl_tex_coord2_in",
          "cogl_tex_coord3_in",
          "cogl_tex_coord4_in",
          "cogl_tex_coord5_in",
          "cogl_tex_coord6_in",
          "cogl_tex_coord7_in"
      };
      char *allocated_name = NULL;
      const char *name;

      if (i < 8)
        name = names[i];
      else
        name = allocated_name = g_strdup_printf ("cogl_tex_coord%d_in", i);

      attributes[i + 1] = cogl_attribute_new (attribute_buffer,
                                              name,
                                              stride_bytes,
                                              /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
                                              12 + 8 * i,
                                              2,
                                              COGL_ATTRIBUTE_TYPE_FLOAT);

      g_free (allocated_name);
    }

  if (use_color)
    {
      attributes[n_attributes - 1] =
        cogl_attribute_new (attribute_buffer,
                            "cogl_color_in",
                            stride_bytes,
                            /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
                            12 + 8 * n_layers,
                            4,
                            COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE);
    }

  /* Convert the vertices into an array of float vertex attributes */
  v = (float *)ctx->polygon_vertices->data;
  for (i = 0; i < n_vertices; i++)
    {
      AppendTexCoordsState append_tex_coords_state;
      uint8_t *c;

      /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
      v[0] = vertices[i].x;
      v[1] = vertices[i].y;
      v[2] = vertices[i].z;

      append_tex_coords_state.vertices_in = vertices;
      append_tex_coords_state.vertex = i;
      append_tex_coords_state.layer = 0;
      append_tex_coords_state.vertices_out = v;
      cogl_pipeline_foreach_layer (pipeline,
                                   append_tex_coord_attributes_cb,
                                   &append_tex_coords_state);

      if (use_color)
        {
          /* NB: [X,Y,Z,TX,TY...,R,G,B,A,...] */
          c = (uint8_t *) (v + 3 + 2 * n_layers);
          c[0] = cogl_color_get_red_byte (&vertices[i].color);
          c[1] = cogl_color_get_green_byte (&vertices[i].color);
          c[2] = cogl_color_get_blue_byte (&vertices[i].color);
          c[3] = cogl_color_get_alpha_byte (&vertices[i].color);
        }

      v += stride;
    }

  v = (float *)ctx->polygon_vertices->data;
  cogl_buffer_set_data (COGL_BUFFER (attribute_buffer),
                        0,
                        v,
                        ctx->polygon_vertices->len * sizeof (float));

  /* XXX: although this may seem redundant, we need to do this since
   * cogl_polygon() can be used with legacy state and its the source stack
   * which track whether legacy state is enabled.
   *
   * (We only have a CoglDrawFlag to disable legacy state not one
   *  to enable it) */
  cogl_push_source (pipeline);

  _cogl_framebuffer_draw_attributes (cogl_get_draw_framebuffer (),
                                     pipeline,
                                     COGL_VERTICES_MODE_TRIANGLE_FAN,
                                     0, n_vertices,
                                     attributes,
                                     n_attributes,
                                     0 /* no draw flags */);

  cogl_pop_source ();

  if (pipeline != validate_state.original_pipeline)
    cogl_object_unref (pipeline);

  cogl_object_unref (attribute_buffer);

  for (i = 0; i < n_attributes; i++)
    cogl_object_unref (attributes[i]);
}