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); } }
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; }