From 93ea1681bb21704a51370c0a2e7bc8f791a38d5a Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 27 Nov 2008 16:44:39 +0000 Subject: [PATCH 01/11] Use a GArray for the texture vertices in cogl_texture_polygon Previously it was a dynamic array that was manually reallocated. --- clutter/cogl/gl/cogl-context.c | 11 +++++++---- clutter/cogl/gl/cogl-context.h | 3 +-- clutter/cogl/gl/cogl-texture.c | 32 +++++++++----------------------- 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/clutter/cogl/gl/cogl-context.c b/clutter/cogl/gl/cogl-context.c index a9240a102..006506ac9 100644 --- a/clutter/cogl/gl/cogl-context.c +++ b/clutter/cogl/gl/cogl-context.c @@ -57,9 +57,9 @@ cogl_create_context () _context->path_nodes_size = 0; _context->texture_handles = NULL; - _context->texture_vertices_size = 0; - _context->texture_vertices = NULL; - + _context->texture_vertices = g_array_new (FALSE, FALSE, + sizeof (CoglTextureGLVertex)); + _context->fbo_handles = NULL; _context->draw_buffer = COGL_WINDOW_BUFFER; @@ -140,7 +140,10 @@ cogl_destroy_context () g_array_free (_context->shader_handles, TRUE); if (_context->program_handles) g_array_free (_context->program_handles, TRUE); - + + if (_context->texture_vertices) + g_array_free (_context->texture_vertices, TRUE); + g_free (_context); } diff --git a/clutter/cogl/gl/cogl-context.h b/clutter/cogl/gl/cogl-context.h index 5ab583862..f1fd2e786 100644 --- a/clutter/cogl/gl/cogl-context.h +++ b/clutter/cogl/gl/cogl-context.h @@ -64,8 +64,7 @@ typedef struct /* Textures */ GArray *texture_handles; - CoglTextureGLVertex *texture_vertices; - gulong texture_vertices_size; + GArray *texture_vertices; /* Framebuffer objects */ GArray *fbo_handles; diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c index bf2eef304..01613c4bd 100644 --- a/clutter/cogl/gl/cogl-texture.c +++ b/clutter/cogl/gl/cogl-texture.c @@ -2252,23 +2252,9 @@ cogl_texture_polygon (CoglHandle handle, /* Make sure there is enough space in the global texture vertex array. This is used so we can render the polygon with a single call to OpenGL but still support any number of vertices */ - if (ctx->texture_vertices_size < n_vertices) - { - guint nsize = ctx->texture_vertices_size; - - if (nsize == 0) - nsize = 1; - do - nsize *= 2; - while (nsize < n_vertices); - - ctx->texture_vertices_size = nsize; + g_array_set_size (ctx->texture_vertices, n_vertices); + p = (CoglTextureGLVertex *) ctx->texture_vertices->data; - ctx->texture_vertices = g_realloc (ctx->texture_vertices, - nsize - * sizeof (CoglTextureGLVertex)); - } - /* Prepare GL state */ enable_flags = (COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_VERTEX_ARRAY @@ -2282,14 +2268,12 @@ cogl_texture_polygon (CoglHandle handle, if (use_color) { enable_flags |= COGL_ENABLE_COLOR_ARRAY; - GE( glColorPointer (4, GL_UNSIGNED_BYTE, sizeof (CoglTextureGLVertex), - ctx->texture_vertices[0].c) ); + GE( glColorPointer (4, GL_UNSIGNED_BYTE, + sizeof (CoglTextureGLVertex), p->c) ); } - GE( glVertexPointer (3, GL_FLOAT, sizeof (CoglTextureGLVertex), - ctx->texture_vertices[0].v) ); - GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex), - ctx->texture_vertices[0].t) ); + GE( glVertexPointer (3, GL_FLOAT, sizeof (CoglTextureGLVertex), p->v ) ); + GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex), p->t ) ); cogl_enable (enable_flags); @@ -2320,9 +2304,11 @@ cogl_texture_polygon (CoglHandle handle, gl_handle = g_array_index (tex->slice_gl_handles, GLuint, tex_num++); + p = (CoglTextureGLVertex *) ctx->texture_vertices->data; + /* Convert the vertices into an array of GLfloats ready to pass to OpenGL */ - for (i = 0, p = ctx->texture_vertices; i < n_vertices; i++, p++) + for (i = 0; i < n_vertices; i++, p++) { #define CFX_F COGL_FIXED_TO_FLOAT From 10942e8e049a4bfdd3df5abd5036c63f5676df92 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 28 Nov 2008 12:33:19 +0000 Subject: [PATCH 02/11] Make cogl_texture_rectangle use the vertex array cogl_texture_quad_hw and _sw now just add vertices to the vertex array. The last texture used is stored and if a different texture is encountered then flushes the vertices. cogl_texture_rectangle always flushes the vertices after calling either of the functions. --- clutter/cogl/gl/cogl-context.h | 7 +- clutter/cogl/gl/cogl-texture.c | 201 ++++++++++++++++++--------------- 2 files changed, 119 insertions(+), 89 deletions(-) diff --git a/clutter/cogl/gl/cogl-context.h b/clutter/cogl/gl/cogl-context.h index f1fd2e786..ffec47464 100644 --- a/clutter/cogl/gl/cogl-context.h +++ b/clutter/cogl/gl/cogl-context.h @@ -65,7 +65,12 @@ typedef struct /* Textures */ GArray *texture_handles; GArray *texture_vertices; - + /* The gl texture number that the above vertices apply to. This to + detect when a different slice is encountered so that the vertices + can be flushed */ + GLuint texture_current; + GLenum texture_target; + /* Framebuffer objects */ GArray *fbo_handles; CoglBufferTarget draw_buffer; diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c index 01613c4bd..fe7208d81 100644 --- a/clutter/cogl/gl/cogl-texture.c +++ b/clutter/cogl/gl/cogl-texture.c @@ -1906,6 +1906,28 @@ cogl_texture_get_data (CoglHandle handle, return byte_size; } +static void +_cogl_texture_flush_vertices (void) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->texture_vertices > 0) + { + CoglTextureGLVertex *p + = (CoglTextureGLVertex *) ctx->texture_vertices->data; + + GE( glVertexPointer (2, GL_FLOAT, + sizeof (CoglTextureGLVertex), p->v ) ); + GE( glTexCoordPointer (2, GL_FLOAT, + sizeof (CoglTextureGLVertex), p->t ) ); + + GE( glBindTexture (ctx->texture_target, ctx->texture_current) ); + GE( glDrawArrays (GL_QUADS, 0, ctx->texture_vertices->len) ); + + g_array_set_size (ctx->texture_vertices, 0); + } +} + static void _cogl_texture_quad_sw (CoglTexture *tex, CoglFixed x1, @@ -1917,40 +1939,23 @@ _cogl_texture_quad_sw (CoglTexture *tex, CoglFixed tx2, CoglFixed ty2) { - CoglSpanIter iter_x , iter_y; - CoglFixed tw , th; - CoglFixed tqx , tqy; - CoglFixed first_tx , first_ty; - CoglFixed first_qx , first_qy; - CoglFixed slice_tx1 , slice_ty1; - CoglFixed slice_tx2 , slice_ty2; - CoglFixed slice_qx1 , slice_qy1; - CoglFixed slice_qx2 , slice_qy2; - GLfloat tex_coords[8]; - GLfloat quad_coords[8]; - GLuint gl_handle; - gulong enable_flags = (COGL_ENABLE_TEXTURE_2D - | COGL_ENABLE_VERTEX_ARRAY - | COGL_ENABLE_TEXCOORD_ARRAY); - + CoglSpanIter iter_x , iter_y; + CoglFixed tw , th; + CoglFixed tqx , tqy; + CoglFixed first_tx , first_ty; + CoglFixed first_qx , first_qy; + CoglFixed slice_tx1 , slice_ty1; + CoglFixed slice_tx2 , slice_ty2; + CoglFixed slice_qx1 , slice_qy1; + CoglFixed slice_qx2 , slice_qy2; + GLuint gl_handle; + CoglTextureGLVertex *p; + _COGL_GET_CONTEXT (ctx, NO_RETVAL); #if COGL_DEBUG printf("=== Drawing Tex Quad (Software Tiling Mode) ===\n"); #endif - - - /* Prepare GL state */ - if (ctx->color_alpha < 255 - || tex->bitmap.format & COGL_A_BIT) - { - enable_flags |= COGL_ENABLE_BLEND; - } - - if (ctx->enable_backface_culling) - enable_flags |= COGL_ENABLE_BACKFACE_CULLING; - - cogl_enable (enable_flags); /* If the texture coordinates are backwards then swap both the geometry and texture coordinates so that the texture will be @@ -1974,10 +1979,7 @@ _cogl_texture_quad_sw (CoglTexture *tex, ty1 = ty2; ty2 = temp; } - - GE( glTexCoordPointer (2, GL_FLOAT, 0, tex_coords) ); - GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords) ); - + /* Scale ratio from texture to quad widths */ tw = COGL_FIXED_FROM_INT (tex->bitmap.width); th = COGL_FIXED_FROM_INT (tex->bitmap.height); @@ -2069,23 +2071,35 @@ _cogl_texture_quad_sw (CoglTexture *tex, gl_handle = g_array_index (tex->slice_gl_handles, GLuint, iter_y.index * iter_x.array->len + iter_x.index); - - GE( glBindTexture (tex->gl_target, gl_handle) ); -#define CFX_F COGL_FIXED_TO_FLOAT - - /* Draw textured quad */ - tex_coords[0] = CFX_F(slice_tx1); tex_coords[1] = CFX_F(slice_ty2); - tex_coords[2] = CFX_F(slice_tx2); tex_coords[3] = CFX_F(slice_ty2); - tex_coords[4] = CFX_F(slice_tx1); tex_coords[5] = CFX_F(slice_ty1); - tex_coords[6] = CFX_F(slice_tx2); tex_coords[7] = CFX_F(slice_ty1); + /* If we're using a different texture from the one already queued + then flush the vertices */ + if (ctx->texture_vertices->len > 0 + && gl_handle != ctx->texture_current) + _cogl_texture_flush_vertices (); + ctx->texture_target = tex->gl_target; + ctx->texture_current = gl_handle; - quad_coords[0] = CFX_F(slice_qx1); quad_coords[1] = CFX_F(slice_qy2); - quad_coords[2] = CFX_F(slice_qx2); quad_coords[3] = CFX_F(slice_qy2); - quad_coords[4] = CFX_F(slice_qx1); quad_coords[5] = CFX_F(slice_qy1); - quad_coords[6] = CFX_F(slice_qx2); quad_coords[7] = CFX_F(slice_qy1); + /* Add the quad to the list of queued vertices */ + g_array_set_size (ctx->texture_vertices, + ctx->texture_vertices->len + 4); + p = &g_array_index (ctx->texture_vertices, CoglTextureGLVertex, + ctx->texture_vertices->len - 4); - GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); +#define CFX_F(x) COGL_FIXED_TO_FLOAT(x) + + p->v[0] = CFX_F (slice_qx1); p->v[1] = CFX_F (slice_qy2); + p->t[0] = CFX_F (slice_tx1); p->t[1] = CFX_F (slice_ty2); + p++; + p->v[0] = CFX_F (slice_qx2); p->v[1] = CFX_F (slice_qy2); + p->t[0] = CFX_F (slice_tx2); p->t[1] = CFX_F (slice_ty2); + p++; + p->v[0] = CFX_F (slice_qx2); p->v[1] = CFX_F (slice_qy1); + p->t[0] = CFX_F (slice_tx2); p->t[1] = CFX_F (slice_ty1); + p++; + p->v[0] = CFX_F (slice_qx1); p->v[1] = CFX_F (slice_qy1); + p->t[0] = CFX_F (slice_tx1); p->t[1] = CFX_F (slice_ty1); + p++; #undef CFX_F } @@ -2103,40 +2117,27 @@ _cogl_texture_quad_hw (CoglTexture *tex, CoglFixed tx2, CoglFixed ty2) { - GLfloat tex_coords[8]; - GLfloat quad_coords[8]; - GLuint gl_handle; - CoglTexSliceSpan *x_span; - CoglTexSliceSpan *y_span; - gulong enable_flags = (COGL_ENABLE_TEXTURE_2D - | COGL_ENABLE_VERTEX_ARRAY - | COGL_ENABLE_TEXCOORD_ARRAY); + GLuint gl_handle; + CoglTexSliceSpan *x_span; + CoglTexSliceSpan *y_span; + CoglTextureGLVertex *p; #if COGL_DEBUG printf("=== Drawing Tex Quad (Hardware Tiling Mode) ===\n"); #endif - - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - /* Prepare GL state */ - if (ctx->color_alpha < 255 - || tex->bitmap.format & COGL_A_BIT) - { - enable_flags |= COGL_ENABLE_BLEND; - } - - if (ctx->enable_backface_culling) - enable_flags |= COGL_ENABLE_BACKFACE_CULLING; - cogl_enable (enable_flags); - - GE( glTexCoordPointer (2, GL_FLOAT, 0, tex_coords) ); - GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords) ); - + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + /* Pick and bind opengl texture object */ gl_handle = g_array_index (tex->slice_gl_handles, GLuint, 0); - GE( glBindTexture (tex->gl_target, gl_handle) ); - + + /* If we're using a different texture from the one already queued + then flush the vertices */ + if (ctx->texture_vertices->len > 0 && gl_handle != ctx->texture_current) + _cogl_texture_flush_vertices (); + ctx->texture_target = tex->gl_target; + ctx->texture_current = gl_handle; + /* Don't include the waste in the texture coordinates */ x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0); y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 0); @@ -2147,20 +2148,25 @@ _cogl_texture_quad_hw (CoglTexture *tex, ty1 = ty1 * (y_span->size - y_span->waste) / y_span->size; ty2 = ty2 * (y_span->size - y_span->waste) / y_span->size; + /* Add the quad to the list of queued vertices */ + g_array_set_size (ctx->texture_vertices, ctx->texture_vertices->len + 4); + p = &g_array_index (ctx->texture_vertices, CoglTextureGLVertex, + ctx->texture_vertices->len - 4); + #define CFX_F(x) COGL_FIXED_TO_FLOAT(x) - - /* Draw textured quad */ - tex_coords[0] = CFX_F(tx1); tex_coords[1] = CFX_F(ty2); - tex_coords[2] = CFX_F(tx2); tex_coords[3] = CFX_F(ty2); - tex_coords[4] = CFX_F(tx1); tex_coords[5] = CFX_F(ty1); - tex_coords[6] = CFX_F(tx2); tex_coords[7] = CFX_F(ty1); - quad_coords[0] = CFX_F(x1); quad_coords[1] = CFX_F(y2); - quad_coords[2] = CFX_F(x2); quad_coords[3] = CFX_F(y2); - quad_coords[4] = CFX_F(x1); quad_coords[5] = CFX_F(y1); - quad_coords[6] = CFX_F(x2); quad_coords[7] = CFX_F(y1); - - GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); + p->v[0] = CFX_F (x1); p->v[1] = CFX_F (y2); + p->t[0] = CFX_F (tx1); p->t[1] = CFX_F (ty2); + p++; + p->v[0] = CFX_F (x2); p->v[1] = CFX_F (y2); + p->t[0] = CFX_F (tx2); p->t[1] = CFX_F (ty2); + p++; + p->v[0] = CFX_F (x2); p->v[1] = CFX_F (y1); + p->t[0] = CFX_F (tx2); p->t[1] = CFX_F (ty1); + p++; + p->v[0] = CFX_F (x1); p->v[1] = CFX_F (y1); + p->t[0] = CFX_F (tx1); p->t[1] = CFX_F (ty1); + p++; #undef CFX_F } @@ -2176,8 +2182,13 @@ cogl_texture_rectangle (CoglHandle handle, CoglFixed tx2, CoglFixed ty2) { - CoglTexture *tex; - + CoglTexture *tex; + gulong enable_flags = (COGL_ENABLE_TEXTURE_2D + | COGL_ENABLE_VERTEX_ARRAY + | COGL_ENABLE_TEXCOORD_ARRAY); + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + /* Check if valid texture */ if (!cogl_is_texture (handle)) return; @@ -2194,6 +2205,18 @@ cogl_texture_rectangle (CoglHandle handle, if (tx1 == tx2 || ty1 == ty2) return; + /* Prepare GL state */ + if (ctx->color_alpha < 255 + || tex->bitmap.format & COGL_A_BIT) + enable_flags |= COGL_ENABLE_BLEND; + + if (ctx->enable_backface_culling) + enable_flags |= COGL_ENABLE_BACKFACE_CULLING; + + cogl_enable (enable_flags); + + g_array_set_size (ctx->texture_vertices, 0); + /* If there is only one GL texture and either the texture is NPOT (no waste) or all of the coordinates are in the range [0,1] then we can use hardware tiling */ @@ -2206,6 +2229,8 @@ cogl_texture_rectangle (CoglHandle handle, _cogl_texture_quad_hw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2); else _cogl_texture_quad_sw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2); + + _cogl_texture_flush_vertices (); } void From b312cd2d5560de953cfc0438353f9f6d8e3cae9a Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 28 Nov 2008 12:44:21 +0000 Subject: [PATCH 03/11] Add cogl_texture_multiple_rectangles This takes an array of sets of 8 floats to describe the rectangles. It tries to send the geometry with a single glDrawArrays as far as possible. cogl_texture_rectangle is now just a wrapper around cogl_texture_multiple_rectangles. --- clutter/cogl/cogl-texture.h | 5 +++ clutter/cogl/gl/cogl-texture.c | 74 +++++++++++++++++++++++----------- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/clutter/cogl/cogl-texture.h b/clutter/cogl/cogl-texture.h index 117a12b14..5df2a818d 100644 --- a/clutter/cogl/cogl-texture.h +++ b/clutter/cogl/cogl-texture.h @@ -385,6 +385,11 @@ void cogl_texture_polygon (CoglHandle handle, CoglTextureVertex *vertices, gboolean use_color); +void cogl_texture_multiple_rectangles + (CoglHandle handle, + const CoglFixed *verts, + guint n_rects); + G_END_DECLS #endif /* __COGL_TEXTURE_H__ */ diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c index fe7208d81..cd241ff80 100644 --- a/clutter/cogl/gl/cogl-texture.c +++ b/clutter/cogl/gl/cogl-texture.c @@ -2172,15 +2172,9 @@ _cogl_texture_quad_hw (CoglTexture *tex, } void -cogl_texture_rectangle (CoglHandle handle, - CoglFixed x1, - CoglFixed y1, - CoglFixed x2, - CoglFixed y2, - CoglFixed tx1, - CoglFixed ty1, - CoglFixed tx2, - CoglFixed ty2) +cogl_texture_multiple_rectangles (CoglHandle handle, + const CoglFixed *verts, + guint n_rects) { CoglTexture *tex; gulong enable_flags = (COGL_ENABLE_TEXTURE_2D @@ -2202,9 +2196,6 @@ cogl_texture_rectangle (CoglHandle handle, if (tex->slice_gl_handles->len == 0) return; - if (tx1 == tx2 || ty1 == ty2) - return; - /* Prepare GL state */ if (ctx->color_alpha < 255 || tex->bitmap.format & COGL_A_BIT) @@ -2217,22 +2208,57 @@ cogl_texture_rectangle (CoglHandle handle, g_array_set_size (ctx->texture_vertices, 0); - /* If there is only one GL texture and either the texture is NPOT - (no waste) or all of the coordinates are in the range [0,1] then - we can use hardware tiling */ - if (tex->slice_gl_handles->len == 1 - && (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) - || (tx1 >= 0 && tx1 <= COGL_FIXED_1 - && tx2 >= 0 && tx2 <= COGL_FIXED_1 - && ty1 >= 0 && ty1 <= COGL_FIXED_1 - && ty2 >= 0 && ty2 <= COGL_FIXED_1))) - _cogl_texture_quad_hw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2); - else - _cogl_texture_quad_sw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2); + while (n_rects-- > 0) + { + if (verts[4] != verts[6] && verts[5] != verts[7]) + { + /* If there is only one GL texture and either the texture is + NPOT (no waste) or all of the coordinates are in the + range [0,1] then we can use hardware tiling */ + if (tex->slice_gl_handles->len == 1 + && (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) + || (verts[4] >= 0 && verts[4] <= COGL_FIXED_1 + && verts[6] >= 0 && verts[6] <= COGL_FIXED_1 + && verts[5] >= 0 && verts[5] <= COGL_FIXED_1 + && verts[7] >= 0 && verts[7] <= COGL_FIXED_1))) + _cogl_texture_quad_hw (tex, verts[0],verts[1], verts[2],verts[3], + verts[4],verts[5], verts[6],verts[7]); + else + _cogl_texture_quad_sw (tex, verts[0],verts[1], verts[2],verts[3], + verts[4],verts[5], verts[6],verts[7]); + } + + verts += 8; + } _cogl_texture_flush_vertices (); } +void +cogl_texture_rectangle (CoglHandle handle, + CoglFixed x1, + CoglFixed y1, + CoglFixed x2, + CoglFixed y2, + CoglFixed tx1, + CoglFixed ty1, + CoglFixed tx2, + CoglFixed ty2) +{ + CoglFixed verts[8]; + + verts[0] = x1; + verts[1] = y1; + verts[2] = x2; + verts[3] = y2; + verts[4] = tx1; + verts[5] = ty1; + verts[6] = tx2; + verts[7] = ty2; + + cogl_texture_multiple_rectangles (handle, verts, 1); +} + void cogl_texture_polygon (CoglHandle handle, guint n_vertices, From ab347481aeccd28b0986fbc991c96d72bbc3f072 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 28 Nov 2008 13:14:10 +0000 Subject: [PATCH 04/11] Use cogl_texture_multiple_rectangles in CoglPangoRenderer The glyphs are queued into an array of rectangles instead of being drawn directly. Whenever a different texture is used or the sequence is complete the array is flushed. This is based on a patch from Owen Taylor. --- clutter/pango/cogl-pango-render.c | 78 +++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 14 deletions(-) diff --git a/clutter/pango/cogl-pango-render.c b/clutter/pango/cogl-pango-render.c index bcf3b11fc..e69c412ac 100644 --- a/clutter/pango/cogl-pango-render.c +++ b/clutter/pango/cogl-pango-render.c @@ -51,6 +51,10 @@ struct _CoglPangoRenderer CoglPangoGlyphCache *mipmapped_glyph_cache; gboolean use_mipmapping; + + /* Array of rectangles to draw from the current texture */ + GArray *glyph_rectangles; + CoglHandle glyph_texture; }; struct _CoglPangoRendererClass @@ -58,6 +62,46 @@ struct _CoglPangoRendererClass PangoRendererClass class_instance; }; +static void +cogl_pango_renderer_glyphs_end (CoglPangoRenderer *priv) +{ + if (priv->glyph_rectangles->len > 0) + { + CoglFixed *rectangles = (CoglFixed *) priv->glyph_rectangles->data; + cogl_texture_multiple_rectangles (priv->glyph_texture, rectangles, + priv->glyph_rectangles->len / 8); + g_array_set_size (priv->glyph_rectangles, 0); + } +} + +static void +cogl_pango_renderer_draw_glyph (CoglPangoRenderer *priv, + CoglPangoGlyphCacheValue *cache_value, + CoglFixed x1, + CoglFixed y1) +{ + CoglFixed x2, y2; + CoglFixed *p; + + if (priv->glyph_rectangles->len > 0 + && priv->glyph_texture != cache_value->texture) + cogl_pango_renderer_glyphs_end (priv); + + priv->glyph_texture = cache_value->texture; + + x2 = x1 + CLUTTER_INT_TO_FIXED (cache_value->draw_width); + y2 = y1 + CLUTTER_INT_TO_FIXED (cache_value->draw_height); + + g_array_set_size (priv->glyph_rectangles, priv->glyph_rectangles->len + 8); + p = &g_array_index (priv->glyph_rectangles, CoglFixed, + priv->glyph_rectangles->len - 8); + + *(p++) = x1; *(p++) = y1; + *(p++) = x2; *(p++) = y2; + *(p++) = cache_value->tx1; *(p++) = cache_value->ty1; + *(p++) = cache_value->tx2; *(p++) = cache_value->ty2; +} + #define COGL_PANGO_UNIT_TO_FIXED(x) ((x) << (COGL_FIXED_Q - 10)) static void cogl_pango_renderer_finalize (GObject *object); @@ -89,6 +133,7 @@ cogl_pango_renderer_init (CoglPangoRenderer *priv) priv->glyph_cache = cogl_pango_glyph_cache_new (FALSE); priv->mipmapped_glyph_cache = cogl_pango_glyph_cache_new (TRUE); priv->use_mipmapping = FALSE; + priv->glyph_rectangles = g_array_new (FALSE, FALSE, sizeof (CoglFixed)); } static void @@ -111,6 +156,7 @@ cogl_pango_renderer_finalize (GObject *object) cogl_pango_glyph_cache_free (priv->mipmapped_glyph_cache); cogl_pango_glyph_cache_free (priv->glyph_cache); + g_array_free (priv->glyph_rectangles, TRUE); G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object); } @@ -376,10 +422,10 @@ cogl_pango_renderer_draw_box (int x, int y, static void cogl_pango_renderer_get_device_units (PangoRenderer *renderer, - int xin, - int yin, - CoglFixed *xout, - CoglFixed *yout) + int xin, + int yin, + CoglFixed *xout, + CoglFixed *yout) { const PangoMatrix *matrix; @@ -454,6 +500,7 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer, int xi, int yi) { + CoglPangoRenderer *priv = (CoglPangoRenderer *) renderer; CoglPangoGlyphCacheValue *cache_value; int i; @@ -474,6 +521,8 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer, { PangoFontMetrics *metrics; + cogl_pango_renderer_glyphs_end (priv); + if (font == NULL || (metrics = pango_font_get_metrics (font, NULL)) == NULL) { @@ -503,10 +552,14 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer, gi->glyph); if (cache_value == NULL) - cogl_pango_renderer_draw_box (COGL_FIXED_TO_INT (x), - COGL_FIXED_TO_INT (y), - PANGO_UNKNOWN_GLYPH_WIDTH, - PANGO_UNKNOWN_GLYPH_HEIGHT); + { + cogl_pango_renderer_glyphs_end (priv); + + cogl_pango_renderer_draw_box (COGL_FIXED_TO_INT (x), + COGL_FIXED_TO_INT (y), + PANGO_UNKNOWN_GLYPH_WIDTH, + PANGO_UNKNOWN_GLYPH_HEIGHT); + } else { CoglFixed width, height; @@ -517,15 +570,12 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer, width = x + COGL_FIXED_FROM_INT (cache_value->draw_width); height = y + COGL_FIXED_FROM_INT (cache_value->draw_height); - /* Render the glyph from the texture */ - cogl_texture_rectangle (cache_value->texture, - x, y, - width, height, - cache_value->tx1, cache_value->ty1, - cache_value->tx2, cache_value->ty2); + cogl_pango_renderer_draw_glyph (priv, cache_value, x, y); } } xi += gi->geometry.width; } + + cogl_pango_renderer_glyphs_end (priv); } From 29505dd0ba651df08dcfb184f0b08efa5b4eddfe Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 28 Nov 2008 14:20:07 +0000 Subject: [PATCH 05/11] Use GL_TRIANGLES for the texture vertex array Most cards don't actually support GL_QUADS and they are deprecated in GL 3.0 so there is a chance it will perform faster with GL_TRIANGLES even though it has to submit two extra vertices. --- clutter/cogl/gl/cogl-texture.c | 36 +++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c index cd241ff80..6031305e1 100644 --- a/clutter/cogl/gl/cogl-texture.c +++ b/clutter/cogl/gl/cogl-texture.c @@ -1922,7 +1922,7 @@ _cogl_texture_flush_vertices (void) sizeof (CoglTextureGLVertex), p->t ) ); GE( glBindTexture (ctx->texture_target, ctx->texture_current) ); - GE( glDrawArrays (GL_QUADS, 0, ctx->texture_vertices->len) ); + GE( glDrawArrays (GL_TRIANGLES, 0, ctx->texture_vertices->len) ); g_array_set_size (ctx->texture_vertices, 0); } @@ -2082,9 +2082,9 @@ _cogl_texture_quad_sw (CoglTexture *tex, /* Add the quad to the list of queued vertices */ g_array_set_size (ctx->texture_vertices, - ctx->texture_vertices->len + 4); + ctx->texture_vertices->len + 6); p = &g_array_index (ctx->texture_vertices, CoglTextureGLVertex, - ctx->texture_vertices->len - 4); + ctx->texture_vertices->len - 6); #define CFX_F(x) COGL_FIXED_TO_FLOAT(x) @@ -2094,13 +2094,20 @@ _cogl_texture_quad_sw (CoglTexture *tex, p->v[0] = CFX_F (slice_qx2); p->v[1] = CFX_F (slice_qy2); p->t[0] = CFX_F (slice_tx2); p->t[1] = CFX_F (slice_ty2); p++; - p->v[0] = CFX_F (slice_qx2); p->v[1] = CFX_F (slice_qy1); - p->t[0] = CFX_F (slice_tx2); p->t[1] = CFX_F (slice_ty1); - p++; p->v[0] = CFX_F (slice_qx1); p->v[1] = CFX_F (slice_qy1); p->t[0] = CFX_F (slice_tx1); p->t[1] = CFX_F (slice_ty1); p++; + p->v[0] = CFX_F (slice_qx1); p->v[1] = CFX_F (slice_qy1); + p->t[0] = CFX_F (slice_tx1); p->t[1] = CFX_F (slice_ty1); + p++; + p->v[0] = CFX_F (slice_qx2); p->v[1] = CFX_F (slice_qy2); + p->t[0] = CFX_F (slice_tx2); p->t[1] = CFX_F (slice_ty2); + p++; + p->v[0] = CFX_F (slice_qx2); p->v[1] = CFX_F (slice_qy1); + p->t[0] = CFX_F (slice_tx2); p->t[1] = CFX_F (slice_ty1); + p++; + #undef CFX_F } } @@ -2149,9 +2156,9 @@ _cogl_texture_quad_hw (CoglTexture *tex, ty2 = ty2 * (y_span->size - y_span->waste) / y_span->size; /* Add the quad to the list of queued vertices */ - g_array_set_size (ctx->texture_vertices, ctx->texture_vertices->len + 4); + g_array_set_size (ctx->texture_vertices, ctx->texture_vertices->len + 6); p = &g_array_index (ctx->texture_vertices, CoglTextureGLVertex, - ctx->texture_vertices->len - 4); + ctx->texture_vertices->len - 6); #define CFX_F(x) COGL_FIXED_TO_FLOAT(x) @@ -2161,13 +2168,20 @@ _cogl_texture_quad_hw (CoglTexture *tex, p->v[0] = CFX_F (x2); p->v[1] = CFX_F (y2); p->t[0] = CFX_F (tx2); p->t[1] = CFX_F (ty2); p++; - p->v[0] = CFX_F (x2); p->v[1] = CFX_F (y1); - p->t[0] = CFX_F (tx2); p->t[1] = CFX_F (ty1); - p++; p->v[0] = CFX_F (x1); p->v[1] = CFX_F (y1); p->t[0] = CFX_F (tx1); p->t[1] = CFX_F (ty1); p++; + p->v[0] = CFX_F (x1); p->v[1] = CFX_F (y1); + p->t[0] = CFX_F (tx1); p->t[1] = CFX_F (ty1); + p++; + p->v[0] = CFX_F (x2); p->v[1] = CFX_F (y2); + p->t[0] = CFX_F (tx2); p->t[1] = CFX_F (ty2); + p++; + p->v[0] = CFX_F (x2); p->v[1] = CFX_F (y1); + p->t[0] = CFX_F (tx2); p->t[1] = CFX_F (ty1); + p++; + #undef CFX_F } From e3f077d55f323d71efed19def7f6a740ff78c2ec Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 4 Dec 2008 17:50:03 +0000 Subject: [PATCH 06/11] Use the correct length in _cogl_texture_flush_vertices The check for whether there are any rectangles to flush was using the wrong value so it would always flush. Thanks to Johan Bilien for spotting. --- clutter/cogl/gl/cogl-texture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c index 6031305e1..471bf4776 100644 --- a/clutter/cogl/gl/cogl-texture.c +++ b/clutter/cogl/gl/cogl-texture.c @@ -1911,7 +1911,7 @@ _cogl_texture_flush_vertices (void) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); - if (ctx->texture_vertices > 0) + if (ctx->texture_vertices->len > 0) { CoglTextureGLVertex *p = (CoglTextureGLVertex *) ctx->texture_vertices->data; From bf72b8cdc3c43221e0813475957712f3ad9c8265 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 9 Dec 2008 13:02:28 +0000 Subject: [PATCH 07/11] Use glDrawRangeElements to share vertices When drawing a quad from cogl_texture_multiple_rectangles share two of the vertices in each triangle by using indices. --- clutter/cogl/gl/cogl-context.c | 4 + clutter/cogl/gl/cogl-context.h | 1 + clutter/cogl/gl/cogl-texture.c | 157 +++++++++++++++++---------------- 3 files changed, 88 insertions(+), 74 deletions(-) diff --git a/clutter/cogl/gl/cogl-context.c b/clutter/cogl/gl/cogl-context.c index 8a12e9572..dbb911024 100644 --- a/clutter/cogl/gl/cogl-context.c +++ b/clutter/cogl/gl/cogl-context.c @@ -58,6 +58,8 @@ cogl_create_context () _context->texture_handles = NULL; _context->texture_vertices = g_array_new (FALSE, FALSE, sizeof (CoglTextureGLVertex)); + _context->texture_indices = g_array_new (FALSE, FALSE, + sizeof (GLushort)); _context->fbo_handles = NULL; _context->draw_buffer = COGL_WINDOW_BUFFER; @@ -150,6 +152,8 @@ cogl_destroy_context () if (_context->texture_vertices) g_array_free (_context->texture_vertices, TRUE); + if (_context->texture_indices) + g_array_free (_context->texture_indices, TRUE); g_free (_context); } diff --git a/clutter/cogl/gl/cogl-context.h b/clutter/cogl/gl/cogl-context.h index fd6e1b918..edabaca50 100644 --- a/clutter/cogl/gl/cogl-context.h +++ b/clutter/cogl/gl/cogl-context.h @@ -64,6 +64,7 @@ typedef struct /* Textures */ GArray *texture_handles; GArray *texture_vertices; + GArray *texture_indices; /* The gl texture number that the above vertices apply to. This to detect when a different slice is encountered so that the vertices can be flushed */ diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c index 8f1dc6ded..4397da7f1 100644 --- a/clutter/cogl/gl/cogl-texture.c +++ b/clutter/cogl/gl/cogl-texture.c @@ -1927,12 +1927,64 @@ _cogl_texture_flush_vertices (void) sizeof (CoglTextureGLVertex), p->t ) ); GE( glBindTexture (ctx->texture_target, ctx->texture_current) ); - GE( glDrawArrays (GL_TRIANGLES, 0, ctx->texture_vertices->len) ); + GE( ctx->pf_glDrawRangeElements (GL_TRIANGLES, + 0, ctx->texture_vertices->len - 1, + ctx->texture_indices->len, + GL_UNSIGNED_SHORT, + ctx->texture_indices->data) ); g_array_set_size (ctx->texture_vertices, 0); + g_array_set_size (ctx->texture_indices, 0); } } +static void +_cogl_texture_add_quad_vertices (GLfloat x1, GLfloat y1, + GLfloat x2, GLfloat y2, + GLfloat tx1, GLfloat ty1, + GLfloat tx2, GLfloat ty2) +{ + CoglTextureGLVertex *p; + GLushort first_vert; + GLushort *q; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* Add the four vertices of the quad to the list of queued + vertices */ + first_vert = ctx->texture_vertices->len; + g_array_set_size (ctx->texture_vertices, first_vert + 4); + p = &g_array_index (ctx->texture_vertices, CoglTextureGLVertex, first_vert); + + p->v[0] = x1; p->v[1] = y1; + p->t[0] = tx1; p->t[1] = ty1; + p++; + p->v[0] = x1; p->v[1] = y2; + p->t[0] = tx1; p->t[1] = ty2; + p++; + p->v[0] = x2; p->v[1] = y2; + p->t[0] = tx2; p->t[1] = ty2; + p++; + p->v[0] = x2; p->v[1] = y1; + p->t[0] = tx2; p->t[1] = ty1; + p++; + + /* Add two triangles to the list of indices. That makes six new + indices but two of the vertices in the triangles are shared. */ + g_array_set_size (ctx->texture_indices, + ctx->texture_indices->len + 6); + q = &g_array_index (ctx->texture_indices, GLushort, + ctx->texture_indices->len - 6); + + *(q++) = first_vert + 0; + *(q++) = first_vert + 1; + *(q++) = first_vert + 3; + + *(q++) = first_vert + 1; + *(q++) = first_vert + 2; + *(q++) = first_vert + 3; +} + static void _cogl_texture_quad_sw (CoglTexture *tex, CoglFixed x1, @@ -1944,17 +1996,16 @@ _cogl_texture_quad_sw (CoglTexture *tex, CoglFixed tx2, CoglFixed ty2) { - CoglSpanIter iter_x , iter_y; - CoglFixed tw , th; - CoglFixed tqx , tqy; - CoglFixed first_tx , first_ty; - CoglFixed first_qx , first_qy; - CoglFixed slice_tx1 , slice_ty1; - CoglFixed slice_tx2 , slice_ty2; - CoglFixed slice_qx1 , slice_qy1; - CoglFixed slice_qx2 , slice_qy2; - GLuint gl_handle; - CoglTextureGLVertex *p; + CoglSpanIter iter_x , iter_y; + CoglFixed tw , th; + CoglFixed tqx , tqy; + CoglFixed first_tx , first_ty; + CoglFixed first_qx , first_qy; + CoglFixed slice_tx1 , slice_ty1; + CoglFixed slice_tx2 , slice_ty2; + CoglFixed slice_qx1 , slice_qy1; + CoglFixed slice_qx2 , slice_qy2; + GLuint gl_handle; _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -2098,35 +2149,14 @@ _cogl_texture_quad_sw (CoglTexture *tex, ctx->texture_target = tex->gl_target; ctx->texture_current = gl_handle; - /* Add the quad to the list of queued vertices */ - g_array_set_size (ctx->texture_vertices, - ctx->texture_vertices->len + 6); - p = &g_array_index (ctx->texture_vertices, CoglTextureGLVertex, - ctx->texture_vertices->len - 6); - -#define CFX_F(x) COGL_FIXED_TO_FLOAT(x) - - p->v[0] = CFX_F (slice_qx1); p->v[1] = CFX_F (slice_qy2); - p->t[0] = CFX_F (slice_tx1); p->t[1] = CFX_F (slice_ty2); - p++; - p->v[0] = CFX_F (slice_qx2); p->v[1] = CFX_F (slice_qy2); - p->t[0] = CFX_F (slice_tx2); p->t[1] = CFX_F (slice_ty2); - p++; - p->v[0] = CFX_F (slice_qx1); p->v[1] = CFX_F (slice_qy1); - p->t[0] = CFX_F (slice_tx1); p->t[1] = CFX_F (slice_ty1); - p++; - - p->v[0] = CFX_F (slice_qx1); p->v[1] = CFX_F (slice_qy1); - p->t[0] = CFX_F (slice_tx1); p->t[1] = CFX_F (slice_ty1); - p++; - p->v[0] = CFX_F (slice_qx2); p->v[1] = CFX_F (slice_qy2); - p->t[0] = CFX_F (slice_tx2); p->t[1] = CFX_F (slice_ty2); - p++; - p->v[0] = CFX_F (slice_qx2); p->v[1] = CFX_F (slice_qy1); - p->t[0] = CFX_F (slice_tx2); p->t[1] = CFX_F (slice_ty1); - p++; - -#undef CFX_F + _cogl_texture_add_quad_vertices (COGL_FIXED_TO_FLOAT (slice_qx1), + COGL_FIXED_TO_FLOAT (slice_qy1), + COGL_FIXED_TO_FLOAT (slice_qx2), + COGL_FIXED_TO_FLOAT (slice_qy2), + COGL_FIXED_TO_FLOAT (slice_tx1), + COGL_FIXED_TO_FLOAT (slice_ty1), + COGL_FIXED_TO_FLOAT (slice_tx2), + COGL_FIXED_TO_FLOAT (slice_ty2)); } } } @@ -2142,11 +2172,10 @@ _cogl_texture_quad_hw (CoglTexture *tex, CoglFixed tx2, CoglFixed ty2) { - GLuint gl_handle; - CoglTexSliceSpan *x_span; - CoglTexSliceSpan *y_span; - CoglTextureGLVertex *p; - GLenum wrap_mode; + GLuint gl_handle; + CoglTexSliceSpan *x_span; + CoglTexSliceSpan *y_span; + GLenum wrap_mode; #if COGL_DEBUG printf("=== Drawing Tex Quad (Hardware Tiling Mode) ===\n"); @@ -2190,11 +2219,6 @@ _cogl_texture_quad_hw (CoglTexture *tex, ty1 = ty1 * (y_span->size - y_span->waste) / y_span->size; ty2 = ty2 * (y_span->size - y_span->waste) / y_span->size; - /* Add the quad to the list of queued vertices */ - g_array_set_size (ctx->texture_vertices, ctx->texture_vertices->len + 6); - p = &g_array_index (ctx->texture_vertices, CoglTextureGLVertex, - ctx->texture_vertices->len - 6); - /* Denormalize texture coordinates for rectangle textures */ if (tex->gl_target == GL_TEXTURE_RECTANGLE_ARB) { @@ -2204,29 +2228,14 @@ _cogl_texture_quad_hw (CoglTexture *tex, ty2 *= y_span->size; } -#define CFX_F(x) COGL_FIXED_TO_FLOAT(x) - - p->v[0] = CFX_F (x1); p->v[1] = CFX_F (y2); - p->t[0] = CFX_F (tx1); p->t[1] = CFX_F (ty2); - p++; - p->v[0] = CFX_F (x2); p->v[1] = CFX_F (y2); - p->t[0] = CFX_F (tx2); p->t[1] = CFX_F (ty2); - p++; - p->v[0] = CFX_F (x1); p->v[1] = CFX_F (y1); - p->t[0] = CFX_F (tx1); p->t[1] = CFX_F (ty1); - p++; - - p->v[0] = CFX_F (x1); p->v[1] = CFX_F (y1); - p->t[0] = CFX_F (tx1); p->t[1] = CFX_F (ty1); - p++; - p->v[0] = CFX_F (x2); p->v[1] = CFX_F (y2); - p->t[0] = CFX_F (tx2); p->t[1] = CFX_F (ty2); - p++; - p->v[0] = CFX_F (x2); p->v[1] = CFX_F (y1); - p->t[0] = CFX_F (tx2); p->t[1] = CFX_F (ty1); - p++; - -#undef CFX_F + _cogl_texture_add_quad_vertices (COGL_FIXED_TO_FLOAT (x1), + COGL_FIXED_TO_FLOAT (y1), + COGL_FIXED_TO_FLOAT (x2), + COGL_FIXED_TO_FLOAT (y2), + COGL_FIXED_TO_FLOAT (tx1), + COGL_FIXED_TO_FLOAT (ty1), + COGL_FIXED_TO_FLOAT (tx2), + COGL_FIXED_TO_FLOAT (ty2)); } void From 73974de482cff70c124aa49869b77099382591c3 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 9 Dec 2008 13:16:42 +0000 Subject: [PATCH 08/11] Add gtk-doc for cogl_texture_multiple_rectangles --- clutter/cogl/cogl-texture.h | 18 ++++++++++++++++++ doc/reference/cogl/cogl-sections.txt | 1 + 2 files changed, 19 insertions(+) diff --git a/clutter/cogl/cogl-texture.h b/clutter/cogl/cogl-texture.h index 5df2a818d..95e663084 100644 --- a/clutter/cogl/cogl-texture.h +++ b/clutter/cogl/cogl-texture.h @@ -385,6 +385,24 @@ void cogl_texture_polygon (CoglHandle handle, CoglTextureVertex *vertices, gboolean use_color); +/** + * cogl_texture_multiple_rectangles: + * @handle: a @CoglHandle. + * @verts: an array of vertices + * @n_rects: number of rectangles to draw + * + * Draws a series of rectangles in the same way that + * cogl_texture_rectangle() does. In some situations it can give a + * significant performance boost to use this function rather than + * calling cogl_texture_rectangle() separately for each rectangle. + * + * @verts should point to an array of #CoglFixeds with + * @n_rects * 8 elements. Each group of 8 values corresponds to the + * parameters x1, y1, x2, y2, tx1, ty1, tx2 and ty2 and have the same + * meaning as in cogl_texture_rectangle(). + * + * Since: 1.0 + */ void cogl_texture_multiple_rectangles (CoglHandle handle, const CoglFixed *verts, diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt index 03247ff3c..dcd7c933f 100644 --- a/doc/reference/cogl/cogl-sections.txt +++ b/doc/reference/cogl/cogl-sections.txt @@ -120,6 +120,7 @@ cogl_texture_set_region cogl_texture_ref cogl_texture_unref cogl_texture_rectangle +cogl_texture_multiple_rectangles cogl_texture_polygon From 8fc949bfafe0ca5de2cf19081f122896e29a3794 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 9 Dec 2008 15:01:10 +0000 Subject: [PATCH 09/11] Minor fix to indentation in gl/cogl-texture.c --- clutter/cogl/gl/cogl-texture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c index 4397da7f1..ee1481296 100644 --- a/clutter/cogl/gl/cogl-texture.c +++ b/clutter/cogl/gl/cogl-texture.c @@ -2265,7 +2265,7 @@ cogl_texture_multiple_rectangles (CoglHandle handle, return; /* Prepare GL state */ - if (tex->gl_target == CGL_TEXTURE_RECTANGLE_ARB) + if (tex->gl_target == CGL_TEXTURE_RECTANGLE_ARB) enable_flags |= COGL_ENABLE_TEXTURE_RECT; else enable_flags |= COGL_ENABLE_TEXTURE_2D; From 0bedd891fb716e03b867e1f450205a2d503721cf Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 9 Dec 2008 15:10:33 +0000 Subject: [PATCH 10/11] Support cogl_texture_multiple_rectangles in GL ES backend --- clutter/cogl/gles/cogl-context.c | 14 +- clutter/cogl/gles/cogl-context.h | 11 +- clutter/cogl/gles/cogl-texture.c | 343 ++++++++++++++++++------------- 3 files changed, 212 insertions(+), 156 deletions(-) diff --git a/clutter/cogl/gles/cogl-context.c b/clutter/cogl/gles/cogl-context.c index c7c768dec..b09568de4 100644 --- a/clutter/cogl/gles/cogl-context.c +++ b/clutter/cogl/gles/cogl-context.c @@ -59,9 +59,11 @@ cogl_create_context () _context->last_path = 0; _context->texture_handles = NULL; - _context->texture_vertices_size = 0; - _context->texture_vertices = NULL; - + _context->texture_vertices = g_array_new (FALSE, FALSE, + sizeof (CoglTextureGLVertex)); + _context->texture_indices = g_array_new (FALSE, FALSE, + sizeof (GLushort)); + _context->fbo_handles = NULL; _context->program_handles = NULL; _context->shader_handles = NULL; @@ -104,8 +106,10 @@ cogl_destroy_context () #endif if (_context->texture_vertices) - g_free (_context->texture_vertices); - + g_array_free (_context->texture_vertices, TRUE); + if (_context->texture_indices) + g_array_free (_context->texture_indices, TRUE); + if (_context->texture_handles) g_array_free (_context->texture_handles, TRUE); if (_context->fbo_handles) diff --git a/clutter/cogl/gles/cogl-context.h b/clutter/cogl/gles/cogl-context.h index b62903efc..5d835712a 100644 --- a/clutter/cogl/gles/cogl-context.h +++ b/clutter/cogl/gles/cogl-context.h @@ -65,9 +65,14 @@ typedef struct /* Textures */ GArray *texture_handles; - CoglTextureGLVertex *texture_vertices; - gulong texture_vertices_size; - + GArray *texture_vertices; + GArray *texture_indices; + /* The gl texture number that the above vertices apply to. This to + detect when a different slice is encountered so that the vertices + can be flushed */ + GLuint texture_current; + GLenum texture_target; + /* Framebuffer objects */ GArray *fbo_handles; CoglBufferTarget draw_buffer; diff --git a/clutter/cogl/gles/cogl-texture.c b/clutter/cogl/gles/cogl-texture.c index 5a75eb389..9fa677687 100644 --- a/clutter/cogl/gles/cogl-texture.c +++ b/clutter/cogl/gles/cogl-texture.c @@ -2047,6 +2047,79 @@ cogl_texture_get_data (CoglHandle handle, return byte_size; } +static void +_cogl_texture_flush_vertices (void) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->texture_vertices->len > 0) + { + CoglTextureGLVertex *p + = (CoglTextureGLVertex *) ctx->texture_vertices->data; + + GE( glVertexPointer (2, GL_FLOAT, + sizeof (CoglTextureGLVertex), p->v ) ); + GE( glTexCoordPointer (2, GL_FLOAT, + sizeof (CoglTextureGLVertex), p->t ) ); + + GE( glBindTexture (ctx->texture_target, ctx->texture_current) ); + GE( glDrawElements (GL_TRIANGLES, + ctx->texture_indices->len, + GL_UNSIGNED_SHORT, + ctx->texture_indices->data) ); + + g_array_set_size (ctx->texture_vertices, 0); + g_array_set_size (ctx->texture_indices, 0); + } +} + +static void +_cogl_texture_add_quad_vertices (GLfloat x1, GLfloat y1, + GLfloat x2, GLfloat y2, + GLfloat tx1, GLfloat ty1, + GLfloat tx2, GLfloat ty2) +{ + CoglTextureGLVertex *p; + GLushort first_vert; + GLushort *q; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* Add the four vertices of the quad to the list of queued + vertices */ + first_vert = ctx->texture_vertices->len; + g_array_set_size (ctx->texture_vertices, first_vert + 4); + p = &g_array_index (ctx->texture_vertices, CoglTextureGLVertex, first_vert); + + p->v[0] = x1; p->v[1] = y1; + p->t[0] = tx1; p->t[1] = ty1; + p++; + p->v[0] = x1; p->v[1] = y2; + p->t[0] = tx1; p->t[1] = ty2; + p++; + p->v[0] = x2; p->v[1] = y2; + p->t[0] = tx2; p->t[1] = ty2; + p++; + p->v[0] = x2; p->v[1] = y1; + p->t[0] = tx2; p->t[1] = ty1; + p++; + + /* Add two triangles to the list of indices. That makes six new + indices but two of the vertices in the triangles are shared. */ + g_array_set_size (ctx->texture_indices, + ctx->texture_indices->len + 6); + q = &g_array_index (ctx->texture_indices, GLushort, + ctx->texture_indices->len - 6); + + *(q++) = first_vert + 0; + *(q++) = first_vert + 1; + *(q++) = first_vert + 3; + + *(q++) = first_vert + 1; + *(q++) = first_vert + 2; + *(q++) = first_vert + 3; +} + static void _cogl_texture_quad_sw (CoglTexture *tex, CoglFixed x1, @@ -2067,31 +2140,13 @@ _cogl_texture_quad_sw (CoglTexture *tex, CoglFixed slice_tx2 , slice_ty2; CoglFixed slice_qx1 , slice_qy1; CoglFixed slice_qx2 , slice_qy2; - GLfloat tex_coords[8]; - GLfloat quad_coords[8]; GLuint gl_handle; - gulong enable_flags = (COGL_ENABLE_TEXTURE_2D - | COGL_ENABLE_VERTEX_ARRAY - | COGL_ENABLE_TEXCOORD_ARRAY); - + _COGL_GET_CONTEXT (ctx, NO_RETVAL); #if COGL_DEBUG printf("=== Drawing Tex Quad (Software Tiling Mode) ===\n"); #endif - - - /* Prepare GL state */ - if (ctx->color_alpha < 255 - || tex->bitmap.format & COGL_A_BIT) - { - enable_flags |= COGL_ENABLE_BLEND; - } - - if (ctx->enable_backface_culling) - enable_flags |= COGL_ENABLE_BACKFACE_CULLING; - - cogl_enable (enable_flags); /* If the texture coordinates are backwards then swap both the geometry and texture coordinates so that the texture will be @@ -2115,10 +2170,7 @@ _cogl_texture_quad_sw (CoglTexture *tex, ty1 = ty2; ty2 = temp; } - - GE( glTexCoordPointer (2, GL_FLOAT, 0, tex_coords) ); - GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords) ); - + /* Scale ratio from texture to quad widths */ tw = COGL_FIXED_FROM_INT (tex->bitmap.width); th = COGL_FIXED_FROM_INT (tex->bitmap.height); @@ -2158,17 +2210,16 @@ _cogl_texture_quad_sw (CoglTexture *tex, slice_qy2 = first_qy + COGL_FIXED_MUL (iter_y.intersect_end - first_ty, tqy); - + /* Localize slice texture coordinates */ slice_ty1 = iter_y.intersect_start - iter_y.pos; slice_ty2 = iter_y.intersect_end - iter_y.pos; - + /* Normalize texture coordinates to current slice (rectangle texture targets take denormalized) */ slice_ty1 /= iter_y.span->size; slice_ty2 /= iter_y.span->size; - - + /* Iterate until whole quad width covered */ for (_cogl_span_iter_begin (&iter_x, tex->slice_x_spans, first_tx, tx1, tx2) ; @@ -2188,12 +2239,12 @@ _cogl_texture_quad_sw (CoglTexture *tex, /* Localize slice texture coordinates */ slice_tx1 = iter_x.intersect_start - iter_x.pos; slice_tx2 = iter_x.intersect_end - iter_x.pos; - + /* Normalize texture coordinates to current slice (rectangle texture targets take denormalized) */ slice_tx1 /= iter_x.span->size; slice_tx2 /= iter_x.span->size; - + #if COGL_DEBUG printf("~~~~~ slice (%d,%d)\n", iter_x.index, iter_y.index); printf("qx1: %f\n", COGL_FIXED_TO_FLOAT (slice_qx1)); @@ -2210,26 +2261,23 @@ _cogl_texture_quad_sw (CoglTexture *tex, gl_handle = g_array_index (tex->slice_gl_handles, GLuint, iter_y.index * iter_x.array->len + iter_x.index); - - GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle, - tex->gl_intformat) ); -#define CFX_F COGL_FIXED_TO_FLOAT - - /* Draw textured quad */ - tex_coords[0] = CFX_F(slice_tx1); tex_coords[1] = CFX_F(slice_ty2); - tex_coords[2] = CFX_F(slice_tx2); tex_coords[3] = CFX_F(slice_ty2); - tex_coords[4] = CFX_F(slice_tx1); tex_coords[5] = CFX_F(slice_ty1); - tex_coords[6] = CFX_F(slice_tx2); tex_coords[7] = CFX_F(slice_ty1); + /* If we're using a different texture from the one already queued + then flush the vertices */ + if (ctx->texture_vertices->len > 0 + && gl_handle != ctx->texture_current) + _cogl_texture_flush_vertices (); + ctx->texture_target = tex->gl_target; + ctx->texture_current = gl_handle; - quad_coords[0] = CFX_F(slice_qx1); quad_coords[1] = CFX_F(slice_qy2); - quad_coords[2] = CFX_F(slice_qx2); quad_coords[3] = CFX_F(slice_qy2); - quad_coords[4] = CFX_F(slice_qx1); quad_coords[5] = CFX_F(slice_qy1); - quad_coords[6] = CFX_F(slice_qx2); quad_coords[7] = CFX_F(slice_qy1); - - GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); - -#undef CFX_F + _cogl_texture_add_quad_vertices (COGL_FIXED_TO_FLOAT (slice_qx1), + COGL_FIXED_TO_FLOAT (slice_qy1), + COGL_FIXED_TO_FLOAT (slice_qx2), + COGL_FIXED_TO_FLOAT (slice_qy2), + COGL_FIXED_TO_FLOAT (slice_tx1), + COGL_FIXED_TO_FLOAT (slice_ty1), + COGL_FIXED_TO_FLOAT (slice_tx2), + COGL_FIXED_TO_FLOAT (slice_ty2)); } } } @@ -2245,41 +2293,27 @@ _cogl_texture_quad_hw (CoglTexture *tex, CoglFixed tx2, CoglFixed ty2) { - GLfloat tex_coords[8]; - GLfloat quad_coords[8]; GLuint gl_handle; CoglTexSliceSpan *x_span; CoglTexSliceSpan *y_span; - gulong enable_flags = (COGL_ENABLE_TEXTURE_2D - | COGL_ENABLE_VERTEX_ARRAY - | COGL_ENABLE_TEXCOORD_ARRAY); #if COGL_DEBUG printf("=== Drawing Tex Quad (Hardware Tiling Mode) ===\n"); #endif - - _COGL_GET_CONTEXT (ctx, NO_RETVAL); - - /* Prepare GL state */ - if (ctx->color_alpha < 255 - || tex->bitmap.format & COGL_A_BIT) - { - enable_flags |= COGL_ENABLE_BLEND; - } - - if (ctx->enable_backface_culling) - enable_flags |= COGL_ENABLE_BACKFACE_CULLING; - cogl_enable (enable_flags); - - GE( glTexCoordPointer (2, GL_FLOAT, 0, tex_coords) ); - GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords) ); - + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + /* Pick and bind opengl texture object */ gl_handle = g_array_index (tex->slice_gl_handles, GLuint, 0); - GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle, - tex->gl_intformat) ); - + + /* If we're using a different texture from the one already queued + then flush the vertices */ + if (ctx->texture_vertices->len > 0 + && gl_handle != ctx->texture_current) + _cogl_texture_flush_vertices (); + ctx->texture_target = tex->gl_target; + ctx->texture_current = gl_handle; + /* Don't include the waste in the texture coordinates */ x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0); y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 0); @@ -2290,22 +2324,80 @@ _cogl_texture_quad_hw (CoglTexture *tex, ty1 = ty1 * (y_span->size - y_span->waste) / y_span->size; ty2 = ty2 * (y_span->size - y_span->waste) / y_span->size; -#define CFX_F(x) COGL_FIXED_TO_FLOAT(x) + _cogl_texture_add_quad_vertices (COGL_FIXED_TO_FLOAT (x1), + COGL_FIXED_TO_FLOAT (y1), + COGL_FIXED_TO_FLOAT (x2), + COGL_FIXED_TO_FLOAT (y2), + COGL_FIXED_TO_FLOAT (tx1), + COGL_FIXED_TO_FLOAT (ty1), + COGL_FIXED_TO_FLOAT (tx2), + COGL_FIXED_TO_FLOAT (ty2)); +} + +void +cogl_texture_multiple_rectangles (CoglHandle handle, + const CoglFixed *verts, + guint n_rects) +{ + CoglTexture *tex; + gulong enable_flags = (COGL_ENABLE_VERTEX_ARRAY + | COGL_ENABLE_TEXCOORD_ARRAY + | COGL_ENABLE_TEXTURE_2D); + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + /* Check if valid texture */ + if (!cogl_is_texture (handle)) + return; - /* Draw textured quad */ - tex_coords[0] = CFX_F(tx1); tex_coords[1] = CFX_F(ty2); - tex_coords[2] = CFX_F(tx2); tex_coords[3] = CFX_F(ty2); - tex_coords[4] = CFX_F(tx1); tex_coords[5] = CFX_F(ty1); - tex_coords[6] = CFX_F(tx2); tex_coords[7] = CFX_F(ty1); + cogl_clip_ensure (); - quad_coords[0] = CFX_F(x1); quad_coords[1] = CFX_F(y2); - quad_coords[2] = CFX_F(x2); quad_coords[3] = CFX_F(y2); - quad_coords[4] = CFX_F(x1); quad_coords[5] = CFX_F(y1); - quad_coords[6] = CFX_F(x2); quad_coords[7] = CFX_F(y1); + tex = _cogl_texture_pointer_from_handle (handle); + + /* Make sure we got stuff to draw */ + if (tex->slice_gl_handles == NULL) + return; + + if (tex->slice_gl_handles->len == 0) + return; - GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); + /* Prepare GL state */ + if (ctx->color_alpha < 255 + || tex->bitmap.format & COGL_A_BIT) + enable_flags |= COGL_ENABLE_BLEND; -#undef CFX_F + if (ctx->enable_backface_culling) + enable_flags |= COGL_ENABLE_BACKFACE_CULLING; + + cogl_enable (enable_flags); + + g_array_set_size (ctx->texture_vertices, 0); + + while (n_rects-- > 0) + { + if (verts[4] != verts[6] && verts[5] != verts[7]) + { + /* If there is only one GL texture and either the texture is + NPOT (no waste) or all of the coordinates are in the + range [0,1] then we can use hardware tiling */ + if (tex->slice_gl_handles->len == 1 + && ((cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) + && tex->gl_target == GL_TEXTURE_2D) + || (verts[4] >= 0 && verts[4] <= COGL_FIXED_1 + && verts[6] >= 0 && verts[6] <= COGL_FIXED_1 + && verts[5] >= 0 && verts[5] <= COGL_FIXED_1 + && verts[7] >= 0 && verts[7] <= COGL_FIXED_1))) + _cogl_texture_quad_hw (tex, verts[0],verts[1], verts[2],verts[3], + verts[4],verts[5], verts[6],verts[7]); + else + _cogl_texture_quad_sw (tex, verts[0],verts[1], verts[2],verts[3], + verts[4],verts[5], verts[6],verts[7]); + } + + verts += 8; + } + + _cogl_texture_flush_vertices (); } void @@ -2319,47 +2411,18 @@ cogl_texture_rectangle (CoglHandle handle, CoglFixed tx2, CoglFixed ty2) { - CoglTexture *tex; - - /* Check if valid texture */ - if (!cogl_is_texture (handle)) - return; + CoglFixed verts[8]; - cogl_clip_ensure (); - - tex = _cogl_texture_pointer_from_handle (handle); - - /* Make sure we got stuff to draw */ - if (tex->slice_gl_handles == NULL) - return; - - if (tex->slice_gl_handles->len == 0) - return; - - if (tx1 == tx2 || ty1 == ty2) - return; - - /* Pick tiling mode according to hw support */ - if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) - && tex->slice_gl_handles->len == 1) - { - _cogl_texture_quad_hw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2); - } - else - { - if (tex->slice_gl_handles->len == 1 - && tx1 >= -COGL_FIXED_1 - && tx2 <= COGL_FIXED_1 - && ty1 >= -COGL_FIXED_1 - && ty2 <= COGL_FIXED_1) - { - _cogl_texture_quad_hw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2); - } - else - { - _cogl_texture_quad_sw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2); - } - } + verts[0] = x1; + verts[1] = y1; + verts[2] = x2; + verts[3] = y2; + verts[4] = tx1; + verts[5] = ty1; + verts[6] = tx2; + verts[7] = ty2; + + cogl_texture_multiple_rectangles (handle, verts, 1); } void @@ -2405,23 +2468,9 @@ cogl_texture_polygon (CoglHandle handle, /* Make sure there is enough space in the global texture vertex array. This is used so we can render the polygon with a single call to OpenGL but still support any number of vertices */ - if (ctx->texture_vertices_size < n_vertices) - { - guint nsize = ctx->texture_vertices_size; - - if (nsize == 0) - nsize = 1; - do - nsize *= 2; - while (nsize < n_vertices); - - ctx->texture_vertices_size = nsize; + g_array_set_size (ctx->texture_vertices, n_vertices); + p = (CoglTextureGLVertex *) ctx->texture_vertices->data; - ctx->texture_vertices = g_realloc (ctx->texture_vertices, - nsize - * sizeof (CoglTextureGLVertex)); - } - /* Prepare GL state */ enable_flags = (COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_VERTEX_ARRAY @@ -2447,14 +2496,12 @@ cogl_texture_polygon (CoglHandle handle, if (use_color) { enable_flags |= COGL_ENABLE_COLOR_ARRAY; - GE( glColorPointer (4, GL_UNSIGNED_BYTE, sizeof (CoglTextureGLVertex), - ctx->texture_vertices[0].c) ); - } + GE( glColorPointer (4, GL_UNSIGNED_BYTE, + sizeof (CoglTextureGLVertex), p->c) ); + } - GE( glVertexPointer (3, GL_FLOAT, sizeof (CoglTextureGLVertex), - ctx->texture_vertices[0].v) ); - GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex), - ctx->texture_vertices[0].t) ); + GE( glVertexPointer (3, GL_FLOAT, sizeof (CoglTextureGLVertex), p->v ) ); + GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex), p->t ) ); cogl_enable (enable_flags); @@ -2464,7 +2511,7 @@ cogl_texture_polygon (CoglHandle handle, /* Convert the vertices into an array of GLfloats ready to pass to OpenGL */ - for (i = 0, p = ctx->texture_vertices; i < n_vertices; i++, p++) + for (i = 0; i < n_vertices; i++, p++) { #define CFX_F COGL_FIXED_TO_FLOAT From 9537f8e4ae69af43848f679d6568e94eb800b266 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 9 Dec 2008 18:03:29 +0000 Subject: [PATCH 11/11] Use a single index array There's no point in clearing the index array because it is always the same sequence of indices regardless of the vertices. Instead it is just added to when there are more vertices than ever before. --- clutter/cogl/gl/cogl-texture.c | 51 +++++++++++++++++++++----------- clutter/cogl/gles/cogl-texture.c | 51 +++++++++++++++++++++----------- 2 files changed, 66 insertions(+), 36 deletions(-) diff --git a/clutter/cogl/gl/cogl-texture.c b/clutter/cogl/gl/cogl-texture.c index ee1481296..71a53f06b 100644 --- a/clutter/cogl/gl/cogl-texture.c +++ b/clutter/cogl/gl/cogl-texture.c @@ -1918,9 +1918,41 @@ _cogl_texture_flush_vertices (void) if (ctx->texture_vertices->len > 0) { + int needed_indices; CoglTextureGLVertex *p = (CoglTextureGLVertex *) ctx->texture_vertices->data; + /* The indices are always the same sequence regardless of the + vertices so we only need to change it if there are more + vertices than ever before */ + needed_indices = ctx->texture_vertices->len / 4 * 6; + if (needed_indices > ctx->texture_indices->len) + { + int old_len = ctx->texture_indices->len; + int vert_num = old_len / 6 * 4; + int i; + GLushort *q; + + /* Add two triangles for each quad to the list of + indices. That makes six new indices but two of the + vertices in the triangles are shared. */ + g_array_set_size (ctx->texture_indices, needed_indices); + q = &g_array_index (ctx->texture_indices, GLushort, old_len); + + for (i = old_len; + i < ctx->texture_indices->len; + i += 6, vert_num += 4) + { + *(q++) = vert_num + 0; + *(q++) = vert_num + 1; + *(q++) = vert_num + 3; + + *(q++) = vert_num + 1; + *(q++) = vert_num + 2; + *(q++) = vert_num + 3; + } + } + GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex), p->v ) ); GE( glTexCoordPointer (2, GL_FLOAT, @@ -1929,12 +1961,11 @@ _cogl_texture_flush_vertices (void) GE( glBindTexture (ctx->texture_target, ctx->texture_current) ); GE( ctx->pf_glDrawRangeElements (GL_TRIANGLES, 0, ctx->texture_vertices->len - 1, - ctx->texture_indices->len, + needed_indices, GL_UNSIGNED_SHORT, ctx->texture_indices->data) ); g_array_set_size (ctx->texture_vertices, 0); - g_array_set_size (ctx->texture_indices, 0); } } @@ -1946,7 +1977,6 @@ _cogl_texture_add_quad_vertices (GLfloat x1, GLfloat y1, { CoglTextureGLVertex *p; GLushort first_vert; - GLushort *q; _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -1968,21 +1998,6 @@ _cogl_texture_add_quad_vertices (GLfloat x1, GLfloat y1, p->v[0] = x2; p->v[1] = y1; p->t[0] = tx2; p->t[1] = ty1; p++; - - /* Add two triangles to the list of indices. That makes six new - indices but two of the vertices in the triangles are shared. */ - g_array_set_size (ctx->texture_indices, - ctx->texture_indices->len + 6); - q = &g_array_index (ctx->texture_indices, GLushort, - ctx->texture_indices->len - 6); - - *(q++) = first_vert + 0; - *(q++) = first_vert + 1; - *(q++) = first_vert + 3; - - *(q++) = first_vert + 1; - *(q++) = first_vert + 2; - *(q++) = first_vert + 3; } static void diff --git a/clutter/cogl/gles/cogl-texture.c b/clutter/cogl/gles/cogl-texture.c index 9fa677687..915e82b23 100644 --- a/clutter/cogl/gles/cogl-texture.c +++ b/clutter/cogl/gles/cogl-texture.c @@ -2054,9 +2054,41 @@ _cogl_texture_flush_vertices (void) if (ctx->texture_vertices->len > 0) { + int needed_indices; CoglTextureGLVertex *p = (CoglTextureGLVertex *) ctx->texture_vertices->data; + /* The indices are always the same sequence regardless of the + vertices so we only need to change it if there are more + vertices than ever before */ + needed_indices = ctx->texture_vertices->len / 4 * 6; + if (needed_indices > ctx->texture_indices->len) + { + int old_len = ctx->texture_indices->len; + int vert_num = old_len / 6 * 4; + int i; + GLushort *q; + + /* Add two triangles for each quad to the list of + indices. That makes six new indices but two of the + vertices in the triangles are shared. */ + g_array_set_size (ctx->texture_indices, needed_indices); + q = &g_array_index (ctx->texture_indices, GLushort, old_len); + + for (i = old_len; + i < ctx->texture_indices->len; + i += 6, vert_num += 4) + { + *(q++) = vert_num + 0; + *(q++) = vert_num + 1; + *(q++) = vert_num + 3; + + *(q++) = vert_num + 1; + *(q++) = vert_num + 2; + *(q++) = vert_num + 3; + } + } + GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex), p->v ) ); GE( glTexCoordPointer (2, GL_FLOAT, @@ -2064,12 +2096,11 @@ _cogl_texture_flush_vertices (void) GE( glBindTexture (ctx->texture_target, ctx->texture_current) ); GE( glDrawElements (GL_TRIANGLES, - ctx->texture_indices->len, + needed_indices, GL_UNSIGNED_SHORT, ctx->texture_indices->data) ); g_array_set_size (ctx->texture_vertices, 0); - g_array_set_size (ctx->texture_indices, 0); } } @@ -2081,7 +2112,6 @@ _cogl_texture_add_quad_vertices (GLfloat x1, GLfloat y1, { CoglTextureGLVertex *p; GLushort first_vert; - GLushort *q; _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -2103,21 +2133,6 @@ _cogl_texture_add_quad_vertices (GLfloat x1, GLfloat y1, p->v[0] = x2; p->v[1] = y1; p->t[0] = tx2; p->t[1] = ty1; p++; - - /* Add two triangles to the list of indices. That makes six new - indices but two of the vertices in the triangles are shared. */ - g_array_set_size (ctx->texture_indices, - ctx->texture_indices->len + 6); - q = &g_array_index (ctx->texture_indices, GLushort, - ctx->texture_indices->len - 6); - - *(q++) = first_vert + 0; - *(q++) = first_vert + 1; - *(q++) = first_vert + 3; - - *(q++) = first_vert + 1; - *(q++) = first_vert + 2; - *(q++) = first_vert + 3; } static void