mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 00:20:42 -05:00
Merge branch multiple-texture-rectangle into master
Bug 1289 - Draw multiple glyphs at once
The multiple-texture-rectangle branch adds a new Cogl texture function
called cogl_texture_multiple_rectangles which is used to draw multiple
rectangles out of a texture using a single GL call. This is
significantly faster than drawing the rectangles with individual calls
on some platforms. The Pango renderer now uses this to speed up
rendering.
The conflicts are just due to the whitespace fixes in cb569a5
.
Conflicts:
clutter/cogl/gl/cogl-context.c
clutter/cogl/gl/cogl-context.h
clutter/cogl/gl/cogl-texture.c
This commit is contained in:
commit
805b88d4c0
@ -385,6 +385,29 @@ 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 #CoglFixed<!-- -->s 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,
|
||||
guint n_rects);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __COGL_TEXTURE_H__ */
|
||||
|
@ -56,8 +56,10 @@ 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->draw_buffer = COGL_WINDOW_BUFFER;
|
||||
@ -148,6 +150,11 @@ cogl_destroy_context ()
|
||||
if (_context->program_handles)
|
||||
g_array_free (_context->program_handles, TRUE);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -63,8 +63,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;
|
||||
GLenum texture_wrap_mode;
|
||||
|
||||
/* Framebuffer objects */
|
||||
GArray *fbo_handles;
|
||||
|
@ -1911,6 +1911,95 @@ 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)
|
||||
{
|
||||
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,
|
||||
sizeof (CoglTextureGLVertex), p->t ) );
|
||||
|
||||
GE( glBindTexture (ctx->texture_target, ctx->texture_current) );
|
||||
GE( ctx->pf_glDrawRangeElements (GL_TRIANGLES,
|
||||
0, ctx->texture_vertices->len - 1,
|
||||
needed_indices,
|
||||
GL_UNSIGNED_SHORT,
|
||||
ctx->texture_indices->data) );
|
||||
|
||||
g_array_set_size (ctx->texture_vertices, 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;
|
||||
|
||||
_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++;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_quad_sw (CoglTexture *tex,
|
||||
CoglFixed x1,
|
||||
@ -1931,11 +2020,7 @@ _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_VERTEX_ARRAY
|
||||
| COGL_ENABLE_TEXCOORD_ARRAY);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
@ -1943,26 +2028,13 @@ _cogl_texture_quad_sw (CoglTexture *tex,
|
||||
printf("=== Drawing Tex Quad (Software Tiling Mode) ===\n");
|
||||
#endif
|
||||
|
||||
/* Prepare GL state */
|
||||
if (tex->gl_target == CGL_TEXTURE_RECTANGLE_ARB)
|
||||
enable_flags |= COGL_ENABLE_TEXTURE_RECT;
|
||||
else
|
||||
enable_flags |= COGL_ENABLE_TEXTURE_2D;
|
||||
|
||||
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);
|
||||
|
||||
/* We can't use hardware repeat so we need to set clamp to edge
|
||||
otherwise it might pull in edge pixels from the other side */
|
||||
if (ctx->texture_vertices->len > 0
|
||||
&& ctx->texture_wrap_mode != GL_CLAMP_TO_EDGE)
|
||||
_cogl_texture_flush_vertices ();
|
||||
_cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_EDGE);
|
||||
ctx->texture_wrap_mode = GL_CLAMP_TO_EDGE;
|
||||
|
||||
/* If the texture coordinates are backwards then swap both the
|
||||
geometry and texture coordinates so that the texture will be
|
||||
@ -1987,9 +2059,6 @@ _cogl_texture_quad_sw (CoglTexture *tex,
|
||||
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);
|
||||
@ -2087,24 +2156,22 @@ _cogl_texture_quad_sw (CoglTexture *tex,
|
||||
iter_y.index * iter_x.array->len +
|
||||
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
|
||||
|
||||
/* 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);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2120,13 +2187,10 @@ _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_VERTEX_ARRAY
|
||||
| COGL_ENABLE_TEXCOORD_ARRAY);
|
||||
GLenum wrap_mode;
|
||||
|
||||
#if COGL_DEBUG
|
||||
printf("=== Drawing Tex Quad (Hardware Tiling Mode) ===\n");
|
||||
@ -2134,24 +2198,6 @@ _cogl_texture_quad_hw (CoglTexture *tex,
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Prepare GL state */
|
||||
if (tex->gl_target == CGL_TEXTURE_RECTANGLE_ARB)
|
||||
enable_flags |= COGL_ENABLE_TEXTURE_RECT;
|
||||
else
|
||||
enable_flags |= COGL_ENABLE_TEXTURE_2D;
|
||||
|
||||
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 coords are all in the range [0,1] then we want to
|
||||
clamp the coords to the edge otherwise it can pull in edge pixels
|
||||
from the wrong side when scaled */
|
||||
@ -2159,16 +2205,24 @@ _cogl_texture_quad_hw (CoglTexture *tex,
|
||||
&& tx2 >= 0 && tx2 <= COGL_FIXED_1
|
||||
&& ty1 >= 0 && ty1 <= COGL_FIXED_1
|
||||
&& ty2 >= 0 && ty2 <= COGL_FIXED_1)
|
||||
_cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_EDGE);
|
||||
wrap_mode = GL_CLAMP_TO_EDGE;
|
||||
else
|
||||
_cogl_texture_set_wrap_mode_parameter (tex, GL_REPEAT);
|
||||
|
||||
GE( glTexCoordPointer (2, GL_FLOAT, 0, tex_coords) );
|
||||
GE( glVertexPointer (2, GL_FLOAT, 0, quad_coords) );
|
||||
wrap_mode = GL_REPEAT;
|
||||
|
||||
/* 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
|
||||
|| ctx->texture_wrap_mode != wrap_mode))
|
||||
_cogl_texture_flush_vertices ();
|
||||
ctx->texture_target = tex->gl_target;
|
||||
ctx->texture_current = gl_handle;
|
||||
ctx->texture_wrap_mode = wrap_mode;
|
||||
|
||||
_cogl_texture_set_wrap_mode_parameter (tex, wrap_mode);
|
||||
|
||||
/* Don't include the waste in the texture coordinates */
|
||||
x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0);
|
||||
@ -2189,36 +2243,26 @@ _cogl_texture_quad_hw (CoglTexture *tex,
|
||||
ty2 *= y_span->size;
|
||||
}
|
||||
|
||||
#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) );
|
||||
|
||||
#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
|
||||
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;
|
||||
CoglTexture *tex;
|
||||
gulong enable_flags = (COGL_ENABLE_VERTEX_ARRAY
|
||||
| COGL_ENABLE_TEXCOORD_ARRAY);
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* Check if valid texture */
|
||||
if (!cogl_is_texture (handle))
|
||||
@ -2235,22 +2279,73 @@ cogl_texture_rectangle (CoglHandle handle,
|
||||
if (tex->slice_gl_handles->len == 0)
|
||||
return;
|
||||
|
||||
if (tx1 == tx2 || ty1 == ty2)
|
||||
return;
|
||||
|
||||
/* 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)
|
||||
|| (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);
|
||||
/* Prepare GL state */
|
||||
if (tex->gl_target == CGL_TEXTURE_RECTANGLE_ARB)
|
||||
enable_flags |= COGL_ENABLE_TEXTURE_RECT;
|
||||
else
|
||||
_cogl_texture_quad_sw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2);
|
||||
enable_flags |= COGL_ENABLE_TEXTURE_2D;
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
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
|
||||
@ -2299,22 +2394,8 @@ 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;
|
||||
|
||||
ctx->texture_vertices = g_realloc (ctx->texture_vertices,
|
||||
nsize
|
||||
* sizeof (CoglTextureGLVertex));
|
||||
}
|
||||
g_array_set_size (ctx->texture_vertices, n_vertices);
|
||||
p = (CoglTextureGLVertex *) ctx->texture_vertices->data;
|
||||
|
||||
/* Prepare GL state */
|
||||
enable_flags = (COGL_ENABLE_VERTEX_ARRAY
|
||||
@ -2332,14 +2413,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);
|
||||
|
||||
@ -2362,9 +2441,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++)
|
||||
{
|
||||
CoglFixed tx, ty;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -2047,6 +2047,94 @@ 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)
|
||||
{
|
||||
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,
|
||||
sizeof (CoglTextureGLVertex), p->t ) );
|
||||
|
||||
GE( glBindTexture (ctx->texture_target, ctx->texture_current) );
|
||||
GE( glDrawElements (GL_TRIANGLES,
|
||||
needed_indices,
|
||||
GL_UNSIGNED_SHORT,
|
||||
ctx->texture_indices->data) );
|
||||
|
||||
g_array_set_size (ctx->texture_vertices, 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;
|
||||
|
||||
_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++;
|
||||
}
|
||||
|
||||
static void
|
||||
_cogl_texture_quad_sw (CoglTexture *tex,
|
||||
CoglFixed x1,
|
||||
@ -2067,31 +2155,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 +2185,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 +2225,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 +2254,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 +2276,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 +2308,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 +2339,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 +2426,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 +2483,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 +2511,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 +2526,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
|
||||
|
||||
|
@ -51,6 +51,10 @@ struct _CoglPangoRenderer
|
||||
CoglPangoGlyphCache *mipmapped_glyph_cache;
|
||||
|
||||
gboolean use_mipmapping;
|
||||
|
||||
/* Array of rectangles to draw from the current texture */
|
||||
GArray *glyph_rectangles;
|
||||
CoglHandle glyph_texture;
|
||||
};
|
||||
|
||||
struct _CoglPangoRendererClass
|
||||
@ -58,6 +62,46 @@ struct _CoglPangoRendererClass
|
||||
PangoRendererClass class_instance;
|
||||
};
|
||||
|
||||
static void
|
||||
cogl_pango_renderer_glyphs_end (CoglPangoRenderer *priv)
|
||||
{
|
||||
if (priv->glyph_rectangles->len > 0)
|
||||
{
|
||||
CoglFixed *rectangles = (CoglFixed *) priv->glyph_rectangles->data;
|
||||
cogl_texture_multiple_rectangles (priv->glyph_texture, rectangles,
|
||||
priv->glyph_rectangles->len / 8);
|
||||
g_array_set_size (priv->glyph_rectangles, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cogl_pango_renderer_draw_glyph (CoglPangoRenderer *priv,
|
||||
CoglPangoGlyphCacheValue *cache_value,
|
||||
CoglFixed x1,
|
||||
CoglFixed y1)
|
||||
{
|
||||
CoglFixed x2, y2;
|
||||
CoglFixed *p;
|
||||
|
||||
if (priv->glyph_rectangles->len > 0
|
||||
&& priv->glyph_texture != cache_value->texture)
|
||||
cogl_pango_renderer_glyphs_end (priv);
|
||||
|
||||
priv->glyph_texture = cache_value->texture;
|
||||
|
||||
x2 = x1 + CLUTTER_INT_TO_FIXED (cache_value->draw_width);
|
||||
y2 = y1 + CLUTTER_INT_TO_FIXED (cache_value->draw_height);
|
||||
|
||||
g_array_set_size (priv->glyph_rectangles, priv->glyph_rectangles->len + 8);
|
||||
p = &g_array_index (priv->glyph_rectangles, CoglFixed,
|
||||
priv->glyph_rectangles->len - 8);
|
||||
|
||||
*(p++) = x1; *(p++) = y1;
|
||||
*(p++) = x2; *(p++) = y2;
|
||||
*(p++) = cache_value->tx1; *(p++) = cache_value->ty1;
|
||||
*(p++) = cache_value->tx2; *(p++) = cache_value->ty2;
|
||||
}
|
||||
|
||||
#define COGL_PANGO_UNIT_TO_FIXED(x) ((x) << (COGL_FIXED_Q - 10))
|
||||
|
||||
static void cogl_pango_renderer_finalize (GObject *object);
|
||||
@ -89,6 +133,7 @@ cogl_pango_renderer_init (CoglPangoRenderer *priv)
|
||||
priv->glyph_cache = cogl_pango_glyph_cache_new (FALSE);
|
||||
priv->mipmapped_glyph_cache = cogl_pango_glyph_cache_new (TRUE);
|
||||
priv->use_mipmapping = FALSE;
|
||||
priv->glyph_rectangles = g_array_new (FALSE, FALSE, sizeof (CoglFixed));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -111,6 +156,7 @@ cogl_pango_renderer_finalize (GObject *object)
|
||||
|
||||
cogl_pango_glyph_cache_free (priv->mipmapped_glyph_cache);
|
||||
cogl_pango_glyph_cache_free (priv->glyph_cache);
|
||||
g_array_free (priv->glyph_rectangles, TRUE);
|
||||
|
||||
G_OBJECT_CLASS (cogl_pango_renderer_parent_class)->finalize (object);
|
||||
}
|
||||
@ -376,10 +422,10 @@ cogl_pango_renderer_draw_box (int x, int y,
|
||||
|
||||
static void
|
||||
cogl_pango_renderer_get_device_units (PangoRenderer *renderer,
|
||||
int xin,
|
||||
int yin,
|
||||
CoglFixed *xout,
|
||||
CoglFixed *yout)
|
||||
int xin,
|
||||
int yin,
|
||||
CoglFixed *xout,
|
||||
CoglFixed *yout)
|
||||
{
|
||||
const PangoMatrix *matrix;
|
||||
|
||||
@ -454,6 +500,7 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
|
||||
int xi,
|
||||
int yi)
|
||||
{
|
||||
CoglPangoRenderer *priv = (CoglPangoRenderer *) renderer;
|
||||
CoglPangoGlyphCacheValue *cache_value;
|
||||
int i;
|
||||
|
||||
@ -474,6 +521,8 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
|
||||
{
|
||||
PangoFontMetrics *metrics;
|
||||
|
||||
cogl_pango_renderer_glyphs_end (priv);
|
||||
|
||||
if (font == NULL ||
|
||||
(metrics = pango_font_get_metrics (font, NULL)) == NULL)
|
||||
{
|
||||
@ -503,10 +552,14 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
|
||||
gi->glyph);
|
||||
|
||||
if (cache_value == NULL)
|
||||
cogl_pango_renderer_draw_box (COGL_FIXED_TO_INT (x),
|
||||
COGL_FIXED_TO_INT (y),
|
||||
PANGO_UNKNOWN_GLYPH_WIDTH,
|
||||
PANGO_UNKNOWN_GLYPH_HEIGHT);
|
||||
{
|
||||
cogl_pango_renderer_glyphs_end (priv);
|
||||
|
||||
cogl_pango_renderer_draw_box (COGL_FIXED_TO_INT (x),
|
||||
COGL_FIXED_TO_INT (y),
|
||||
PANGO_UNKNOWN_GLYPH_WIDTH,
|
||||
PANGO_UNKNOWN_GLYPH_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
CoglFixed width, height;
|
||||
@ -517,15 +570,12 @@ cogl_pango_renderer_draw_glyphs (PangoRenderer *renderer,
|
||||
width = x + COGL_FIXED_FROM_INT (cache_value->draw_width);
|
||||
height = y + COGL_FIXED_FROM_INT (cache_value->draw_height);
|
||||
|
||||
/* Render the glyph from the texture */
|
||||
cogl_texture_rectangle (cache_value->texture,
|
||||
x, y,
|
||||
width, height,
|
||||
cache_value->tx1, cache_value->ty1,
|
||||
cache_value->tx2, cache_value->ty2);
|
||||
cogl_pango_renderer_draw_glyph (priv, cache_value, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
xi += gi->geometry.width;
|
||||
}
|
||||
|
||||
cogl_pango_renderer_glyphs_end (priv);
|
||||
}
|
||||
|
@ -120,6 +120,7 @@ cogl_texture_set_region
|
||||
cogl_texture_ref
|
||||
cogl_texture_unref
|
||||
cogl_texture_rectangle
|
||||
cogl_texture_multiple_rectangles
|
||||
cogl_texture_polygon
|
||||
</SECTION>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user