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.
This commit is contained in:
Neil Roberts 2008-11-28 12:33:19 +00:00
parent 93ea1681bb
commit 10942e8e04
2 changed files with 119 additions and 89 deletions

View File

@ -65,6 +65,11 @@ typedef struct
/* Textures */ /* Textures */
GArray *texture_handles; GArray *texture_handles;
GArray *texture_vertices; 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 */ /* Framebuffer objects */
GArray *fbo_handles; GArray *fbo_handles;

View File

@ -1906,6 +1906,28 @@ cogl_texture_get_data (CoglHandle handle,
return byte_size; 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 static void
_cogl_texture_quad_sw (CoglTexture *tex, _cogl_texture_quad_sw (CoglTexture *tex,
CoglFixed x1, CoglFixed x1,
@ -1917,21 +1939,17 @@ _cogl_texture_quad_sw (CoglTexture *tex,
CoglFixed tx2, CoglFixed tx2,
CoglFixed ty2) CoglFixed ty2)
{ {
CoglSpanIter iter_x , iter_y; CoglSpanIter iter_x , iter_y;
CoglFixed tw , th; CoglFixed tw , th;
CoglFixed tqx , tqy; CoglFixed tqx , tqy;
CoglFixed first_tx , first_ty; CoglFixed first_tx , first_ty;
CoglFixed first_qx , first_qy; CoglFixed first_qx , first_qy;
CoglFixed slice_tx1 , slice_ty1; CoglFixed slice_tx1 , slice_ty1;
CoglFixed slice_tx2 , slice_ty2; CoglFixed slice_tx2 , slice_ty2;
CoglFixed slice_qx1 , slice_qy1; CoglFixed slice_qx1 , slice_qy1;
CoglFixed slice_qx2 , slice_qy2; CoglFixed slice_qx2 , slice_qy2;
GLfloat tex_coords[8]; GLuint gl_handle;
GLfloat quad_coords[8]; CoglTextureGLVertex *p;
GLuint gl_handle;
gulong enable_flags = (COGL_ENABLE_TEXTURE_2D
| COGL_ENABLE_VERTEX_ARRAY
| COGL_ENABLE_TEXCOORD_ARRAY);
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -1939,19 +1957,6 @@ _cogl_texture_quad_sw (CoglTexture *tex,
printf("=== Drawing Tex Quad (Software Tiling Mode) ===\n"); printf("=== Drawing Tex Quad (Software Tiling Mode) ===\n");
#endif #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 /* If the texture coordinates are backwards then swap both the
geometry and texture coordinates so that the texture will be geometry and texture coordinates so that the texture will be
flipped but we can still use the same algorithm to iterate the flipped but we can still use the same algorithm to iterate the
@ -1975,9 +1980,6 @@ _cogl_texture_quad_sw (CoglTexture *tex,
ty2 = temp; 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 */ /* Scale ratio from texture to quad widths */
tw = COGL_FIXED_FROM_INT (tex->bitmap.width); tw = COGL_FIXED_FROM_INT (tex->bitmap.width);
th = COGL_FIXED_FROM_INT (tex->bitmap.height); th = COGL_FIXED_FROM_INT (tex->bitmap.height);
@ -2070,22 +2072,34 @@ _cogl_texture_quad_sw (CoglTexture *tex,
iter_y.index * iter_x.array->len + iter_y.index * iter_x.array->len +
iter_x.index); iter_x.index);
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;
#define CFX_F COGL_FIXED_TO_FLOAT /* 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);
/* Draw textured quad */ #define CFX_F(x) COGL_FIXED_TO_FLOAT(x)
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);
quad_coords[0] = CFX_F(slice_qx1); quad_coords[1] = CFX_F(slice_qy2); p->v[0] = CFX_F (slice_qx1); p->v[1] = CFX_F (slice_qy2);
quad_coords[2] = CFX_F(slice_qx2); quad_coords[3] = CFX_F(slice_qy2); p->t[0] = CFX_F (slice_tx1); p->t[1] = CFX_F (slice_ty2);
quad_coords[4] = CFX_F(slice_qx1); quad_coords[5] = CFX_F(slice_qy1); p++;
quad_coords[6] = CFX_F(slice_qx2); quad_coords[7] = CFX_F(slice_qy1); 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);
GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); 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 #undef CFX_F
} }
@ -2103,14 +2117,10 @@ _cogl_texture_quad_hw (CoglTexture *tex,
CoglFixed tx2, CoglFixed tx2,
CoglFixed ty2) CoglFixed ty2)
{ {
GLfloat tex_coords[8]; GLuint gl_handle;
GLfloat quad_coords[8]; CoglTexSliceSpan *x_span;
GLuint gl_handle; CoglTexSliceSpan *y_span;
CoglTexSliceSpan *x_span; CoglTextureGLVertex *p;
CoglTexSliceSpan *y_span;
gulong enable_flags = (COGL_ENABLE_TEXTURE_2D
| COGL_ENABLE_VERTEX_ARRAY
| COGL_ENABLE_TEXCOORD_ARRAY);
#if COGL_DEBUG #if COGL_DEBUG
printf("=== Drawing Tex Quad (Hardware Tiling Mode) ===\n"); printf("=== Drawing Tex Quad (Hardware Tiling Mode) ===\n");
@ -2118,24 +2128,15 @@ _cogl_texture_quad_hw (CoglTexture *tex,
_COGL_GET_CONTEXT (ctx, NO_RETVAL); _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) );
/* Pick and bind opengl texture object */ /* Pick and bind opengl texture object */
gl_handle = g_array_index (tex->slice_gl_handles, GLuint, 0); 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 */ /* Don't include the waste in the texture coordinates */
x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0); x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0);
@ -2147,20 +2148,25 @@ _cogl_texture_quad_hw (CoglTexture *tex,
ty1 = ty1 * (y_span->size - y_span->waste) / y_span->size; ty1 = ty1 * (y_span->size - y_span->waste) / y_span->size;
ty2 = ty2 * (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) #define CFX_F(x) COGL_FIXED_TO_FLOAT(x)
/* Draw textured quad */ p->v[0] = CFX_F (x1); p->v[1] = CFX_F (y2);
tex_coords[0] = CFX_F(tx1); tex_coords[1] = CFX_F(ty2); p->t[0] = CFX_F (tx1); p->t[1] = CFX_F (ty2);
tex_coords[2] = CFX_F(tx2); tex_coords[3] = CFX_F(ty2); p++;
tex_coords[4] = CFX_F(tx1); tex_coords[5] = CFX_F(ty1); p->v[0] = CFX_F (x2); p->v[1] = CFX_F (y2);
tex_coords[6] = CFX_F(tx2); tex_coords[7] = CFX_F(ty1); p->t[0] = CFX_F (tx2); p->t[1] = CFX_F (ty2);
p++;
quad_coords[0] = CFX_F(x1); quad_coords[1] = CFX_F(y2); p->v[0] = CFX_F (x2); p->v[1] = CFX_F (y1);
quad_coords[2] = CFX_F(x2); quad_coords[3] = CFX_F(y2); p->t[0] = CFX_F (tx2); p->t[1] = CFX_F (ty1);
quad_coords[4] = CFX_F(x1); quad_coords[5] = CFX_F(y1); p++;
quad_coords[6] = CFX_F(x2); quad_coords[7] = CFX_F(y1); p->v[0] = CFX_F (x1); p->v[1] = CFX_F (y1);
p->t[0] = CFX_F (tx1); p->t[1] = CFX_F (ty1);
GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); p++;
#undef CFX_F #undef CFX_F
} }
@ -2176,7 +2182,12 @@ cogl_texture_rectangle (CoglHandle handle,
CoglFixed tx2, CoglFixed tx2,
CoglFixed ty2) 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 */ /* Check if valid texture */
if (!cogl_is_texture (handle)) if (!cogl_is_texture (handle))
@ -2194,6 +2205,18 @@ cogl_texture_rectangle (CoglHandle handle,
if (tx1 == tx2 || ty1 == ty2) if (tx1 == tx2 || ty1 == ty2)
return; 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 /* 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 (no waste) or all of the coordinates are in the range [0,1] then
we can use hardware tiling */ 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); _cogl_texture_quad_hw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2);
else else
_cogl_texture_quad_sw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2); _cogl_texture_quad_sw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2);
_cogl_texture_flush_vertices ();
} }
void void