Example #1
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);
}
Example #2
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);
}
Example #3
0
static CoglBool
_cogl_rectangles_validate_layer_cb (CoglPipeline *pipeline,
                                    int layer_index,
                                    void *user_data)
{
  ValidateLayerState *state = user_data;
  CoglTexture *texture;

  state->i++;

  /* We need to ensure the mipmaps are ready before deciding
   * anything else about the texture because the texture storage
   * could completely change if it needs to be migrated out of the
   * atlas and will affect how we validate the layer.
   *
   * FIXME: this needs to be generalized. There could be any
   * number of things that might require a shuffling of the
   * underlying texture storage. We could add two mechanisms to
   * generalize this a bit...
   *
   * 1) add a _cogl_pipeline_layer_update_storage() function that
   * would for instance consider if mipmapping is necessary and
   * potentially migrate the texture from an atlas.
   *
   * 2) allow setting of transient primitive-flags on a pipeline
   * that may affect the outcome of _update_storage(). One flag
   * could indicate that we expect to sample beyond the bounds of
   * the texture border.
   *
   *   flags = COGL_PIPELINE_PRIMITIVE_FLAG_VALID_BORDERS;
   *   _cogl_pipeline_layer_assert_primitive_flags (layer, flags)
   *   _cogl_pipeline_layer_update_storage (layer)
   *   enqueue primitive in journal
   *
   *   when the primitive is dequeued and drawn we should:
   *   _cogl_pipeline_flush_gl_state (pipeline)
   *   draw primitive
   *   _cogl_pipeline_unassert_primitive_flags (layer, flags);
   *
   * _cogl_pipeline_layer_update_storage should take into
   * consideration all the asserted primitive requirements.  (E.g.
   * there could be multiple primitives in the journal - or in a
   * renderlist in the future - that need mipmaps or that need
   * valid contents beyond their borders (for cogl_polygon)
   * meaning they can't work with textures in an atas, so
   * _cogl_pipeline_layer_update_storage would pass on these
   * requirements to the texture atlas backend which would make
   * sure the referenced texture is migrated out of the atlas and
   * mipmaps are generated.)
   */
  _cogl_pipeline_pre_paint_for_layer (pipeline, layer_index);

  texture = cogl_pipeline_get_layer_texture (pipeline, layer_index);

  /* NULL textures are handled by
   * _cogl_pipeline_flush_gl_state */
  if (texture == NULL)
    return TRUE;

  if (state->i == 0)
    state->first_layer = layer_index;

  /* XXX:
   * For now, if the first layer is sliced then all other layers are
   * ignored since we currently don't support multi-texturing with
   * sliced textures. If the first layer is not sliced then any other
   * layers found to be sliced will be skipped. (with a warning)
   *
   * TODO: Add support for multi-texturing rectangles with sliced
   * textures if no texture matrices are in use.
   */
  if (cogl_texture_is_sliced (texture))
    {
      if (state->i == 0)
        {
          if (cogl_pipeline_get_n_layers (pipeline) > 1)
            {
              static CoglBool warning_seen = FALSE;

              if (!state->override_source)
                state->override_source = cogl_pipeline_copy (pipeline);
              _cogl_pipeline_prune_to_n_layers (state->override_source, 1);

              if (!warning_seen)
                g_warning ("Skipping layers 1..n of your pipeline since "
                           "the first layer is sliced. We don't currently "
                           "support any multi-texturing with sliced "
                           "textures but assume layer 0 is the most "
                           "important to keep");
              warning_seen = TRUE;
            }

          state->all_use_sliced_quad_fallback = TRUE;

          return FALSE;
        }
      else
        {
          static CoglBool warning_seen = FALSE;
          CoglTexture2D *tex_2d;

          if (!warning_seen)
            g_warning ("Skipping layer %d of your pipeline consisting of "
                       "a sliced texture (unsuported for multi texturing)",
                       state->i);
          warning_seen = TRUE;

          /* Note: currently only 2D textures can be sliced. */
          tex_2d = state->ctx->default_gl_texture_2d_tex;
          cogl_pipeline_set_layer_texture (pipeline, layer_index,
                                           COGL_TEXTURE (tex_2d));
          return TRUE;
        }
    }

#ifdef COGL_ENABLE_DEBUG
  /* If the texture can't be repeated with the GPU (e.g. because it has
   * waste or if using GL_TEXTURE_RECTANGLE_ARB) then if a texture matrix
   * is also in use we don't know if the result will end up trying
   * to texture from the waste area.
   *
   * Note: we check can_hardware_repeat() first since it's cheaper.
   *
   * Note: cases where the texture coordinates will require repeating
   * will be caught by later validation.
   */
  if (!_cogl_texture_can_hardware_repeat (texture) &&
      _cogl_pipeline_layer_has_user_matrix (pipeline, layer_index))
    {
      static CoglBool warning_seen = FALSE;
      if (!warning_seen)
        g_warning ("layer %d of your pipeline uses a custom "
                   "texture matrix but because the texture doesn't "
                   "support hardware repeating you may see artefacts "
                   "due to sampling beyond the texture's bounds.",
                   state->i);
      warning_seen = TRUE;
    }
#endif

  return TRUE;
}