Support cogl_texture_multiple_rectangles in GL ES backend

This commit is contained in:
Neil Roberts 2008-12-09 15:10:33 +00:00
parent 59aef7488f
commit 223c1225ea
3 changed files with 212 additions and 156 deletions

View File

@ -59,8 +59,10 @@ cogl_create_context ()
_context->last_path = 0; _context->last_path = 0;
_context->texture_handles = NULL; _context->texture_handles = NULL;
_context->texture_vertices_size = 0; _context->texture_vertices = g_array_new (FALSE, FALSE,
_context->texture_vertices = NULL; sizeof (CoglTextureGLVertex));
_context->texture_indices = g_array_new (FALSE, FALSE,
sizeof (GLushort));
_context->fbo_handles = NULL; _context->fbo_handles = NULL;
_context->program_handles = NULL; _context->program_handles = NULL;
@ -104,7 +106,9 @@ cogl_destroy_context ()
#endif #endif
if (_context->texture_vertices) 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) if (_context->texture_handles)
g_array_free (_context->texture_handles, TRUE); g_array_free (_context->texture_handles, TRUE);

View File

@ -65,8 +65,13 @@ typedef struct
/* Textures */ /* Textures */
GArray *texture_handles; GArray *texture_handles;
CoglTextureGLVertex *texture_vertices; GArray *texture_vertices;
gulong texture_vertices_size; 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 */ /* Framebuffer objects */
GArray *fbo_handles; GArray *fbo_handles;

View File

@ -2047,6 +2047,79 @@ 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->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 static void
_cogl_texture_quad_sw (CoglTexture *tex, _cogl_texture_quad_sw (CoglTexture *tex,
CoglFixed x1, CoglFixed x1,
@ -2067,12 +2140,7 @@ _cogl_texture_quad_sw (CoglTexture *tex,
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];
GLfloat quad_coords[8];
GLuint gl_handle; 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);
@ -2080,19 +2148,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
@ -2116,9 +2171,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);
@ -2168,7 +2220,6 @@ _cogl_texture_quad_sw (CoglTexture *tex,
slice_ty1 /= iter_y.span->size; slice_ty1 /= iter_y.span->size;
slice_ty2 /= iter_y.span->size; slice_ty2 /= iter_y.span->size;
/* Iterate until whole quad width covered */ /* Iterate until whole quad width covered */
for (_cogl_span_iter_begin (&iter_x, tex->slice_x_spans, for (_cogl_span_iter_begin (&iter_x, tex->slice_x_spans,
first_tx, tx1, tx2) ; first_tx, tx1, tx2) ;
@ -2211,25 +2262,22 @@ _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( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle, /* If we're using a different texture from the one already queued
tex->gl_intformat) ); 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 _cogl_texture_add_quad_vertices (COGL_FIXED_TO_FLOAT (slice_qx1),
COGL_FIXED_TO_FLOAT (slice_qy1),
/* Draw textured quad */ COGL_FIXED_TO_FLOAT (slice_qx2),
tex_coords[0] = CFX_F(slice_tx1); tex_coords[1] = CFX_F(slice_ty2); COGL_FIXED_TO_FLOAT (slice_qy2),
tex_coords[2] = CFX_F(slice_tx2); tex_coords[3] = CFX_F(slice_ty2); COGL_FIXED_TO_FLOAT (slice_tx1),
tex_coords[4] = CFX_F(slice_tx1); tex_coords[5] = CFX_F(slice_ty1); COGL_FIXED_TO_FLOAT (slice_ty1),
tex_coords[6] = CFX_F(slice_tx2); tex_coords[7] = CFX_F(slice_ty1); COGL_FIXED_TO_FLOAT (slice_tx2),
COGL_FIXED_TO_FLOAT (slice_ty2));
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
} }
} }
} }
@ -2245,14 +2293,9 @@ _cogl_texture_quad_hw (CoglTexture *tex,
CoglFixed tx2, CoglFixed tx2,
CoglFixed ty2) CoglFixed ty2)
{ {
GLfloat tex_coords[8];
GLfloat quad_coords[8];
GLuint gl_handle; GLuint gl_handle;
CoglTexSliceSpan *x_span; CoglTexSliceSpan *x_span;
CoglTexSliceSpan *y_span; 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");
@ -2260,25 +2303,16 @@ _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( 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 */ /* 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);
@ -2290,36 +2324,27 @@ _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;
#define CFX_F(x) COGL_FIXED_TO_FLOAT(x) _cogl_texture_add_quad_vertices (COGL_FIXED_TO_FLOAT (x1),
COGL_FIXED_TO_FLOAT (y1),
/* Draw textured quad */ COGL_FIXED_TO_FLOAT (x2),
tex_coords[0] = CFX_F(tx1); tex_coords[1] = CFX_F(ty2); COGL_FIXED_TO_FLOAT (y2),
tex_coords[2] = CFX_F(tx2); tex_coords[3] = CFX_F(ty2); COGL_FIXED_TO_FLOAT (tx1),
tex_coords[4] = CFX_F(tx1); tex_coords[5] = CFX_F(ty1); COGL_FIXED_TO_FLOAT (ty1),
tex_coords[6] = CFX_F(tx2); tex_coords[7] = CFX_F(ty1); COGL_FIXED_TO_FLOAT (tx2),
COGL_FIXED_TO_FLOAT (ty2));
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) );
#undef CFX_F
} }
void void
cogl_texture_rectangle (CoglHandle handle, cogl_texture_multiple_rectangles (CoglHandle handle,
CoglFixed x1, const CoglFixed *verts,
CoglFixed y1, guint n_rects)
CoglFixed x2,
CoglFixed y2,
CoglFixed tx1,
CoglFixed ty1,
CoglFixed tx2,
CoglFixed ty2)
{ {
CoglTexture *tex; 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 */ /* Check if valid texture */
if (!cogl_is_texture (handle)) if (!cogl_is_texture (handle))
@ -2336,30 +2361,68 @@ cogl_texture_rectangle (CoglHandle handle,
if (tex->slice_gl_handles->len == 0) if (tex->slice_gl_handles->len == 0)
return; return;
if (tx1 == tx2 || ty1 == ty2) /* Prepare GL state */
return; if (ctx->color_alpha < 255
|| tex->bitmap.format & COGL_A_BIT)
enable_flags |= COGL_ENABLE_BLEND;
/* Pick tiling mode according to hw support */ if (ctx->enable_backface_culling)
if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
&& tex->slice_gl_handles->len == 1)
cogl_enable (enable_flags);
g_array_set_size (ctx->texture_vertices, 0);
while (n_rects-- > 0)
{ {
_cogl_texture_quad_hw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2); if (verts[4] != verts[6] && verts[5] != verts[7])
}
else
{ {
/* 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 if (tex->slice_gl_handles->len == 1
&& tx1 >= -COGL_FIXED_1 && ((cogl_features_available (COGL_FEATURE_TEXTURE_NPOT)
&& tx2 <= COGL_FIXED_1 && tex->gl_target == GL_TEXTURE_2D)
&& ty1 >= -COGL_FIXED_1 || (verts[4] >= 0 && verts[4] <= COGL_FIXED_1
&& ty2 <= COGL_FIXED_1) && verts[6] >= 0 && verts[6] <= COGL_FIXED_1
{ && verts[5] >= 0 && verts[5] <= COGL_FIXED_1
_cogl_texture_quad_hw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2); && 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 else
{ _cogl_texture_quad_sw (tex, verts[0],verts[1], verts[2],verts[3],
_cogl_texture_quad_sw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2); 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 void
@ -2405,22 +2468,8 @@ cogl_texture_polygon (CoglHandle handle,
/* Make sure there is enough space in the global texture vertex /* Make sure there is enough space in the global texture vertex
array. This is used so we can render the polygon with a single array. This is used so we can render the polygon with a single
call to OpenGL but still support any number of vertices */ call to OpenGL but still support any number of vertices */
if (ctx->texture_vertices_size < n_vertices) g_array_set_size (ctx->texture_vertices, n_vertices);
{ p = (CoglTextureGLVertex *) ctx->texture_vertices->data;
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 */ /* Prepare GL state */
enable_flags = (COGL_ENABLE_TEXTURE_2D enable_flags = (COGL_ENABLE_TEXTURE_2D
@ -2447,14 +2496,12 @@ cogl_texture_polygon (CoglHandle handle,
if (use_color) if (use_color)
{ {
enable_flags |= COGL_ENABLE_COLOR_ARRAY; enable_flags |= COGL_ENABLE_COLOR_ARRAY;
GE( glColorPointer (4, GL_UNSIGNED_BYTE, sizeof (CoglTextureGLVertex), GE( glColorPointer (4, GL_UNSIGNED_BYTE,
ctx->texture_vertices[0].c) ); sizeof (CoglTextureGLVertex), p->c) );
} }
GE( glVertexPointer (3, GL_FLOAT, sizeof (CoglTextureGLVertex), GE( glVertexPointer (3, GL_FLOAT, sizeof (CoglTextureGLVertex), p->v ) );
ctx->texture_vertices[0].v) ); GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex), p->t ) );
GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex),
ctx->texture_vertices[0].t) );
cogl_enable (enable_flags); 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 /* Convert the vertices into an array of GLfloats ready to pass to
OpenGL */ 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 #define CFX_F COGL_FIXED_TO_FLOAT