A comparison of gl/cogl-texture.c and gles/cogl-texture.c, to reduce

differences and improve maintainability.

	* clutter/cogl/gl/cogl-context.h:
	Adds a CoglTextureGLVertex typedef + texture_vertices and
	texture_vertices_size members to CoglContext for using vertex arrays
	like GLES does

	* clutter/cogl/gl/cogl-context.c:
	Initializes texture_vertices + texture_vertices_size members

	* clutter/cogl/gl/cogl-internal.h:
	Adds COGL_ENABLE_COLOR_ARRAY

	* clutter/cogl/gl/cogl.c:
	Add COGL_ENABLE_COLOR_ARRAY support to cogl_enable

	* clutter/cogl/gles/cogl-context.h:
	Change the CoglTextureGLVertex to use GLfloat for the position
	and texture coord attributes and GLubyte for the color.

	* clutter/cogl/gles/cogl-texture-private.h:
	Adds a wrap_mode member like GL has.

	* clutter/cogl/gl/cogl-texture.c
	* clutter/cogl/gles/cogl-texture.c:
	Improves the comparability of the files, such that the remaining
	differences, better reflect the fundamental differences needed
	between GL and GLES. Notably GL no longer uses glBegin/glEnd for
	submitting vertices, it uses vertex arrays like GLES and this gives
	a small but measurable fps improvement for test-text.
This commit is contained in:
Robert Bragg 2008-11-18 16:24:09 +00:00
parent 6731dfa468
commit 8b557c6c13
8 changed files with 624 additions and 406 deletions

View File

@ -57,6 +57,8 @@ cogl_create_context ()
_context->path_nodes_size = 0;
_context->texture_handles = NULL;
_context->texture_vertices_size = 0;
_context->texture_vertices = NULL;
_context->fbo_handles = NULL;
_context->draw_buffer = COGL_WINDOW_BUFFER;

View File

@ -28,6 +28,13 @@
#include "cogl-primitives.h"
typedef struct
{
GLfloat v[3];
GLfloat t[2];
GLubyte c[4];
} CoglTextureGLVertex;
typedef struct
{
/* Features cache */
@ -56,7 +63,9 @@ typedef struct
GLfloat inverse_projection[16];
/* Textures */
GArray *texture_handles;
GArray *texture_handles;
CoglTextureGLVertex *texture_vertices;
gulong texture_vertices_size;
/* Framebuffer objects */
GArray *fbo_handles;

View File

@ -56,7 +56,8 @@ const char *_cogl_error_string(GLenum errorCode);
#define COGL_ENABLE_TEXTURE_RECT (1<<4)
#define COGL_ENABLE_VERTEX_ARRAY (1<<5)
#define COGL_ENABLE_TEXCOORD_ARRAY (1<<6)
#define COGL_ENABLE_BACKFACE_CULLING (1<<7)
#define COGL_ENABLE_COLOR_ARRAY (1<<7)
#define COGL_ENABLE_BACKFACE_CULLING (1<<8)
gint
_cogl_get_format_bpp (CoglPixelFormat format);

View File

@ -49,10 +49,6 @@
printf("err: 0x%x\n", err); \
} */
static void _cogl_texture_free (CoglTexture *tex);
COGL_HANDLE_DEFINE (Texture, texture, texture_handles);
struct _CoglSpanIter
{
gint index;
@ -70,6 +66,11 @@ struct _CoglSpanIter
gboolean intersects;
};
static void _cogl_texture_free (CoglTexture *tex);
COGL_HANDLE_DEFINE (Texture, texture, texture_handles);
static void
_cogl_texture_bitmap_free (CoglTexture *tex)
{
@ -100,8 +101,8 @@ _cogl_span_iter_update (CoglSpanIter *iter)
iter->index);
/* Offset next position by span size */
iter->next_pos = iter->pos
+ COGL_FIXED_FROM_INT (iter->span->size - iter->span->waste);
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 ||
@ -168,48 +169,37 @@ _cogl_span_iter_end (CoglSpanIter *iter)
}
static void
_cogl_subregion_gl_store_rules (gint bmp_rowstride,
gint bmp_width,
gint bmp_bpp,
gint src_x,
gint src_y,
gboolean pack)
prep_for_gl_pixels_upload (gint pixels_rowstride,
gint pixels_src_x,
gint pixels_src_y,
gint pixels_bpp)
{
const GLenum ALIGNMENT = pack ?
GL_PACK_ALIGNMENT : GL_UNPACK_ALIGNMENT;
GE( glPixelStorei (GL_UNPACK_ROW_LENGTH, pixels_rowstride / pixels_bpp) );
const GLenum ROW_LENGTH = pack ?
GL_PACK_ROW_LENGTH : GL_UNPACK_ROW_LENGTH;
GE( glPixelStorei (GL_UNPACK_SKIP_PIXELS, pixels_src_x) );
GE( glPixelStorei (GL_UNPACK_SKIP_ROWS, pixels_src_y) );
const GLenum SKIP_ROWS = pack ?
GL_PACK_SKIP_ROWS : GL_UNPACK_SKIP_ROWS;
const GLenum SKIP_PIXELS = pack ?
GL_PACK_SKIP_PIXELS : GL_UNPACK_SKIP_PIXELS;
/* Encode the part of the rowstride that is a multiple of bmp_bpp in
ROW_LENGTH and the remainder in ALIGNMENT */
GE( glPixelStorei (ROW_LENGTH, bmp_rowstride / bmp_bpp) );
if (bmp_rowstride == bmp_width * bmp_bpp)
{
GE( glPixelStorei (ALIGNMENT, 1) );
}
if (!(pixels_rowstride & 0x7))
GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 8) );
else if (!(pixels_rowstride & 0x3))
GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 4) );
else if (!(pixels_rowstride & 0x1))
GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 2) );
else
{
if ((bmp_rowstride % 4) == 0)
{
GE( glPixelStorei (ALIGNMENT, 4) );
}
else
{
if ((bmp_rowstride % 2) == 0)
GE( glPixelStorei (ALIGNMENT, 2) );
}
}
GE( glPixelStorei (SKIP_ROWS, src_y) );
GE( glPixelStorei (SKIP_PIXELS, src_x) );
GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 1) );
}
static void
prep_for_gl_pixels_download (gint pixels_rowstride)
{
if (!(pixels_rowstride & 0x7))
GE( glPixelStorei (GL_PACK_ALIGNMENT, 8) );
else if (!(pixels_rowstride & 0x3))
GE( glPixelStorei (GL_PACK_ALIGNMENT, 4) );
else if (!(pixels_rowstride & 0x1))
GE( glPixelStorei (GL_PACK_ALIGNMENT, 2) );
else
GE( glPixelStorei (GL_PACK_ALIGNMENT, 1) );
}
static guchar *
@ -270,17 +260,17 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
y * tex->slice_x_spans->len + x);
/* Setup gl alignment to match rowstride and top-left corner */
_cogl_subregion_gl_store_rules (tex->bitmap.rowstride,
tex->bitmap.width,
bpp,
x_span->start,
y_span->start,
FALSE);
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) );
GE( glTexSubImage2D (tex->gl_target, 0, 0, 0,
GE( glTexSubImage2D (tex->gl_target, 0,
0,
0,
x_span->size - x_span->waste,
y_span->size - y_span->waste,
tex->gl_format, tex->gl_type,
@ -305,13 +295,14 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
src += tex->bitmap.rowstride;
}
_cogl_subregion_gl_store_rules (x_span->waste * bpp,
x_span->waste,
bpp,
0, 0, FALSE);
prep_for_gl_pixels_upload (x_span->waste * bpp,
0, /* src x */
0, /* src y */
bpp);
GE( glTexSubImage2D (tex->gl_target, 0,
x_span->size - x_span->waste, 0,
x_span->size - x_span->waste,
0,
x_span->waste,
y_span->size - y_span->waste,
tex->gl_format, tex->gl_type,
@ -339,13 +330,14 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
}
}
_cogl_subregion_gl_store_rules (x_span->size * bpp,
x_span->size,
bpp,
0, 0, FALSE);
prep_for_gl_pixels_upload (x_span->size * bpp,
0, /* src x */
0, /* src y */
bpp);
GE( glTexSubImage2D (tex->gl_target, 0,
0, y_span->size - y_span->waste,
0,
y_span->size - y_span->waste,
x_span->size,
y_span->waste,
tex->gl_format, tex->gl_type,
@ -401,17 +393,16 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
slice_bmp.height = y_span->size;
slice_bmp.rowstride = bpp * slice_bmp.width;
slice_bmp.data = (guchar*) g_malloc (slice_bmp.rowstride *
slice_bmp.height);
slice_bmp.height);
/* Setup gl alignment to 0,0 top-left corner */
_cogl_subregion_gl_store_rules (slice_bmp.rowstride,
slice_bmp.width,
bpp, 0, 0, TRUE);
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,
GE (glGetTexImage (tex->gl_target,
0, /* level */
target_gl_format,
target_gl_type,
slice_bmp.data) );
@ -428,34 +419,21 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
g_free (slice_bmp.data);
}
else
{
/* Setup gl alignment to match rowstride and top-left corner */
/* FIXME: for some strange reason any value other than 0
* for GL_PACK_SKIP_PIXELS or GL_PACK_SKIP_ROWS corrupts the
* memory. As a workaround we offset data pointer manually
{
GLvoid *dst = target_bmp->data
+ x_span->start * bpp
+ y_span->start * target_bmp->rowstride;
_cogl_subregion_gl_store_rules (target_bmp->rowstride,
target_bmp->width,
bpp,
x_span->start,
y_span->start,
TRUE);*/
_cogl_subregion_gl_store_rules (target_bmp->rowstride,
target_bmp->width,
bpp,
0, 0,
TRUE);
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,
GE( glGetTexImage (tex->gl_target,
0, /* level */
target_gl_format,
target_gl_type,
target_bmp->data +
x_span->start * bpp +
y_span->start * target_bmp->rowstride) );
dst) );
}
}
}
@ -487,7 +465,7 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
guchar *waste_buf;
bpp = _cogl_get_format_bpp (source_bmp->format);
waste_buf = _cogl_texture_allocate_waste_buffer (tex);
/* Iterate vertical spans */
@ -550,13 +528,10 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
x_iter.index);
/* Setup gl alignment to match rowstride and top-left corner */
_cogl_subregion_gl_store_rules (source_bmp->rowstride,
source_bmp->width,
bpp,
source_x,
source_y,
FALSE);
prep_for_gl_pixels_upload (source_bmp->rowstride,
source_x,
source_y,
bpp);
/* Upload new image data */
GE( glBindTexture (tex->gl_target, gl_handle) );
@ -599,13 +574,14 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
src += source_bmp->rowstride;
}
_cogl_subregion_gl_store_rules (x_span->waste * bpp,
x_span->waste,
bpp,
0, 0, FALSE);
prep_for_gl_pixels_upload (x_span->waste * bpp,
0, /* src x */
0, /* src y */
bpp);
GE( glTexSubImage2D (tex->gl_target, 0,
x_span->size - x_span->waste, local_y,
x_span->size - x_span->waste,
local_y,
x_span->waste,
inter_h,
source_gl_format,
@ -650,13 +626,14 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
}
}
_cogl_subregion_gl_store_rules (copy_width * bpp,
copy_width,
bpp,
0, 0, FALSE);
prep_for_gl_pixels_upload (copy_width * bpp,
0, /* src x */
0, /* src y */
bpp);
GE( glTexSubImage2D (tex->gl_target, 0,
local_x, y_span->size - y_span->waste,
local_x,
y_span->size - y_span->waste,
copy_width,
y_span->waste,
source_gl_format,
@ -764,7 +741,7 @@ _cogl_texture_size_supported (GLenum gl_target,
int width,
int height)
{
if (gl_target == GL_TEXTURE_2D)
if (gl_target == GL_TEXTURE_2D)
{
/* Proxy texture allows for a quick check for supported size */
@ -805,7 +782,7 @@ _cogl_texture_slices_create (CoglTexture *tex)
bpp = _cogl_get_format_bpp (tex->bitmap.format);
/* Initialize size of largest slice according to supported features*/
/* Initialize size of largest slice according to supported features */
if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT))
{
max_width = tex->bitmap.width;
@ -904,7 +881,7 @@ _cogl_texture_slices_create (CoglTexture *tex)
max_height, tex->max_waste,
tex->slice_y_spans);
}
/* Init and resize GL handle array */
n_slices = n_x_slices * n_y_slices;
@ -946,18 +923,22 @@ _cogl_texture_slices_create (CoglTexture *tex)
y_span->size - y_span->waste);
#endif
/* Setup texture parameters */
GE( glBindTexture (tex->gl_target, gl_handles[y * n_x_slices + x]) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER, tex->mag_filter) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER, tex->min_filter) );
GE( glBindTexture (tex->gl_target,
gl_handles[y * n_x_slices + x]) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER,
tex->mag_filter) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER,
tex->min_filter) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S,
tex->wrap_mode) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T,
tex->wrap_mode) );
if (tex->auto_mipmap)
GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP, GL_TRUE) );
GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP,
GL_TRUE) );
/* Use a transparent border color so that we can leave the
color buffer alone when using texture co-ordinates
outside of the texture */
@ -1284,7 +1265,7 @@ cogl_texture_new_from_data (guint width,
tex->is_foreign = FALSE;
tex->auto_mipmap = auto_mipmap;
tex->bitmap.width = width;
tex->bitmap.height = height;
tex->bitmap.data = (guchar*)data;
@ -1361,7 +1342,7 @@ cogl_texture_new_from_file (const gchar *filename,
tex->is_foreign = FALSE;
tex->auto_mipmap = auto_mipmap;
tex->bitmap = bmp;
tex->bitmap_owner = TRUE;
@ -1414,10 +1395,10 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
CoglPixelFormat format)
{
/* NOTE: width, height and internal format are not queriable
in GLES, hence such a function prototype. However, here
they are still queried from the texture for improved
robustness and for completeness in case GLES 1.0 gets
unsupported in favor of a new version and cleaner api
in GLES, hence such a function prototype. However, for
OpenGL they are still queried from the texture for improved
robustness and for completeness in case one day GLES gains
support for them.
*/
GLenum gl_error = 0;
@ -1468,7 +1449,7 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
GE( glGetTexLevelParameteriv (gl_target, 0,
GL_TEXTURE_HEIGHT,
&gl_height) );
GE( glGetTexParameteriv (gl_target,
GL_TEXTURE_MIN_FILTER,
&gl_min_filter) );
@ -1501,8 +1482,6 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
return COGL_INVALID_HANDLE;
}
bpp = _cogl_get_format_bpp (format);
/* Create new texture */
tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture));
@ -1513,6 +1492,7 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
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;
@ -1737,9 +1717,11 @@ cogl_texture_set_filters (CoglHandle handle,
for (i=0; i<tex->slice_gl_handles->len; ++i)
{
gl_handle = g_array_index (tex->slice_gl_handles, GLuint, i);
GE( glBindTexture (tex->gl_target, gl_handle) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER, tex->mag_filter) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER, tex->min_filter) );
GE( glBindTexture (tex->gl_target, gl_handle) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER,
tex->mag_filter) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER,
tex->min_filter) );
}
}
@ -1935,7 +1917,7 @@ _cogl_texture_quad_sw (CoglTexture *tex,
CoglFixed tx2,
CoglFixed ty2)
{
CoglSpanIter iter_x , iter_y;
CoglSpanIter iter_x , iter_y;
CoglFixed tw , th;
CoglFixed tqx , tqy;
CoglFixed first_tx , first_ty;
@ -1944,18 +1926,21 @@ _cogl_texture_quad_sw (CoglTexture *tex,
CoglFixed slice_tx2 , slice_ty2;
CoglFixed slice_qx1 , slice_qy1;
CoglFixed slice_qx2 , slice_qy2;
GLuint gl_handle;
gulong enable_flags = 0;
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 */
enable_flags |= COGL_ENABLE_TEXTURE_2D;
/* Prepare GL state */
if (ctx->color_alpha < 255
|| tex->bitmap.format & COGL_A_BIT)
{
@ -1964,9 +1949,9 @@ _cogl_texture_quad_sw (CoglTexture *tex,
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
flipped but we can still use the same algorithm to iterate the
@ -1990,6 +1975,9 @@ _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);
@ -2083,25 +2071,21 @@ _cogl_texture_quad_sw (CoglTexture *tex,
iter_x.index);
GE( glBindTexture (tex->gl_target, gl_handle) );
#define CFX_F COGL_FIXED_TO_FLOAT
/* Draw textured quad */
glBegin (GL_QUADS);
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);
glTexCoord2f (CFX_F(slice_tx1), CFX_F(slice_ty1));
glVertex2f (CFX_F(slice_qx1), CFX_F(slice_qy1));
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);
glTexCoord2f (CFX_F(slice_tx1), CFX_F(slice_ty2));
glVertex2f (CFX_F(slice_qx1), CFX_F(slice_qy2));
glTexCoord2f (CFX_F(slice_tx2), CFX_F(slice_ty2));
glVertex2f (CFX_F(slice_qx2), CFX_F(slice_qy2));
glTexCoord2f (CFX_F(slice_tx2), CFX_F(slice_ty1));
glVertex2f (CFX_F(slice_qx2), CFX_F(slice_qy1));
GE( glEnd () );
GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
#undef CFX_F
}
@ -2119,11 +2103,15 @@ _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;
GLuint gl_handle;
gulong enable_flags = 0;
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
@ -2131,8 +2119,6 @@ _cogl_texture_quad_hw (CoglTexture *tex,
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* Prepare GL state */
enable_flags |= COGL_ENABLE_TEXTURE_2D;
if (ctx->color_alpha < 255
|| tex->bitmap.format & COGL_A_BIT)
{
@ -2144,10 +2130,14 @@ _cogl_texture_quad_hw (CoglTexture *tex,
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 */
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);
@ -2160,21 +2150,17 @@ _cogl_texture_quad_hw (CoglTexture *tex,
#define CFX_F(x) COGL_FIXED_TO_FLOAT(x)
/* Draw textured quad */
glBegin (GL_QUADS);
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);
glTexCoord2f (CFX_F(tx1), CFX_F(ty1));
glVertex2f (CFX_F(x1), CFX_F(y1));
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);
glTexCoord2f (CFX_F(tx1), CFX_F(ty2));
glVertex2f (CFX_F(x1), CFX_F(y2));
glTexCoord2f (CFX_F(tx2), CFX_F(ty2));
glVertex2f (CFX_F(x2), CFX_F(y2));
glTexCoord2f (CFX_F(tx2), CFX_F(ty1));
glVertex2f (CFX_F(x2), CFX_F(y1));
GE( glEnd () );
GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
#undef CFX_F
}
@ -2216,11 +2202,11 @@ cogl_texture_rectangle (CoglHandle handle,
}
else
{
if (tex->slice_gl_handles->len == 1 &&
tx1 >= -COGL_FIXED_1 &&
tx2 <= COGL_FIXED_1 &&
ty1 >= -COGL_FIXED_1 &&
ty2 <= COGL_FIXED_1)
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);
}
@ -2238,10 +2224,11 @@ cogl_texture_polygon (CoglHandle handle,
gboolean use_color)
{
CoglTexture *tex;
int i, x, y, vnum;
int i, x, y;
GLuint gl_handle;
CoglTexSliceSpan *y_span, *x_span;
gulong enable_flags;
CoglTextureGLVertex *p;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -2250,7 +2237,7 @@ cogl_texture_polygon (CoglHandle handle,
return;
tex = _cogl_texture_pointer_from_handle (handle);
/* The polygon will have artifacts where the slices join if the wrap
mode is GL_LINEAR because the filtering will pull in pixels from
the transparent border. To make it clear that the function
@ -2271,14 +2258,48 @@ cogl_texture_polygon (CoglHandle handle,
return;
}
tex = _cogl_texture_pointer_from_handle (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));
}
/* Prepare GL state */
enable_flags = COGL_ENABLE_TEXTURE_2D | COGL_ENABLE_BLEND;
enable_flags = (COGL_ENABLE_TEXTURE_2D
| COGL_ENABLE_VERTEX_ARRAY
| COGL_ENABLE_TEXCOORD_ARRAY
| COGL_ENABLE_BLEND);
if (ctx->enable_backface_culling)
enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
if (use_color)
{
enable_flags |= COGL_ENABLE_COLOR_ARRAY;
GE( glColorPointer (4, GL_UNSIGNED_BYTE, sizeof (CoglTextureGLVertex),
ctx->texture_vertices[0].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) );
cogl_enable (enable_flags);
/* Temporarily change the wrapping mode on all of the slices to use
@ -2308,34 +2329,30 @@ cogl_texture_polygon (CoglHandle handle,
gl_handle = g_array_index (tex->slice_gl_handles, GLuint, i++);
GE( glBindTexture (tex->gl_target, gl_handle) );
glBegin (GL_TRIANGLE_FAN);
for (vnum = 0; vnum < n_vertices; vnum++)
/* 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++)
{
GLfloat tx, ty;
#define CFX_F COGL_FIXED_TO_FLOAT
if (use_color)
cogl_set_source_color (&vertices[vnum].color);
p->v[0] = CFX_F(vertices[i].x);
p->v[1] = CFX_F(vertices[i].y);
p->v[2] = CFX_F(vertices[i].z);
p->t[0] = CFX_F(vertices[i].tx
* (x_span->size - x_span->waste) / x_span->size);
p->t[1] = CFX_F(vertices[i].ty
* (y_span->size - y_span->waste) / y_span->size);
p->c[0] = cogl_color_get_red_byte(&vertices[i].color);
p->c[1] = cogl_color_get_green_byte(&vertices[i].color);
p->c[2] = cogl_color_get_blue_byte(&vertices[i].color);
p->c[3] = cogl_color_get_alpha_byte(&vertices[i].color);
/* Transform the texture co-ordinates so they are
relative to the slice */
tx = (COGL_FIXED_TO_FLOAT (vertices[vnum].tx)
- x_span->start / (GLfloat) tex->bitmap.width)
* tex->bitmap.width / x_span->size;
ty = (COGL_FIXED_TO_FLOAT (vertices[vnum].ty)
- y_span->start / (GLfloat) tex->bitmap.height)
* tex->bitmap.height / y_span->size;
glTexCoord2f (tx, ty);
glVertex3f (COGL_FIXED_TO_FLOAT (vertices[vnum].x),
COGL_FIXED_TO_FLOAT (vertices[vnum].y),
COGL_FIXED_TO_FLOAT (vertices[vnum].z));
#undef CFX_F
}
GE( glEnd () );
GE( glBindTexture (tex->gl_target, gl_handle) );
GE( glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) );
}
}

View File

@ -327,6 +327,9 @@ cogl_enable (gulong flags)
COGL_ENABLE_TEXCOORD_ARRAY,
GL_TEXTURE_COORD_ARRAY);
cogl_toggle_client_flag (ctx, flags,
COGL_ENABLE_COLOR_ARRAY,
GL_COLOR_ARRAY);
}
gulong

View File

@ -32,9 +32,9 @@
typedef struct
{
GLfixed v[3];
GLfixed t[2];
GLfixed c[4];
GLfloat v[3];
GLfloat t[2];
GLubyte c[4];
} CoglTextureGLVertex;
typedef struct

View File

@ -55,6 +55,7 @@ struct _CoglTexture
COGLenum min_filter;
COGLenum mag_filter;
gboolean is_foreign;
GLint wrap_mode;
gboolean auto_mipmap;
};

File diff suppressed because it is too large Load Diff