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,7 +65,12 @@ 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;
CoglBufferTarget draw_buffer; CoglBufferTarget draw_buffer;

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,40 +1939,23 @@ _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);
#if COGL_DEBUG #if COGL_DEBUG
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
@ -1974,10 +1979,7 @@ _cogl_texture_quad_sw (CoglTexture *tex,
ty1 = ty2; ty1 = ty2;
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);
@ -2069,23 +2071,35 @@ _cogl_texture_quad_sw (CoglTexture *tex,
gl_handle = g_array_index (tex->slice_gl_handles, GLuint, gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
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) );
#define CFX_F COGL_FIXED_TO_FLOAT /* If we're using a different texture from the one already queued
then flush the vertices */
/* Draw textured quad */ if (ctx->texture_vertices->len > 0
tex_coords[0] = CFX_F(slice_tx1); tex_coords[1] = CFX_F(slice_ty2); && gl_handle != ctx->texture_current)
tex_coords[2] = CFX_F(slice_tx2); tex_coords[3] = CFX_F(slice_ty2); _cogl_texture_flush_vertices ();
tex_coords[4] = CFX_F(slice_tx1); tex_coords[5] = CFX_F(slice_ty1); ctx->texture_target = tex->gl_target;
tex_coords[6] = CFX_F(slice_tx2); tex_coords[7] = CFX_F(slice_ty1); ctx->texture_current = gl_handle;
quad_coords[0] = CFX_F(slice_qx1); quad_coords[1] = CFX_F(slice_qy2); /* Add the quad to the list of queued vertices */
quad_coords[2] = CFX_F(slice_qx2); quad_coords[3] = CFX_F(slice_qy2); g_array_set_size (ctx->texture_vertices,
quad_coords[4] = CFX_F(slice_qx1); quad_coords[5] = CFX_F(slice_qy1); ctx->texture_vertices->len + 4);
quad_coords[6] = CFX_F(slice_qx2); quad_coords[7] = CFX_F(slice_qy1); 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 #undef CFX_F
} }
@ -2103,40 +2117,27 @@ _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");
#endif #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); _COGL_GET_CONTEXT (ctx, NO_RETVAL);
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);
y_span = &g_array_index (tex->slice_y_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; 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 */
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); p->v[0] = CFX_F (x1); p->v[1] = CFX_F (y2);
quad_coords[2] = CFX_F(x2); quad_coords[3] = CFX_F(y2); p->t[0] = CFX_F (tx1); p->t[1] = CFX_F (ty2);
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 (x2); p->v[1] = CFX_F (y2);
p->t[0] = CFX_F (tx2); p->t[1] = CFX_F (ty2);
GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) ); 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 #undef CFX_F
} }
@ -2176,8 +2182,13 @@ 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))
return; return;
@ -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