From 5557de30eb80dcb5dfd36b142492cf3d231a89f8 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. --- gl/cogl-context.c | 11 +++++++---- gl/cogl-context.h | 3 +-- gl/cogl-texture.c | 32 +++++++++----------------------- 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/gl/cogl-context.c b/gl/cogl-context.c index a9240a102..006506ac9 100644 --- a/gl/cogl-context.c +++ b/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/gl/cogl-context.h b/gl/cogl-context.h index 5ab583862..f1fd2e786 100644 --- a/gl/cogl-context.h +++ b/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/gl/cogl-texture.c b/gl/cogl-texture.c index bf2eef304..01613c4bd 100644 --- a/gl/cogl-texture.c +++ b/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 47a21cd94f5499201d014452bb8b0c2fc77f5c55 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. --- gl/cogl-context.h | 7 +- gl/cogl-texture.c | 201 ++++++++++++++++++++++++++-------------------- 2 files changed, 119 insertions(+), 89 deletions(-) diff --git a/gl/cogl-context.h b/gl/cogl-context.h index f1fd2e786..ffec47464 100644 --- a/gl/cogl-context.h +++ b/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/gl/cogl-texture.c b/gl/cogl-texture.c index 01613c4bd..fe7208d81 100644 --- a/gl/cogl-texture.c +++ b/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 c502c5c3f41b1dc0f165930c6feb5a3f00aec90b 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. --- cogl-texture.h | 5 ++++ gl/cogl-texture.c | 74 ++++++++++++++++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 24 deletions(-) diff --git a/cogl-texture.h b/cogl-texture.h index 117a12b14..5df2a818d 100644 --- a/cogl-texture.h +++ b/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/gl/cogl-texture.c b/gl/cogl-texture.c index fe7208d81..cd241ff80 100644 --- a/gl/cogl-texture.c +++ b/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 420b1f0791eb2c1b06c115ff33cc49a99eb95d25 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 28 Nov 2008 14:20:07 +0000 Subject: [PATCH 04/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. --- gl/cogl-texture.c | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/gl/cogl-texture.c b/gl/cogl-texture.c index cd241ff80..6031305e1 100644 --- a/gl/cogl-texture.c +++ b/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 7a276affd68d928e5afcb9faa0e8ada69c2141f3 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Thu, 4 Dec 2008 17:50:03 +0000 Subject: [PATCH 05/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. --- gl/cogl-texture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gl/cogl-texture.c b/gl/cogl-texture.c index 6031305e1..471bf4776 100644 --- a/gl/cogl-texture.c +++ b/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 778a9f7d6761e22937e48c9d63001d34b30a9f4a Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 9 Dec 2008 13:02:28 +0000 Subject: [PATCH 06/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. --- gl/cogl-context.c | 4 ++ gl/cogl-context.h | 1 + gl/cogl-texture.c | 157 ++++++++++++++++++++++++---------------------- 3 files changed, 88 insertions(+), 74 deletions(-) diff --git a/gl/cogl-context.c b/gl/cogl-context.c index 8a12e9572..dbb911024 100644 --- a/gl/cogl-context.c +++ b/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/gl/cogl-context.h b/gl/cogl-context.h index fd6e1b918..edabaca50 100644 --- a/gl/cogl-context.h +++ b/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/gl/cogl-texture.c b/gl/cogl-texture.c index 8f1dc6ded..4397da7f1 100644 --- a/gl/cogl-texture.c +++ b/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 3f492e60542ce8303c9863798a935d7967d6d16d Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 9 Dec 2008 13:16:42 +0000 Subject: [PATCH 07/11] Add gtk-doc for cogl_texture_multiple_rectangles --- cogl-texture.h | 18 ++++++++++++++++++ doc/reference/cogl/cogl-sections.txt | 1 + 2 files changed, 19 insertions(+) diff --git a/cogl-texture.h b/cogl-texture.h index 5df2a818d..95e663084 100644 --- a/cogl-texture.h +++ b/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 59aef7488f98fbeb3cedc8f535fbb964b105a51a Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 9 Dec 2008 15:01:10 +0000 Subject: [PATCH 08/11] Minor fix to indentation in gl/cogl-texture.c --- gl/cogl-texture.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gl/cogl-texture.c b/gl/cogl-texture.c index 4397da7f1..ee1481296 100644 --- a/gl/cogl-texture.c +++ b/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 223c1225ea92817a411e86b81adfcae04dba1636 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 9 Dec 2008 15:10:33 +0000 Subject: [PATCH 09/11] Support cogl_texture_multiple_rectangles in GL ES backend --- gles/cogl-context.c | 14 +- gles/cogl-context.h | 11 +- gles/cogl-texture.c | 343 +++++++++++++++++++++++++------------------- 3 files changed, 212 insertions(+), 156 deletions(-) diff --git a/gles/cogl-context.c b/gles/cogl-context.c index c7c768dec..b09568de4 100644 --- a/gles/cogl-context.c +++ b/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/gles/cogl-context.h b/gles/cogl-context.h index b62903efc..5d835712a 100644 --- a/gles/cogl-context.h +++ b/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/gles/cogl-texture.c b/gles/cogl-texture.c index 5a75eb389..9fa677687 100644 --- a/gles/cogl-texture.c +++ b/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 b11b74fcdec86233c67d52d4bc84e8da6de15be2 Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 9 Dec 2008 18:03:29 +0000 Subject: [PATCH 10/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. --- gl/cogl-texture.c | 51 +++++++++++++++++++++++++++++---------------- gles/cogl-texture.c | 51 +++++++++++++++++++++++++++++---------------- 2 files changed, 66 insertions(+), 36 deletions(-) diff --git a/gl/cogl-texture.c b/gl/cogl-texture.c index ee1481296..71a53f06b 100644 --- a/gl/cogl-texture.c +++ b/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/gles/cogl-texture.c b/gles/cogl-texture.c index 9fa677687..915e82b23 100644 --- a/gles/cogl-texture.c +++ b/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 From baa63b7c466397fd9d9e73e3b50399e22a2131f4 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 23 Dec 2008 16:29:29 +0000 Subject: [PATCH 11/11] White space clean up across a number of files (only removing trailing spaces) Removed trailing white space from the following files: - clutter-clone-texture.c - clutter-texture.c - clutter-texture.h - cogl/cogl-texture.h - cogl/gl/cogl-context.c - cogl/gl/cogl-texture.c - cogl/gl/cogl-context.h --- cogl-texture.h | 24 +-- gl/cogl-context.c | 26 +-- gl/cogl-context.h | 16 +- gl/cogl-texture.c | 512 +++++++++++++++++++++++----------------------- 4 files changed, 289 insertions(+), 289 deletions(-) diff --git a/cogl-texture.h b/cogl-texture.h index 117a12b14..07cec1ce1 100644 --- a/cogl-texture.h +++ b/cogl-texture.h @@ -148,7 +148,7 @@ gboolean cogl_is_texture (CoglHandle handle); /** * cogl_texture_get_width: * @handle: a #CoglHandle for a texture. - * + * * Query the width of a cogl texture. * * Returns: the width of the GPU side texture in pixels: @@ -158,7 +158,7 @@ guint cogl_texture_get_width (CoglHandle handle); /** * cogl_texture_get_height: * @handle: a #CoglHandle for a texture. - * + * * Query the height of a cogl texture. * * Returns: the height of the GPU side texture in pixels: @@ -168,7 +168,7 @@ guint cogl_texture_get_height (CoglHandle handle); /** * cogl_texture_get_format: * @handle: a #CoglHandle for a texture. - * + * * Query the #CoglPixelFormat of a cogl texture. * * Returns: the #CoglPixelFormat of the GPU side texture. @@ -179,7 +179,7 @@ CoglPixelFormat cogl_texture_get_format (CoglHandle handle); /** * cogl_texture_get_rowstride: * @handle: a #CoglHandle for a texture. - * + * * Query the rowstride of a cogl texture. * * Returns: the offset in bytes between each consequetive row of pixels. @@ -189,7 +189,7 @@ guint cogl_texture_get_rowstride (CoglHandle handle); /** * cogl_texture_get_max_waste: * @handle: a #CoglHandle for a texture. - * + * * Query the maximum wasted (unused) pixels in one dimension of a GPU side * texture. * @@ -200,7 +200,7 @@ gint cogl_texture_get_max_waste (CoglHandle handle); /** * cogl_texture_get_min_filter: * @handle: a #CoglHandle for a texture. - * + * * Query the currently set downscaling filter for a cogl texture. * * Returns: the current downscaling filter for a cogl texture. @@ -210,7 +210,7 @@ COGLenum cogl_texture_get_min_filter (CoglHandle handle); /** * cogl_texture_get_mag_filter: * @handle: a #CoglHandle for a texture. - * + * * Query the currently set downscaling filter for a cogl texture. * * Returns: the current downscaling filter for a cogl texture. @@ -220,7 +220,7 @@ COGLenum cogl_texture_get_mag_filter (CoglHandle handle); /** * cogl_texture_is_sliced: * @handle: a #CoglHandle for a texture. - * + * * Query if a texture is sliced (stored as multiple GPU side tecture * objects). * @@ -235,7 +235,7 @@ gboolean cogl_texture_is_sliced (CoglHandle handle); * @out_gl_handle: pointer to return location for the textures GL handle, or * NULL. * @out_gl_target: pointer to return location for the GL target type, or NULL. - * + * * Query the GL handles for a GPU side texture through it's #CoglHandle, * if the texture is spliced the data for the first sub texture will be * queried. @@ -255,7 +255,7 @@ gboolean cogl_texture_get_gl_texture (CoglHandle handle, * specified. * @data: memory location to write contents of buffer, or %NULL if we're * only querying the data size through the return value. - * + * * Copy the pixel data from a cogl texture to system memory. * * Returns: the size of the texture data in bytes (or 0 if the texture @@ -271,7 +271,7 @@ gint cogl_texture_get_data (CoglHandle handle, * @handle: a #CoglHandle. * @min_filter: the filter used when scaling the texture down. * @mag_filter: the filter used when magnifying the texture. - * + * * Changes the decimation and interpolation filters used when the texture is * drawn at other scales than 100%. */ @@ -297,7 +297,7 @@ void cogl_texture_set_filters (CoglHandle handle, * @data: the actual pixel data. * * Sets the pixels in a rectangular subregion of @handle from an in-memory - * buffer containing pixel data. + * buffer containing pixel data. * * Returns: %TRUE if the subregion upload was successful, otherwise %FALSE. */ diff --git a/gl/cogl-context.c b/gl/cogl-context.c index d75086fbc..35af840c0 100644 --- a/gl/cogl-context.c +++ b/gl/cogl-context.c @@ -41,27 +41,27 @@ cogl_create_context () { if (_context != NULL) return FALSE; - + /* Allocate context memory */ _context = (CoglContext*) g_malloc (sizeof (CoglContext)); - + /* Init default values */ _context->feature_flags = 0; _context->features_cached = FALSE; - + _context->enable_flags = 0; _context->color_alpha = 255; - + _context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode)); _context->last_path = 0; - + _context->texture_handles = NULL; _context->texture_vertices_size = 0; _context->texture_vertices = NULL; - + _context->fbo_handles = NULL; _context->draw_buffer = COGL_WINDOW_BUFFER; - + _context->blend_src_factor = CGL_SRC_ALPHA; _context->blend_dst_factor = CGL_ONE_MINUS_SRC_ALPHA; @@ -70,7 +70,7 @@ cogl_create_context () _context->program_handles = NULL; _context->mesh_handles = NULL; - + _context->pf_glGenRenderbuffersEXT = NULL; _context->pf_glBindRenderbufferEXT = NULL; _context->pf_glRenderbufferStorageEXT = NULL; @@ -82,7 +82,7 @@ cogl_create_context () _context->pf_glDeleteFramebuffersEXT = NULL; _context->pf_glBlitFramebufferEXT = NULL; _context->pf_glRenderbufferStorageMultisampleEXT = NULL; - + _context->pf_glCreateProgramObjectARB = NULL; _context->pf_glCreateShaderObjectARB = NULL; _context->pf_glShaderSourceARB = NULL; @@ -115,7 +115,7 @@ cogl_create_context () _context->pf_glUniformMatrix4fvARB = NULL; _context->pf_glDrawRangeElements = NULL; - + /* Init OpenGL state */ GE( glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) ); GE( glColorMask (TRUE, TRUE, TRUE, FALSE) ); @@ -124,7 +124,7 @@ cogl_create_context () /* Initialise the clip stack */ _cogl_clip_stack_state_init (); - + return TRUE; } @@ -147,7 +147,7 @@ cogl_destroy_context () g_array_free (_context->shader_handles, TRUE); if (_context->program_handles) g_array_free (_context->program_handles, TRUE); - + g_free (_context); } @@ -157,6 +157,6 @@ _cogl_context_get_default () /* Create if doesn't exist yet */ if (_context == NULL) cogl_create_context (); - + return _context; } diff --git a/gl/cogl-context.h b/gl/cogl-context.h index 8a2fc877d..172035d60 100644 --- a/gl/cogl-context.h +++ b/gl/cogl-context.h @@ -41,7 +41,7 @@ typedef struct /* Features cache */ CoglFeatureFlags feature_flags; gboolean features_cached; - + /* Enable cache */ gulong enable_flags; guint8 color_alpha; @@ -49,7 +49,7 @@ typedef struct COGLenum blend_dst_factor; gboolean enable_backface_culling; - + /* Primitives */ CoglFixedVec2 path_start; CoglFixedVec2 path_pen; @@ -60,12 +60,12 @@ typedef struct /* Cache of inverse projection matrix */ GLfloat inverse_projection[16]; - + /* Textures */ GArray *texture_handles; CoglTextureGLVertex *texture_vertices; gulong texture_vertices_size; - + /* Framebuffer objects */ GArray *fbo_handles; CoglBufferTarget draw_buffer; @@ -78,10 +78,10 @@ typedef struct /* Clip stack */ CoglClipStackState clip; - + /* Mesh */ GArray *mesh_handles; - + /* Relying on glext.h to define these */ COGL_PFNGLGENRENDERBUFFERSEXTPROC pf_glGenRenderbuffersEXT; COGL_PFNGLDELETERENDERBUFFERSEXTPROC pf_glDeleteRenderbuffersEXT; @@ -95,7 +95,7 @@ typedef struct COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC pf_glDeleteFramebuffersEXT; COGL_PFNGLBLITFRAMEBUFFEREXTPROC pf_glBlitFramebufferEXT; COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC pf_glRenderbufferStorageMultisampleEXT; - + COGL_PFNGLCREATEPROGRAMOBJECTARBPROC pf_glCreateProgramObjectARB; COGL_PFNGLCREATESHADEROBJECTARBPROC pf_glCreateShaderObjectARB; COGL_PFNGLSHADERSOURCEARBPROC pf_glShaderSourceARB; @@ -151,6 +151,6 @@ _cogl_context_get_default (); CoglContext *ctxvar = _cogl_context_get_default (); \ if (ctxvar == NULL) return retval; -#define NO_RETVAL +#define NO_RETVAL #endif /* __COGL_CONTEXT_H */ diff --git a/gl/cogl-texture.c b/gl/cogl-texture.c index 5a202ae6b..12caf7c58 100644 --- a/gl/cogl-texture.c +++ b/gl/cogl-texture.c @@ -76,7 +76,7 @@ _cogl_texture_bitmap_free (CoglTexture *tex) { if (tex->bitmap.data != NULL && tex->bitmap_owner) g_free (tex->bitmap.data); - + tex->bitmap.data = NULL; tex->bitmap_owner = FALSE; } @@ -87,7 +87,7 @@ _cogl_texture_bitmap_swap (CoglTexture *tex, { if (tex->bitmap.data != NULL && tex->bitmap_owner) g_free (tex->bitmap.data); - + tex->bitmap = *new_bitmap; tex->bitmap_owner = TRUE; } @@ -99,11 +99,11 @@ _cogl_span_iter_update (CoglSpanIter *iter) iter->span = &g_array_index (iter->array, CoglTexSliceSpan, iter->index); - + /* Offset next position by span size */ iter->next_pos = iter->pos + COGL_FIXED_FROM_INT (iter->span->size - iter->span->waste); - + /* Check if span intersects the area to cover */ if (iter->next_pos <= iter->cover_start || iter->pos >= iter->cover_end) @@ -112,15 +112,15 @@ _cogl_span_iter_update (CoglSpanIter *iter) iter->intersects = FALSE; return; } - + iter->intersects = TRUE; - + /* Clip start position to coverage area */ if (iter->pos < iter->cover_start) iter->intersect_start = iter->cover_start; else iter->intersect_start = iter->pos; - + /* Clip end position to coverage area */ if (iter->next_pos > iter->cover_end) iter->intersect_end = iter->cover_end; @@ -143,7 +143,7 @@ _cogl_span_iter_begin (CoglSpanIter *iter, iter->cover_start = cover_start; iter->cover_end = cover_end; iter->pos = iter->origin; - + /* Update intersection */ _cogl_span_iter_update (iter); } @@ -153,10 +153,10 @@ _cogl_span_iter_next (CoglSpanIter *iter) { /* Move current position */ iter->pos = iter->next_pos; - + /* Pick next slice (wrap when last reached) */ iter->index = (iter->index + 1) % iter->array->len; - + /* Update intersection */ _cogl_span_iter_update (iter); } @@ -175,10 +175,10 @@ prep_for_gl_pixels_upload (gint pixels_rowstride, gint pixels_bpp) { GE( glPixelStorei (GL_UNPACK_ROW_LENGTH, pixels_rowstride / pixels_bpp) ); - + GE( glPixelStorei (GL_UNPACK_SKIP_PIXELS, pixels_src_x) ); GE( glPixelStorei (GL_UNPACK_SKIP_ROWS, pixels_src_y) ); - + if (!(pixels_rowstride & 0x7)) GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 8) ); else if (!(pixels_rowstride & 0x3)) @@ -240,7 +240,7 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) gint bpp; gint x,y; guchar *waste_buf; - + bpp = _cogl_get_format_bpp (tex->bitmap.format); waste_buf = _cogl_texture_allocate_waste_buffer (tex); @@ -249,22 +249,22 @@ _cogl_texture_upload_to_gl (CoglTexture *tex) for (y = 0; y < tex->slice_y_spans->len; ++y) { y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, y); - + /* Iterate horizontal slices */ for (x = 0; x < tex->slice_x_spans->len; ++x) { x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x); - + /* Pick the gl texture object handle */ gl_handle = g_array_index (tex->slice_gl_handles, GLuint, y * tex->slice_x_spans->len + x); - + /* Setup gl alignment to match rowstride and top-left corner */ prep_for_gl_pixels_upload (tex->bitmap.rowstride, x_span->start, y_span->start, bpp); - + /* Upload new image data */ GE( glBindTexture (tex->gl_target, gl_handle) ); @@ -364,27 +364,27 @@ _cogl_texture_download_from_gl (CoglTexture *tex, gint bpp; gint x,y; CoglBitmap slice_bmp; - + bpp = _cogl_get_format_bpp (target_bmp->format); - + /* Iterate vertical slices */ for (y = 0; y < tex->slice_y_spans->len; ++y) { y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, y); - + /* Iterate horizontal slices */ for (x = 0; x < tex->slice_x_spans->len; ++x) { /*if (x != 0 || y != 1) continue;*/ x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x); - + /* Pick the gl texture object handle */ gl_handle = g_array_index (tex->slice_gl_handles, GLuint, y * tex->slice_x_spans->len + x); - + /* If there's any waste we need to copy manually (no glGetTexSubImage) */ - + if (y_span->waste != 0 || x_span->waste != 0) { /* Setup temp bitmap for slice subregion */ @@ -394,19 +394,19 @@ _cogl_texture_download_from_gl (CoglTexture *tex, slice_bmp.rowstride = bpp * slice_bmp.width; slice_bmp.data = (guchar*) g_malloc (slice_bmp.rowstride * slice_bmp.height); - + /* Setup gl alignment to 0,0 top-left corner */ prep_for_gl_pixels_download (slice_bmp.rowstride); - + /* Download slice image data into temp bmp */ GE( glBindTexture (tex->gl_target, gl_handle) ); - + GE (glGetTexImage (tex->gl_target, 0, /* level */ target_gl_format, target_gl_type, slice_bmp.data) ); - + /* Copy portion of slice from temp to target bmp */ _cogl_bitmap_copy_subregion (&slice_bmp, target_bmp, @@ -425,10 +425,10 @@ _cogl_texture_download_from_gl (CoglTexture *tex, + y_span->start * target_bmp->rowstride; prep_for_gl_pixels_download (target_bmp->rowstride); - + /* Download slice image data */ GE( glBindTexture (tex->gl_target, gl_handle) ); - + GE( glGetTexImage (tex->gl_target, 0, /* level */ target_gl_format, @@ -437,7 +437,7 @@ _cogl_texture_download_from_gl (CoglTexture *tex, } } } - + return TRUE; } @@ -463,7 +463,7 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, gint inter_w = 0, inter_h = 0; gint local_x = 0, local_y = 0; guchar *waste_buf; - + bpp = _cogl_get_format_bpp (source_bmp->format); waste_buf = _cogl_texture_allocate_waste_buffer (tex); @@ -473,9 +473,9 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, _cogl_span_iter_begin (&y_iter, tex->slice_y_spans, 0, COGL_FIXED_FROM_INT (dst_y), COGL_FIXED_FROM_INT (dst_y + height)); - + !_cogl_span_iter_end (&y_iter); - + _cogl_span_iter_next (&y_iter), source_y += inter_h ) { @@ -494,9 +494,9 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, _cogl_span_iter_begin (&x_iter, tex->slice_x_spans, 0, COGL_FIXED_FROM_INT (dst_x), COGL_FIXED_FROM_INT (dst_x + width)); - + !_cogl_span_iter_end (&x_iter); - + _cogl_span_iter_next (&x_iter), source_x += inter_w ) { @@ -515,27 +515,27 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex, x_iter.intersect_start); inter_h = COGL_FIXED_TO_INT (y_iter.intersect_end - y_iter.intersect_start); - + /* Localize intersection top-left corner to slice*/ local_x = COGL_FIXED_TO_INT (x_iter.intersect_start - x_iter.pos); local_y = COGL_FIXED_TO_INT (y_iter.intersect_start - y_iter.pos); - + /* Pick slice GL handle */ gl_handle = g_array_index (tex->slice_gl_handles, GLuint, y_iter.index * tex->slice_x_spans->len + x_iter.index); - + /* Setup gl alignment to match rowstride and top-left corner */ prep_for_gl_pixels_upload (source_bmp->rowstride, source_x, source_y, bpp); - + /* Upload new image data */ GE( glBindTexture (tex->gl_target, gl_handle) ); - + GE( glTexSubImage2D (tex->gl_target, 0, local_x, local_y, inter_w, inter_h, @@ -657,12 +657,12 @@ _cogl_rect_slices_for_size (gint size_to_fill, { gint n_spans = 0; CoglTexSliceSpan span; - + /* Init first slice span */ span.start = 0; span.size = max_span_size; span.waste = 0; - + /* Repeat until whole area covered */ while (size_to_fill >= span.size) { @@ -672,7 +672,7 @@ _cogl_rect_slices_for_size (gint size_to_fill, size_to_fill -= span.size; n_spans++; } - + /* Add one last smaller slice span */ if (size_to_fill > 0) { @@ -680,7 +680,7 @@ _cogl_rect_slices_for_size (gint size_to_fill, if (out_spans) g_array_append_val (out_spans, span); n_spans++; } - + return n_spans; } @@ -692,15 +692,15 @@ _cogl_pot_slices_for_size (gint size_to_fill, { gint n_spans = 0; CoglTexSliceSpan span; - + /* Init first slice span */ span.start = 0; span.size = max_span_size; span.waste = 0; - + /* Fix invalid max_waste */ if (max_waste < 0) max_waste = 0; - + while (TRUE) { /* Is the whole area covered? */ @@ -729,7 +729,7 @@ _cogl_pot_slices_for_size (gint size_to_fill, } } } - + /* Can't get here */ return 0; } @@ -744,7 +744,7 @@ _cogl_texture_size_supported (GLenum gl_target, if (gl_target == GL_TEXTURE_2D) { /* Proxy texture allows for a quick check for supported size */ - + GLint new_width = 0; GE( glTexImage2D (GL_PROXY_TEXTURE_2D, 0, GL_RGBA, @@ -788,7 +788,7 @@ _cogl_texture_set_wrap_mode_parameter (CoglTexture *tex, static gboolean _cogl_texture_slices_create (CoglTexture *tex) -{ +{ gint bpp; gint max_width; gint max_height; @@ -800,11 +800,11 @@ _cogl_texture_slices_create (CoglTexture *tex) CoglTexSliceSpan *x_span; CoglTexSliceSpan *y_span; const GLfloat transparent_color[4] = { 0x00, 0x00, 0x00, 0x00 }; - + gint (*slices_for_size) (gint, gint, gint, GArray*); - + bpp = _cogl_get_format_bpp (tex->bitmap.format); - + /* Initialize size of largest slice according to supported features */ if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT)) { @@ -820,12 +820,12 @@ _cogl_texture_slices_create (CoglTexture *tex) tex->gl_target = GL_TEXTURE_2D; slices_for_size = _cogl_pot_slices_for_size; } - + /* Negative number means no slicing forced by the user */ if (tex->max_waste <= -1) { CoglTexSliceSpan span; - + /* Check if size supported else bail out */ if (!_cogl_texture_size_supported (tex->gl_target, tex->gl_format, @@ -835,25 +835,25 @@ _cogl_texture_slices_create (CoglTexture *tex) { return FALSE; } - + n_x_slices = 1; n_y_slices = 1; - - /* Init span arrays */ + + /* Init span arrays */ tex->slice_x_spans = g_array_sized_new (FALSE, FALSE, sizeof (CoglTexSliceSpan), 1); - + tex->slice_y_spans = g_array_sized_new (FALSE, FALSE, sizeof (CoglTexSliceSpan), 1); - + /* Add a single span for width and height */ span.start = 0; span.size = max_width; span.waste = max_width - tex->bitmap.width; g_array_append_val (tex->slice_x_spans, span); - + span.size = max_height; span.waste = max_height - tex->bitmap.height; g_array_append_val (tex->slice_y_spans, span); @@ -872,46 +872,46 @@ _cogl_texture_slices_create (CoglTexture *tex) max_width /= 2; else max_height /= 2; - + if (max_width == 0 || max_height == 0) return FALSE; } - + /* Determine the slices required to cover the bitmap area */ n_x_slices = slices_for_size (tex->bitmap.width, max_width, tex->max_waste, NULL); - + n_y_slices = slices_for_size (tex->bitmap.height, max_height, tex->max_waste, NULL); - + /* Init span arrays with reserved size */ tex->slice_x_spans = g_array_sized_new (FALSE, FALSE, sizeof (CoglTexSliceSpan), n_x_slices); - + tex->slice_y_spans = g_array_sized_new (FALSE, FALSE, sizeof (CoglTexSliceSpan), n_y_slices); - + /* Fill span arrays with info */ slices_for_size (tex->bitmap.width, max_width, tex->max_waste, tex->slice_x_spans); - + slices_for_size (tex->bitmap.height, max_height, tex->max_waste, tex->slice_y_spans); } - + /* Init and resize GL handle array */ n_slices = n_x_slices * n_y_slices; - + tex->slice_gl_handles = g_array_sized_new (FALSE, FALSE, sizeof (GLuint), n_slices); - + g_array_set_size (tex->slice_gl_handles, n_slices); /* Wrap mode not yet set */ @@ -921,19 +921,19 @@ _cogl_texture_slices_create (CoglTexture *tex) * (some implementations might supported faster * re-binding between textures inside a set) */ gl_handles = (GLuint*) tex->slice_gl_handles->data; - + GE( glGenTextures (n_slices, gl_handles) ); - - + + /* Init each GL texture object */ for (y = 0; y < n_y_slices; ++y) { y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, y); - + for (x = 0; x < n_x_slices; ++x) { x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x); - + #if COGL_DEBUG printf ("CREATE SLICE (%d,%d)\n", x,y); printf ("size: (%d x %d)\n", @@ -964,19 +964,19 @@ _cogl_texture_slices_create (CoglTexture *tex) tex->gl_format, tex->gl_type, 0) ); } } - + return TRUE; } static void _cogl_texture_slices_free (CoglTexture *tex) -{ +{ if (tex->slice_x_spans != NULL) g_array_free (tex->slice_x_spans, TRUE); - + if (tex->slice_y_spans != NULL) g_array_free (tex->slice_y_spans, TRUE); - + if (tex->slice_gl_handles != NULL) { if (tex->is_foreign == FALSE) @@ -984,7 +984,7 @@ _cogl_texture_slices_free (CoglTexture *tex) GE( glDeleteTextures (tex->slice_gl_handles->len, (GLuint*) tex->slice_gl_handles->data) ); } - + g_array_free (tex->slice_gl_handles, TRUE); } } @@ -998,34 +998,34 @@ _cogl_pixel_format_from_gl_internal (GLenum gl_int_format, is re-matched against cogl when getting or setting texture image data. */ - + switch (gl_int_format) { case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8: case GL_ALPHA12: case GL_ALPHA16: - + *out_format = COGL_PIXEL_FORMAT_A_8; return TRUE; - + case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8: case GL_LUMINANCE12: case GL_LUMINANCE16: - + *out_format = COGL_PIXEL_FORMAT_G_8; return TRUE; - + case GL_RGB: case GL_RGB4: case GL_RGB5: case GL_RGB8: case GL_RGB10: case GL_RGB12: case GL_RGB16: case GL_R3_G3_B2: - + *out_format = COGL_PIXEL_FORMAT_RGB_888; return TRUE; - + case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGB5_A1: case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16: - + *out_format = COGL_PIXEL_FORMAT_RGBA_8888; return TRUE; } - + return FALSE; } @@ -1039,17 +1039,17 @@ _cogl_pixel_format_to_gl (CoglPixelFormat format, GLenum glintformat = 0; GLenum glformat = 0; GLenum gltype = 0; - + /* No premultiplied formats accepted by GL * (FIXME: latest hardware?) */ - + if (format & COGL_PREMULT_BIT) format = (format & COGL_UNPREMULT_MASK); - + /* Everything else accepted * (FIXME: check YUV support) */ required_format = format; - + /* Find GL equivalents */ switch (format) { @@ -1063,7 +1063,7 @@ _cogl_pixel_format_to_gl (CoglPixelFormat format, glformat = GL_LUMINANCE; gltype = GL_UNSIGNED_BYTE; break; - + case COGL_PIXEL_FORMAT_RGB_888: glintformat = GL_RGB; glformat = GL_RGB; @@ -1084,7 +1084,7 @@ _cogl_pixel_format_to_gl (CoglPixelFormat format, glformat = GL_BGRA; gltype = GL_UNSIGNED_BYTE; break; - + /* The following two types of channel ordering * have no GL equivalent unless defined using * system word byte ordering */ @@ -1097,7 +1097,7 @@ _cogl_pixel_format_to_gl (CoglPixelFormat format, gltype = GL_UNSIGNED_INT_8_8_8_8_REV; #endif break; - + case COGL_PIXEL_FORMAT_ABGR_8888: glintformat = GL_RGBA; glformat = GL_RGBA; @@ -1107,7 +1107,7 @@ _cogl_pixel_format_to_gl (CoglPixelFormat format, gltype = GL_UNSIGNED_INT_8_8_8_8_REV; #endif break; - + /* The following three types of channel ordering * are always defined using system word byte * ordering (even according to GLES spec) */ @@ -1126,19 +1126,19 @@ _cogl_pixel_format_to_gl (CoglPixelFormat format, glformat = GL_RGBA; gltype = GL_UNSIGNED_SHORT_5_5_5_1; break; - + /* FIXME: check extensions for YUV support */ default: break; } - + if (out_glintformat != NULL) *out_glintformat = glintformat; if (out_glformat != NULL) *out_glformat = glformat; if (out_gltype != NULL) *out_gltype = gltype; - + return required_format; } @@ -1149,7 +1149,7 @@ _cogl_texture_bitmap_prepare (CoglTexture *tex, CoglBitmap new_bitmap; CoglPixelFormat new_data_format; gboolean success; - + /* Was there any internal conversion requested? */ if (internal_format == COGL_PIXEL_FORMAT_ANY) internal_format = tex->bitmap.format; @@ -1159,21 +1159,21 @@ _cogl_texture_bitmap_prepare (CoglTexture *tex, &tex->gl_intformat, &tex->gl_format, &tex->gl_type); - + /* Convert to internal format */ if (new_data_format != tex->bitmap.format) { success = _cogl_bitmap_convert_and_premult (&tex->bitmap, &new_bitmap, new_data_format); - + if (!success) return FALSE; - + /* Update texture with new data */ _cogl_texture_bitmap_swap (tex, &new_bitmap); } - + return TRUE; } @@ -1197,15 +1197,15 @@ cogl_texture_new_with_size (guint width, CoglTexture *tex; gint bpp; gint rowstride; - + /* Since no data, we need some internal format */ if (internal_format == COGL_PIXEL_FORMAT_ANY) return COGL_INVALID_HANDLE; - + /* Rowstride from width */ bpp = _cogl_get_format_bpp (internal_format); rowstride = width * bpp; - + /* Init texture with empty bitmap */ tex = (CoglTexture*) g_malloc (sizeof (CoglTexture)); @@ -1214,36 +1214,36 @@ cogl_texture_new_with_size (guint width, tex->is_foreign = FALSE; tex->auto_mipmap = auto_mipmap; - + tex->bitmap.width = width; tex->bitmap.height = height; tex->bitmap.format = internal_format; tex->bitmap.rowstride = rowstride; tex->bitmap.data = NULL; tex->bitmap_owner = FALSE; - + tex->slice_x_spans = NULL; tex->slice_y_spans = NULL; tex->slice_gl_handles = NULL; - + tex->max_waste = max_waste; tex->min_filter = CGL_NEAREST; tex->mag_filter = CGL_NEAREST; - + /* Find closest GL format match */ tex->bitmap.format = _cogl_pixel_format_to_gl (internal_format, &tex->gl_intformat, &tex->gl_format, &tex->gl_type); - + /* Create slices for the given format and size */ if (!_cogl_texture_slices_create (tex)) { _cogl_texture_free (tex); return COGL_INVALID_HANDLE; } - + return _cogl_texture_handle_new (tex); } @@ -1259,20 +1259,20 @@ cogl_texture_new_from_data (guint width, { CoglTexture *tex; gint bpp; - + if (format == COGL_PIXEL_FORMAT_ANY) return COGL_INVALID_HANDLE; - + if (data == NULL) return COGL_INVALID_HANDLE; - + /* Rowstride from width if not given */ bpp = _cogl_get_format_bpp (format); if (rowstride == 0) rowstride = width * bpp; - + /* Create new texture and fill with given data */ tex = (CoglTexture*) g_malloc (sizeof (CoglTexture)); - + tex->ref_count = 1; COGL_HANDLE_DEBUG_NEW (texture, tex); @@ -1285,40 +1285,40 @@ cogl_texture_new_from_data (guint width, tex->bitmap.format = format; tex->bitmap.rowstride = rowstride; tex->bitmap_owner = FALSE; - + tex->slice_x_spans = NULL; tex->slice_y_spans = NULL; tex->slice_gl_handles = NULL; - + tex->max_waste = max_waste; tex->min_filter = CGL_NEAREST; tex->mag_filter = CGL_NEAREST; - + /* FIXME: If upload fails we should set some kind of * error flag but still return texture handle (this * is to keep the behavior equal to _new_from_file; * see below) */ - + if (!_cogl_texture_bitmap_prepare (tex, internal_format)) { _cogl_texture_free (tex); return COGL_INVALID_HANDLE; } - + if (!_cogl_texture_slices_create (tex)) { _cogl_texture_free (tex); return COGL_INVALID_HANDLE; } - + if (!_cogl_texture_upload_to_gl (tex)) { _cogl_texture_free (tex); return COGL_INVALID_HANDLE; } - + _cogl_texture_bitmap_free (tex); - + return _cogl_texture_handle_new (tex); } @@ -1331,7 +1331,7 @@ cogl_texture_new_from_file (const gchar *filename, { CoglBitmap bmp; CoglTexture *tex; - + g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE); /* Try loading with imaging backend */ @@ -1346,27 +1346,27 @@ cogl_texture_new_from_file (const gchar *filename, *error = NULL; } } - + /* Create new texture and fill with loaded data */ tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture)); - + tex->ref_count = 1; COGL_HANDLE_DEBUG_NEW (texture, tex); - + tex->is_foreign = FALSE; tex->auto_mipmap = auto_mipmap; tex->bitmap = bmp; tex->bitmap_owner = TRUE; - + tex->slice_x_spans = NULL; tex->slice_y_spans = NULL; tex->slice_gl_handles = NULL; - + tex->max_waste = max_waste; tex->min_filter = CGL_NEAREST; tex->mag_filter = CGL_NEAREST; - + /* FIXME: If upload fails we should set some kind of * error flag but still return texture handle if the * user decides to destroy another texture and upload @@ -1374,27 +1374,27 @@ cogl_texture_new_from_file (const gchar *filename, * in that case). As a rule then, everytime a valid * CoglHandle is returned, it should also be destroyed * with cogl_texture_unref at some point! */ - + if (!_cogl_texture_bitmap_prepare (tex, internal_format)) { _cogl_texture_free (tex); return COGL_INVALID_HANDLE; } - + if (!_cogl_texture_slices_create (tex)) { _cogl_texture_free (tex); return COGL_INVALID_HANDLE; } - + if (!_cogl_texture_upload_to_gl (tex)) { _cogl_texture_free (tex); return COGL_INVALID_HANDLE; } - + _cogl_texture_bitmap_free (tex); - + return _cogl_texture_handle_new (tex); } @@ -1413,7 +1413,7 @@ cogl_texture_new_from_foreign (GLuint gl_handle, robustness and for completeness in case one day GLES gains support for them. */ - + GLenum gl_error = 0; GLboolean gl_istexture; GLint gl_compressed = GL_FALSE; @@ -1448,23 +1448,23 @@ cogl_texture_new_from_foreign (GLuint gl_handle, glBindTexture (gl_target, gl_handle); if (glGetError () != GL_NO_ERROR) return COGL_INVALID_HANDLE; - + /* Obtain texture parameters (only level 0 we are interested in) */ - + GE( glGetTexLevelParameteriv (gl_target, 0, GL_TEXTURE_COMPRESSED, &gl_compressed) ); - + GE( glGetTexLevelParameteriv (gl_target, 0, GL_TEXTURE_INTERNAL_FORMAT, &gl_int_format) ); - + GE( glGetTexLevelParameteriv (gl_target, 0, GL_TEXTURE_WIDTH, &gl_width) ); - + GE( glGetTexLevelParameteriv (gl_target, 0, GL_TEXTURE_HEIGHT, &gl_height) ); @@ -1472,57 +1472,57 @@ cogl_texture_new_from_foreign (GLuint gl_handle, GE( glGetTexParameteriv (gl_target, GL_TEXTURE_MIN_FILTER, &gl_min_filter) ); - + GE( glGetTexParameteriv (gl_target, GL_TEXTURE_MAG_FILTER, &gl_mag_filter) ); - + GE( glGetTexParameteriv (gl_target, GL_GENERATE_MIPMAP, &gl_gen_mipmap) ); - + /* Validate width and height */ if (gl_width <= 0 || gl_height <= 0) return COGL_INVALID_HANDLE; - + /* Validate pot waste */ if (x_pot_waste < 0 || x_pot_waste >= gl_width || y_pot_waste < 0 || y_pot_waste >= gl_height) return COGL_INVALID_HANDLE; - + /* Compressed texture images not supported */ if (gl_compressed == GL_TRUE) return COGL_INVALID_HANDLE; - + /* Try and match to a cogl format */ if (!_cogl_pixel_format_from_gl_internal (gl_int_format, &format)) { return COGL_INVALID_HANDLE; } - + /* Create new texture */ tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture)); - + tex->ref_count = 1; COGL_HANDLE_DEBUG_NEW (texture, tex); - + /* Setup bitmap info */ tex->is_foreign = TRUE; tex->auto_mipmap = (gl_gen_mipmap == GL_TRUE) ? TRUE : FALSE; - + bpp = _cogl_get_format_bpp (format); tex->bitmap.format = format; tex->bitmap.width = gl_width - x_pot_waste; tex->bitmap.height = gl_height - y_pot_waste; tex->bitmap.rowstride = tex->bitmap.width * bpp; tex->bitmap_owner = FALSE; - + tex->gl_target = gl_target; tex->gl_intformat = gl_int_format; tex->gl_format = gl_int_format; tex->gl_type = GL_UNSIGNED_BYTE; - + tex->min_filter = gl_min_filter; tex->mag_filter = gl_mag_filter; tex->max_waste = 0; @@ -1534,26 +1534,26 @@ cogl_texture_new_from_foreign (GLuint gl_handle, tex->slice_x_spans = g_array_sized_new (FALSE, FALSE, sizeof (CoglTexSliceSpan), 1); - + tex->slice_y_spans = g_array_sized_new (FALSE, FALSE, sizeof (CoglTexSliceSpan), 1); - + tex->slice_gl_handles = g_array_sized_new (FALSE, FALSE, sizeof (GLuint), 1); - + /* Store info for a single slice */ x_span.start = 0; x_span.size = gl_width; x_span.waste = x_pot_waste; g_array_append_val (tex->slice_x_spans, x_span); - + y_span.start = 0; y_span.size = gl_height; y_span.waste = y_pot_waste; g_array_append_val (tex->slice_y_spans, y_span); - + g_array_append_val (tex->slice_gl_handles, gl_handle); return _cogl_texture_handle_new (tex); @@ -1563,12 +1563,12 @@ guint cogl_texture_get_width (CoglHandle handle) { CoglTexture *tex; - + if (!cogl_is_texture (handle)) return 0; - + tex = _cogl_texture_pointer_from_handle (handle); - + return tex->bitmap.width; } @@ -1576,12 +1576,12 @@ guint cogl_texture_get_height (CoglHandle handle) { CoglTexture *tex; - + if (!cogl_is_texture (handle)) return 0; - + tex = _cogl_texture_pointer_from_handle (handle); - + return tex->bitmap.height; } @@ -1589,12 +1589,12 @@ CoglPixelFormat cogl_texture_get_format (CoglHandle handle) { CoglTexture *tex; - + if (!cogl_is_texture (handle)) return COGL_PIXEL_FORMAT_ANY; - + tex = _cogl_texture_pointer_from_handle (handle); - + return tex->bitmap.format; } @@ -1602,12 +1602,12 @@ guint cogl_texture_get_rowstride (CoglHandle handle) { CoglTexture *tex; - + if (!cogl_is_texture (handle)) return 0; - + tex = _cogl_texture_pointer_from_handle (handle); - + return tex->bitmap.rowstride; } @@ -1615,12 +1615,12 @@ gint cogl_texture_get_max_waste (CoglHandle handle) { CoglTexture *tex; - + if (!cogl_is_texture (handle)) return 0; - + tex = _cogl_texture_pointer_from_handle (handle); - + return tex->max_waste; } @@ -1628,18 +1628,18 @@ gboolean cogl_texture_is_sliced (CoglHandle handle) { CoglTexture *tex; - + if (!cogl_is_texture (handle)) return FALSE; - + tex = _cogl_texture_pointer_from_handle (handle); - + if (tex->slice_gl_handles == NULL) return FALSE; - + if (tex->slice_gl_handles->len <= 1) return FALSE; - + return TRUE; } @@ -1649,24 +1649,24 @@ cogl_texture_get_gl_texture (CoglHandle handle, GLenum *out_gl_target) { CoglTexture *tex; - + if (!cogl_is_texture (handle)) return FALSE; - + tex = _cogl_texture_pointer_from_handle (handle); - + if (tex->slice_gl_handles == NULL) return FALSE; - + if (tex->slice_gl_handles->len < 1) return FALSE; - + if (out_gl_handle != NULL) *out_gl_handle = g_array_index (tex->slice_gl_handles, GLuint, 0); - + if (out_gl_target != NULL) *out_gl_target = tex->gl_target; - + return TRUE; } @@ -1674,12 +1674,12 @@ COGLenum cogl_texture_get_min_filter (CoglHandle handle) { CoglTexture *tex; - + if (!cogl_is_texture (handle)) return 0; - + tex = _cogl_texture_pointer_from_handle (handle); - + return tex->min_filter; } @@ -1687,12 +1687,12 @@ COGLenum cogl_texture_get_mag_filter (CoglHandle handle) { CoglTexture *tex; - + if (!cogl_is_texture (handle)) return 0; - + tex = _cogl_texture_pointer_from_handle (handle); - + return tex->mag_filter; } @@ -1704,20 +1704,20 @@ cogl_texture_set_filters (CoglHandle handle, CoglTexture *tex; GLuint gl_handle; int i; - + if (!cogl_is_texture (handle)) return; - + tex = _cogl_texture_pointer_from_handle (handle); - + /* Store new values */ tex->min_filter = min_filter; tex->mag_filter = mag_filter; - + /* Make sure slices were created */ if (tex->slice_gl_handles == NULL) return; - + /* Apply new filters to every slice */ for (i=0; islice_gl_handles->len; ++i) { @@ -1753,37 +1753,37 @@ cogl_texture_set_region (CoglHandle handle, GLenum closest_gl_format; GLenum closest_gl_type; gboolean success; - + /* Check if valid texture handle */ if (!cogl_is_texture (handle)) return FALSE; - + tex = _cogl_texture_pointer_from_handle (handle); - + /* Check for valid format */ if (format == COGL_PIXEL_FORMAT_ANY) return FALSE; - + /* Shortcut out early if the image is empty */ if (width == 0 || height == 0) return TRUE; - + /* Init source bitmap */ source_bmp.width = width; source_bmp.height = height; source_bmp.format = format; source_bmp.data = (guchar*)data; - + /* Rowstride from width if none specified */ bpp = _cogl_get_format_bpp (format); source_bmp.rowstride = (rowstride == 0) ? width * bpp : rowstride; - + /* Find closest format to internal that's supported by GL */ closest_format = _cogl_pixel_format_to_gl (tex->bitmap.format, NULL, /* don't need */ &closest_gl_format, &closest_gl_type); - + /* If no direct match, convert */ if (closest_format != format) { @@ -1791,13 +1791,13 @@ cogl_texture_set_region (CoglHandle handle, success = _cogl_bitmap_convert_and_premult (&source_bmp, &temp_bmp, closest_format); - + /* Swap bitmaps if succeeded */ if (!success) return FALSE; source_bmp = temp_bmp; source_bmp_owner = TRUE; } - + /* Send data to GL */ _cogl_texture_upload_subregion_to_gl (tex, src_x, src_y, @@ -1806,11 +1806,11 @@ cogl_texture_set_region (CoglHandle handle, &source_bmp, closest_gl_format, closest_gl_type); - + /* Free data if owner */ if (source_bmp_owner) g_free (source_bmp.data); - + return TRUE; } @@ -1833,33 +1833,33 @@ cogl_texture_get_data (CoglHandle handle, guchar *src; guchar *dst; gint y; - + /* Check if valid texture handle */ if (!cogl_is_texture (handle)) return 0; - + tex = _cogl_texture_pointer_from_handle (handle); - + /* Default to internal format if none specified */ if (format == COGL_PIXEL_FORMAT_ANY) format = tex->bitmap.format; - + /* Rowstride from texture width if none specified */ bpp = _cogl_get_format_bpp (format); if (rowstride == 0) rowstride = tex->bitmap.width * bpp; - + /* Return byte size if only that requested */ byte_size = tex->bitmap.height * rowstride; if (data == NULL) return byte_size; - + /* Find closest format that's supported by GL */ closest_format = _cogl_pixel_format_to_gl (format, NULL, /* don't need */ &closest_gl_format, &closest_gl_type); - + closest_bpp = _cogl_get_format_bpp (closest_format); - + /* Is the requested format supported? */ if (closest_format == format) { @@ -1878,12 +1878,12 @@ cogl_texture_get_data (CoglHandle handle, target_bmp.data = (guchar*) g_malloc (target_bmp.height * target_bmp.rowstride); } - + /* Retrieve data from slices */ _cogl_texture_download_from_gl (tex, &target_bmp, closest_gl_format, closest_gl_type); - + /* Was intermediate used? */ if (closest_format != format) { @@ -1891,11 +1891,11 @@ cogl_texture_get_data (CoglHandle handle, success = _cogl_bitmap_convert_and_premult (&target_bmp, &new_bmp, format); - + /* Free intermediate data and return if failed */ g_free (target_bmp.data); if (!success) return 0; - + /* Copy to user buffer */ for (y = 0; y < new_bmp.height; ++y) { @@ -1903,11 +1903,11 @@ cogl_texture_get_data (CoglHandle handle, dst = data + y * rowstride; memcpy (dst, src, new_bmp.width); } - + /* Free converted data */ g_free (new_bmp.data); } - + return byte_size; } @@ -1936,7 +1936,7 @@ _cogl_texture_quad_sw (CoglTexture *tex, GLuint gl_handle; gulong enable_flags = (COGL_ENABLE_VERTEX_ARRAY | COGL_ENABLE_TEXCOORD_ARRAY); - + _COGL_GET_CONTEXT (ctx, NO_RETVAL); #if COGL_DEBUG @@ -1986,21 +1986,21 @@ _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); - + tqx = COGL_FIXED_DIV (x2 - x1, COGL_FIXED_MUL (tw, (tx2 - tx1))); tqy = COGL_FIXED_DIV (y2 - y1, COGL_FIXED_MUL (th, (ty2 - ty1))); /* Integral texture coordinate for first tile */ first_tx = COGL_FIXED_FROM_INT (COGL_FIXED_FLOOR (tx1)); first_ty = COGL_FIXED_FROM_INT (COGL_FIXED_FLOOR (ty1)); - + /* Denormalize texture coordinates */ first_tx = COGL_FIXED_MUL (first_tx, tw); first_ty = COGL_FIXED_MUL (first_ty, th); @@ -2012,21 +2012,21 @@ _cogl_texture_quad_sw (CoglTexture *tex, /* Quad coordinate of the first tile */ first_qx = x1 - COGL_FIXED_MUL (tx1 - first_tx, tqx); first_qy = y1 - COGL_FIXED_MUL (ty1 - first_ty, tqy); - - + + /* Iterate until whole quad height covered */ for (_cogl_span_iter_begin (&iter_y, tex->slice_y_spans, first_ty, ty1, ty2) ; !_cogl_span_iter_end (&iter_y) ; _cogl_span_iter_next (&iter_y) ) - { + { /* Discard slices out of quad early */ if (!iter_y.intersects) continue; - + /* Span-quad intersection in quad coordinates */ slice_qy1 = first_qy + COGL_FIXED_MUL (iter_y.intersect_start - first_ty, tqy); - + slice_qy2 = first_qy + COGL_FIXED_MUL (iter_y.intersect_end - first_ty, tqy); @@ -2050,14 +2050,14 @@ _cogl_texture_quad_sw (CoglTexture *tex, { /* Discard slices out of quad early */ if (!iter_x.intersects) continue; - + /* Span-quad intersection in quad coordinates */ slice_qx1 = first_qx + COGL_FIXED_MUL (iter_x.intersect_start - first_tx, tqx); - + slice_qx2 = first_qx + COGL_FIXED_MUL (iter_x.intersect_end - first_tx, tqx); - + /* Localize slice texture coordinates */ slice_tx1 = iter_x.intersect_start - iter_x.pos; slice_tx2 = iter_x.intersect_end - iter_x.pos; @@ -2081,16 +2081,16 @@ _cogl_texture_quad_sw (CoglTexture *tex, printf("tx2: %f\n", COGL_FIXED_TO_FLOAT (slice_tx2)); printf("ty2: %f\n", COGL_FIXED_TO_FLOAT (slice_ty2)); #endif - + /* Pick and bind opengl texture object */ 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); @@ -2131,9 +2131,9 @@ _cogl_texture_quad_hw (CoglTexture *tex, #if COGL_DEBUG printf("=== Drawing Tex Quad (Hardware Tiling Mode) ===\n"); #endif - + _COGL_GET_CONTEXT (ctx, NO_RETVAL); - + /* Prepare GL state */ if (tex->gl_target == CGL_TEXTURE_RECTANGLE_ARB) enable_flags |= COGL_ENABLE_TEXTURE_RECT; @@ -2145,7 +2145,7 @@ _cogl_texture_quad_hw (CoglTexture *tex, { enable_flags |= COGL_ENABLE_BLEND; } - + if (ctx->enable_backface_culling) enable_flags |= COGL_ENABLE_BACKFACE_CULLING; @@ -2165,11 +2165,11 @@ _cogl_texture_quad_hw (CoglTexture *tex, GE( glTexCoordPointer (2, GL_FLOAT, 0, tex_coords) ); GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords) ); - + /* Pick and bind opengl texture object */ gl_handle = g_array_index (tex->slice_gl_handles, GLuint, 0); GE( glBindTexture (tex->gl_target, 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); @@ -2219,22 +2219,22 @@ cogl_texture_rectangle (CoglHandle handle, CoglFixed ty2) { CoglTexture *tex; - + /* Check if valid texture */ if (!cogl_is_texture (handle)) return; - + 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; @@ -2302,20 +2302,20 @@ cogl_texture_polygon (CoglHandle handle, 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; ctx->texture_vertices = g_realloc (ctx->texture_vertices, nsize * sizeof (CoglTextureGLVertex)); } - + /* Prepare GL state */ enable_flags = (COGL_ENABLE_VERTEX_ARRAY | COGL_ENABLE_TEXCOORD_ARRAY