static void
emit_vertex_buffer_geometry (CoglPangoDisplayListNode *node)
{
  _COGL_GET_CONTEXT (ctx, NO_RETVAL);

  /* It's expensive to go through the Cogl journal for large runs
   * of text in part because the journal transforms the quads in software
   * to avoid changing the modelview matrix. So for larger runs of text
   * we load the vertices into a VBO, and this has the added advantage
   * that if the text doesn't change from frame to frame the VBO can
   * be re-used avoiding the repeated cost of validating the data and
   * mapping it into the GPU... */

  if (node->d.texture.vertex_buffer == COGL_INVALID_HANDLE)
    {
      CoglHandle vb = cogl_vertex_buffer_new (node->d.texture.verts->len);

      cogl_vertex_buffer_add (vb, "gl_Vertex", 2,
                              COGL_ATTRIBUTE_TYPE_FLOAT, FALSE,
                              sizeof (CoglPangoDisplayListVertex),
                              &g_array_index (node->d.texture.verts,
                                              CoglPangoDisplayListVertex, 0).x);
      cogl_vertex_buffer_add (vb, "gl_MultiTexCoord0", 2,
                              COGL_ATTRIBUTE_TYPE_FLOAT, FALSE,
                              sizeof (CoglPangoDisplayListVertex),
                              &g_array_index (node->d.texture.verts,
                                              CoglPangoDisplayListVertex,
                                              0).t_x);
      cogl_vertex_buffer_submit (vb);

      node->d.texture.vertex_buffer = vb;
    }

#ifdef CLUTTER_COGL_HAS_GL
  if (ctx->driver == COGL_DRIVER_GL)
    cogl_vertex_buffer_draw (node->d.texture.vertex_buffer,
                             GL_QUADS,
                             0, node->d.texture.verts->len);
  else
#endif
    {
      /* GLES doesn't support GL_QUADS so instead we use a VBO with
         indexed vertices to generate GL_TRIANGLES from the quads */

      int n_indices = node->d.texture.verts->len / 4 * 6;
      CoglHandle indices_vbo
        = cogl_vertex_buffer_indices_get_for_quads (n_indices);

      cogl_vertex_buffer_draw_elements (node->d.texture.vertex_buffer,
                                        COGL_VERTICES_MODE_TRIANGLES,
                                        indices_vbo,
                                        0, node->d.texture.verts->len - 1,
                                        0, n_indices);
    }
}
Exemple #2
0
static void
mx_fade_effect_update_vbo (MxFadeEffect *self)
{
  guint n_quads;
  gint bu, br, bb, bl;
  gfloat x1, y1, x2, y2;
  CoglColor opaque, color;
  CoglTextureVertex verts[9*4];

  MxFadeEffectPrivate *priv = self->priv;

  cogl_color_init_from_4ub (&opaque, 0xff, 0xff, 0xff, 0xff);
  cogl_color_init_from_4ub (&color,
                            priv->color.red,
                            priv->color.green,
                            priv->color.blue,
                            priv->color.alpha);

  /* Validate the bounds */
  x1 = priv->x;
  y1 = priv->y;
  x2 = x1 + (priv->bounds_width ? priv->bounds_width : priv->width);
  y2 = y1 + (priv->bounds_height ? priv->bounds_height : priv->height);

  if (x1 < 0)
    x1 = 0;
  if (x2 > priv->width)
    x2 = priv->width;
  if (y1 < 0)
    y1 = 0;
  if (y2 > priv->height)
    y2 = priv->height;

  /* Validate the border sizes */
  /* Note,
   *   bu = Border-up
   *   br = Border-right
   *   bb = Border-bottom
   *   bl = Border-left
   */
  bu = priv->border[0];
  br = priv->border[1];
  bb = priv->border[2];
  bl = priv->border[3];

  if (y1 + bu >= y2)
    bu = y2 - y1 - 1;
  if (x1 + bl >= x2)
    bl = x2 - x1 - 1;
  if (x2 - br <= x1 + bl)
    br = x2 - (x1 + bl) - 1;
  if (y2 - bb <= y1 + bu)
    bb = y2 - (y1 + bu) - 1;

  n_quads = 0;

  /* Generate the top-left square */
  if (bl && bu)
    {
      mx_fade_effect_draw_rect (&verts[n_quads*4],
                                x1, y1,
                                x1 + bl, y1 + bu,
                                priv->width, priv->height,
                                &color, &color,
                                &opaque, &color,
                                FALSE);
      n_quads ++;
    }

  /* Generate the top-middle square */
  if (bu)
    {
      mx_fade_effect_draw_rect (&verts[n_quads*4],
                                x1 + bl, y1,
                                x2 - br, y1 + bu,
                                priv->width, priv->height,
                                &color, &color,
                                &opaque, &opaque,
                                FALSE);
      n_quads ++;
    }

  /* Generate the top-right square */
  if (br && bu)
    {
      mx_fade_effect_draw_rect (&verts[n_quads*4],
                                x2 - br, y1,
                                x2, y1 + bu,
                                priv->width, priv->height,
                                &color, &color,
                                &color, &opaque,
                                TRUE);
      n_quads ++;
    }

  /* Generate the left square */
  if (bl)
    {
      mx_fade_effect_draw_rect (&verts[n_quads*4],
                                x1, y1 + bu,
                                x1 + bl, y2 - bb,
                                priv->width, priv->height,
                                &color, &opaque,
                                &opaque, &color,
                                TRUE);
      n_quads ++;
    }

  /* Generate the middle square */
  mx_fade_effect_draw_rect (&verts[n_quads*4],
                            x1 + bl, y1 + bu,
                            x2 - br, y2 - bb,
                            priv->width, priv->height,
                            &opaque, &opaque,
                            &opaque, &opaque,
                            TRUE);
  n_quads ++;

  /* Generate the right square */
  if (br)
    {
      mx_fade_effect_draw_rect (&verts[n_quads*4],
                                x2 - br, y1 + bu,
                                x2, y2 - bb,
                                priv->width, priv->height,
                                &opaque, &color,
                                &color, &opaque,
                                TRUE);
      n_quads ++;
    }

  /* Generate the bottom-left square */
  if (bb && bl)
    {
      mx_fade_effect_draw_rect (&verts[n_quads*4],
                                x1, y2 - bb,
                                x1 + bl, y2,
                                priv->width, priv->height,
                                &color, &opaque,
                                &color, &color,
                                TRUE);
      n_quads ++;
    }

  /* Generate the bottom-middle square */
  if (bb)
    {
      mx_fade_effect_draw_rect (&verts[n_quads*4],
                                x1 + bl, y2 - bb,
                                x2 - br, y2,
                                priv->width, priv->height,
                                &opaque, &opaque,
                                &color, &color,
                                FALSE);
      n_quads ++;
    }

  /* Generate the bottom-right square */
  if (bb && br)
    {
      mx_fade_effect_draw_rect (&verts[n_quads*4],
                                x2 - br, y2 - bb,
                                x2, y2,
                                priv->width, priv->height,
                                &opaque, &color,
                                &color, &color,
                                FALSE);
      n_quads ++;
    }

  /* Unref the old vbo if it's a different size - otherwise we reuse it */
  if (priv->vbo && (n_quads != priv->n_quads))
    {
      cogl_handle_unref (priv->vbo);
      priv->vbo = NULL;
    }

  priv->n_quads = n_quads;

  if (!priv->vbo)
    {
      priv->vbo = cogl_vertex_buffer_new (n_quads * 4);
      if (!priv->vbo)
        return;

      priv->indices = cogl_vertex_buffer_indices_get_for_quads (n_quads * 6);
      if (!priv->indices)
        return;
    }

  cogl_vertex_buffer_add (priv->vbo,
                          "gl_Vertex",
                          2,
                          COGL_ATTRIBUTE_TYPE_FLOAT,
                          FALSE,
                          sizeof (CoglTextureVertex),
                          &(verts[0].x));
  cogl_vertex_buffer_add (priv->vbo,
                          "gl_MultiTexCoord0",
                          2,
                          COGL_ATTRIBUTE_TYPE_FLOAT,
                          FALSE,
                          sizeof (CoglTextureVertex),
                          &(verts[0].tx));
  cogl_vertex_buffer_add (priv->vbo,
                          "gl_Color",
                          4,
                          COGL_ATTRIBUTE_TYPE_UNSIGNED_BYTE,
                          FALSE,
                          sizeof (CoglTextureVertex),
                          &(verts[0].color));

  cogl_vertex_buffer_submit (priv->vbo);
  priv->update_vbo = FALSE;
}