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 */
@ -57,6 +64,8 @@ typedef struct
/* Textures */
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 (GL_UNPACK_ALIGNMENT, 1) );
}
GE( glPixelStorei (SKIP_ROWS, src_y) );
GE( glPixelStorei (SKIP_PIXELS, src_x) );
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,
prep_for_gl_pixels_upload (tex->bitmap.rowstride,
x_span->start,
y_span->start,
FALSE);
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,
@ -404,14 +396,13 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
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) );
@ -429,33 +420,20 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
}
else
{
/* Setup gl alignment to match rowstride and top-left corner */
GLvoid *dst = target_bmp->data
+ x_span->start * bpp
+ y_span->start * target_bmp->rowstride;
/* 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
_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) );
}
}
}
@ -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,
prep_for_gl_pixels_upload (source_bmp->rowstride,
source_x,
source_y,
FALSE);
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,
@ -946,9 +923,12 @@ _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) );
@ -956,7 +936,8 @@ _cogl_texture_slices_create (CoglTexture *tex)
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
@ -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;
@ -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;
@ -1738,8 +1718,10 @@ cogl_texture_set_filters (CoglHandle handle,
{
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( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER,
tex->mag_filter) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER,
tex->min_filter) );
}
}
@ -1944,8 +1926,12 @@ _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 = 0;
gulong enable_flags = (COGL_ENABLE_TEXTURE_2D
| COGL_ENABLE_VERTEX_ARRAY
| COGL_ENABLE_TEXCOORD_ARRAY);
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -1953,9 +1939,8 @@ _cogl_texture_quad_sw (CoglTexture *tex,
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)
{
@ -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);
@ -2087,21 +2075,17 @@ _cogl_texture_quad_sw (CoglTexture *tex,
#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,10 +2103,14 @@ _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");
@ -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);
@ -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;
};

View File

@ -39,6 +39,13 @@
#include <string.h>
#include <stdlib.h>
#define glVertexPointer cogl_wrap_glVertexPointer
#define glTexCoordPointer cogl_wrap_glTexCoordPointer
#define glColorPointer cogl_wrap_glColorPointer
#define glDrawArrays cogl_wrap_glDrawArrays
#define glTexParameteri cogl_wrap_glTexParameteri
/*
#define COGL_DEBUG 1
@ -174,6 +181,36 @@ _cogl_span_iter_end (CoglSpanIter *iter)
return iter->pos >= iter->cover_end;
}
static void
prep_for_gl_pixels_upload (gint pixels_rowstride,
gint pixels_src_x,
gint pixels_src_y,
gint pixels_bpp)
{
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
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 *
_cogl_texture_allocate_waste_buffer (CoglTexture *tex)
{
@ -214,10 +251,6 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
guchar *waste_buf;
CoglBitmap slice_bmp;
/* FIXME: might optimize by not copying to intermediate slice
bitmap when source rowstride = bpp * width and the texture
image is not sliced */
bpp = _cogl_get_format_bpp (tex->bitmap.format);
waste_buf = _cogl_texture_allocate_waste_buffer (tex);
@ -236,6 +269,10 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
y * tex->slice_x_spans->len + x);
/* FIXME: might optimize by not copying to intermediate slice
bitmap when source rowstride = bpp * width and the texture
image is not sliced */
/* Setup temp bitmap for slice subregion */
slice_bmp.format = tex->bitmap.format;
slice_bmp.width = x_span->size - x_span->waste;
@ -244,6 +281,12 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
slice_bmp.data = (guchar*) g_malloc (slice_bmp.rowstride *
slice_bmp.height);
/* Setup gl alignment to match rowstride and top-left corner */
prep_for_gl_pixels_upload (tex->bitmap.rowstride,
0,
0,
bpp);
/* Copy subregion data */
_cogl_bitmap_copy_subregion (&tex->bitmap,
&slice_bmp,
@ -257,9 +300,9 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle,
tex->gl_intformat) );
GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 1) );
GE( glTexSubImage2D (tex->gl_target, 0, 0, 0,
GE( glTexSubImage2D (tex->gl_target, 0,
0,
0,
slice_bmp.width,
slice_bmp.height,
tex->gl_format, tex->gl_type,
@ -284,8 +327,14 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
src += tex->bitmap.rowstride;
}
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,
@ -313,8 +362,14 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
}
}
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,
@ -371,7 +426,7 @@ _cogl_texture_draw_and_read (CoglTexture *tex,
0, 0, COGL_FIXED_1, COGL_FIXED_1);
/* Read into target bitmap */
GE( glPixelStorei (GL_PACK_ALIGNMENT, 1) );
prep_for_gl_pixels_download (tex->bitmap.rowstride);
GE( glReadPixels (viewport[0], viewport[1],
tex->bitmap.width,
tex->bitmap.height,
@ -430,7 +485,7 @@ _cogl_texture_draw_and_read (CoglTexture *tex,
rect_bmp.data = (guchar*) g_malloc (rect_bmp.rowstride *
rect_bmp.height);
GE( glPixelStorei (GL_PACK_ALIGNMENT, 1) );
prep_for_gl_pixels_download (rect_bmp.rowstride);
GE( glReadPixels (viewport[0], viewport[1],
rect_bmp.width,
rect_bmp.height,
@ -603,10 +658,6 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
waste_buf = _cogl_texture_allocate_waste_buffer (tex);
/* FIXME: might optimize by not copying to intermediate slice
bitmap when source rowstride = bpp * width and the texture
image is not sliced */
/* Iterate vertical spans */
for (source_y = src_y,
_cogl_span_iter_begin (&y_iter, tex->slice_y_spans,
@ -618,7 +669,7 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
_cogl_span_iter_next (&y_iter),
source_y += inter_h )
{
/* Skip non-intersecting ones */
/* Discard slices out of the subregion early */
if (!y_iter.intersects)
{
inter_h = 0;
@ -639,7 +690,7 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
_cogl_span_iter_next (&x_iter),
source_x += inter_w )
{
/* Skip non-intersecting ones */
/* Discard slices out of the subregion early */
if (!x_iter.intersects)
{
inter_w = 0;
@ -666,6 +717,10 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
y_iter.index * tex->slice_x_spans->len +
x_iter.index);
/* FIXME: might optimize by not copying to intermediate slice
bitmap when source rowstride = bpp * width and the texture
image is not sliced */
/* Setup temp bitmap for slice subregion */
slice_bmp.format = tex->bitmap.format;
slice_bmp.width = inter_w;
@ -674,6 +729,12 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
slice_bmp.data = (guchar*) g_malloc (slice_bmp.rowstride *
slice_bmp.height);
/* Setup gl alignment to match rowstride and top-left corner */
prep_for_gl_pixels_upload (slice_bmp.rowstride,
0, /* src x */
0, /* src y */
bpp);
/* Copy subregion data */
_cogl_bitmap_copy_subregion (source_bmp,
&slice_bmp,
@ -684,8 +745,6 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
slice_bmp.height);
/* Upload new image data */
GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 1) );
GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle,
tex->gl_intformat) );
@ -703,14 +762,20 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
&& local_x < x_span->size - x_span->waste
&& local_x + inter_w >= x_span->size - x_span->waste)
{
const guchar *src = source_bmp->data
+ (src_y + COGL_FIXED_TO_INT (y_iter.intersect_start)
- dst_y) * source_bmp->rowstride
+ (src_x + x_span->start + x_span->size - x_span->waste
- dst_x - 1) * bpp;
guchar *dst = waste_buf;
const guchar *src;
guchar *dst;
guint wx, wy;
src = source_bmp->data
+ (src_y + COGL_FIXED_TO_INT (y_iter.intersect_start)
- dst_y)
* source_bmp->rowstride
+ (src_x + x_span->start + x_span->size - x_span->waste
- dst_x - 1)
* bpp;
dst = waste_buf;
for (wy = 0; wy < inter_h; wy++)
{
for (wx = 0; wx < x_span->waste; wx++)
@ -721,8 +786,14 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
src += source_bmp->rowstride;
}
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,
@ -735,15 +806,21 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
&& local_y < y_span->size - y_span->waste
&& local_y + inter_h >= y_span->size - y_span->waste)
{
const guchar *src = source_bmp->data
+ (src_x + COGL_FIXED_TO_INT (x_iter.intersect_start)
- dst_x) * bpp
+ (src_y + y_span->start + y_span->size - y_span->waste
- dst_y - 1) * source_bmp->rowstride;
guchar *dst = waste_buf;
const guchar *src;
guchar *dst;
guint wy, wx;
guint copy_width;
src = source_bmp->data
+ (src_x + COGL_FIXED_TO_INT (x_iter.intersect_start)
- dst_x)
* bpp
+ (src_y + y_span->start + y_span->size - y_span->waste
- dst_y - 1)
* source_bmp->rowstride;
dst = waste_buf;
if (local_x + inter_w >= x_span->size - x_span->waste)
copy_width = x_span->size - local_x;
else
@ -761,8 +838,14 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
}
}
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,
@ -784,6 +867,41 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
return TRUE;
}
static gint
_cogl_rect_slices_for_size (gint size_to_fill,
gint max_span_size,
gint max_waste,
GArray *out_spans)
{
gint n_spans = 0;
CoglTexSliceSpan span;
/* Init first slice span */
span.start = 0;
span.size = max_span_size;
span.waste = 0;
/* Repeat until whole area covered */
while (size_to_fill >= span.size)
{
/* Add another slice span of same size */
if (out_spans) g_array_append_val (out_spans, span);
span.start += span.size;
size_to_fill -= span.size;
n_spans++;
}
/* Add one last smaller slice span */
if (size_to_fill > 0)
{
span.size = size_to_fill;
if (out_spans) g_array_append_val (out_spans, span);
n_spans++;
}
return n_spans;
}
static gint
_cogl_pot_slices_for_size (gint size_to_fill,
gint max_span_size,
@ -863,10 +981,20 @@ _cogl_texture_slices_create (CoglTexture *tex)
bpp = _cogl_get_format_bpp (tex->bitmap.format);
/* Initialize size of largest slice according to supported features */
if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT))
{
max_width = tex->bitmap.width;
max_height = tex->bitmap.height;
tex->gl_target = GL_TEXTURE_2D;
slices_for_size = _cogl_rect_slices_for_size;
}
else
{
max_width = cogl_util_next_p2 (tex->bitmap.width);
max_height = cogl_util_next_p2 (tex->bitmap.height);
tex->gl_target = GL_TEXTURE_2D;
slices_for_size = _cogl_pot_slices_for_size;
}
/* Negative number means no slicing forced by the user */
if (tex->max_waste <= -1)
@ -961,6 +1089,14 @@ _cogl_texture_slices_create (CoglTexture *tex)
g_array_set_size (tex->slice_gl_handles, n_slices);
/* Hardware repeated tiling if supported, else tile in software*/
if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT)
&& n_slices == 1)
tex->wrap_mode = GL_REPEAT;
else
tex->wrap_mode = GL_CLAMP_TO_EDGE;
/* Generate a "working set" of GL texture objects
* (some implementations might supported faster
* re-binding between textures inside a set) */
@ -988,18 +1124,18 @@ _cogl_texture_slices_create (CoglTexture *tex)
GE( cogl_gles2_wrapper_bind_texture (tex->gl_target,
gl_handles[y * n_x_slices + x],
tex->gl_intformat) );
GE( cogl_wrap_glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER,
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER,
tex->mag_filter) );
GE( cogl_wrap_glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER,
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER,
tex->min_filter) );
GE( cogl_wrap_glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE) );
GE( cogl_wrap_glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE) );
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( cogl_wrap_glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP,
GE( glTexParameteri (tex->gl_target, GL_GENERATE_MIPMAP,
GL_TRUE) );
/* Pass NULL data to init size and internal format */
@ -1033,13 +1169,20 @@ _cogl_texture_slices_free (CoglTexture *tex)
}
}
static gboolean
_cogl_pixel_format_from_gl_internal (GLenum gl_int_format,
CoglPixelFormat *out_format)
{
return TRUE;
}
static CoglPixelFormat
_cogl_pixel_format_to_gl (CoglPixelFormat format,
GLenum *out_glintformat,
GLenum *out_glformat,
GLenum *out_gltype)
{
CoglPixelFormat required_format = format;
CoglPixelFormat required_format;
GLenum glintformat = 0;
GLenum glformat = 0;
GLenum gltype = 0;
@ -1050,6 +1193,10 @@ _cogl_pixel_format_to_gl (CoglPixelFormat format,
if (format & COGL_PREMULT_BIT)
format = (format & COGL_UNPREMULT_MASK);
/* Everything else accepted
* (FIXME: check YUV support) */
required_format = format;
/* Find GL equivalents */
switch (format)
{
@ -1213,6 +1360,7 @@ cogl_texture_new_with_size (guint width,
&tex->gl_format,
&tex->gl_type);
/* Create slices for the given format and size */
if (!_cogl_texture_slices_create (tex))
{
_cogl_texture_free (tex);
@ -1294,7 +1442,7 @@ cogl_texture_new_from_data (guint width,
_cogl_texture_bitmap_free (tex);
return _cogl_texture_handle_new (tex);;
return _cogl_texture_handle_new (tex);
}
CoglHandle
@ -1382,8 +1530,19 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
GLuint y_pot_waste,
CoglPixelFormat format)
{
/* NOTE: width, height and internal format are not queriable
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;
GLboolean gl_istexture;
GLint gl_compressed = GL_FALSE;
GLint gl_int_format = 0;
GLint gl_width = 0;
GLint gl_height = 0;
GLint gl_min_filter;
GLint gl_mag_filter;
GLint gl_gen_mipmap;
@ -1410,7 +1569,7 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
/* Obtain texture parameters
(only level 0 we are interested in) */
/* These are not queriable in GLES :(
#if HAVE_COGL_GL
GE( glGetTexLevelParameteriv (gl_target, 0,
GL_TEXTURE_COMPRESSED,
&gl_compressed) );
@ -1418,7 +1577,20 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
GE( glGetTexLevelParameteriv (gl_target, 0,
GL_TEXTURE_INTERNAL_FORMAT,
&gl_int_format) );
*/
GE( glGetTexLevelParameteriv (gl_target, 0,
GL_TEXTURE_WIDTH,
&gl_width) );
GE( glGetTexLevelParameteriv (gl_target, 0,
GL_TEXTURE_HEIGHT,
&gl_height) );
#else
gl_width = width + x_pot_waste;
gl_height = height + y_pot_waste;
#endif
GE( glGetTexParameteriv (gl_target,
GL_TEXTURE_MIN_FILTER,
&gl_min_filter) );
@ -1432,14 +1604,25 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
&gl_gen_mipmap) );
/* Validate width and height */
if (width <= 0 || height <= 0)
if (gl_width <= 0 || gl_height <= 0)
return COGL_INVALID_HANDLE;
/* Validate pot waste */
if (x_pot_waste < 0 || x_pot_waste >= width ||
y_pot_waste < 0 || y_pot_waste >= height)
if (x_pot_waste < 0 || x_pot_waste >= gl_width ||
y_pot_waste < 0 || y_pot_waste >= gl_height)
return COGL_INVALID_HANDLE;
/* Compressed texture images not supported */
if (gl_compressed == GL_TRUE)
return COGL_INVALID_HANDLE;
/* Try and match to a cogl format */
if (!_cogl_pixel_format_from_gl_internal (gl_int_format,
&format))
{
return COGL_INVALID_HANDLE;
}
/* Create new texture */
tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture));
@ -1452,15 +1635,15 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
bpp = _cogl_get_format_bpp (format);
tex->bitmap.format = format;
tex->bitmap.width = width;
tex->bitmap.height = height;
tex->bitmap.width = gl_width - x_pot_waste;
tex->bitmap.height = gl_height - y_pot_waste;
tex->bitmap.rowstride = tex->bitmap.width * bpp;
tex->bitmap_owner = FALSE;
tex->gl_target = gl_target;
tex->gl_intformat = 0;
tex->gl_format = 0;
tex->gl_type = 0;
tex->gl_intformat = gl_int_format;
tex->gl_format = gl_int_format;
tex->gl_type = GL_UNSIGNED_BYTE;
tex->min_filter = gl_min_filter;
tex->mag_filter = gl_mag_filter;
@ -1481,57 +1664,35 @@ cogl_texture_new_from_foreign (GLuint gl_handle,
/* Store info for a single slice */
x_span.start = 0;
x_span.size = width + x_pot_waste;
x_span.size = gl_width;
x_span.waste = x_pot_waste;
g_array_append_val (tex->slice_x_spans, x_span);
y_span.start = 0;
y_span.size = height + x_pot_waste;
y_span.size = gl_height;
y_span.waste = y_pot_waste;
g_array_append_val (tex->slice_y_spans, y_span);
g_array_append_val (tex->slice_gl_handles, gl_handle);
/* Force appropriate wrap parameter */
GE( cogl_wrap_glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S,
GL_CLAMP_TO_EDGE) );
GE( cogl_wrap_glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T,
GL_CLAMP_TO_EDGE) );
return _cogl_texture_handle_new (tex);
if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT) &&
gl_target == GL_TEXTURE_2D)
{
/* Hardware repeated tiling */
tex->wrap_mode = GL_REPEAT;
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S, GL_REPEAT) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T, GL_REPEAT) );
}
else
{
/* Any tiling will be done in software */
tex->wrap_mode = GL_CLAMP_TO_EDGE;
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE) );
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE) );
}
void
cogl_texture_get_properties (CoglHandle handle,
guint *out_width,
guint *out_height,
CoglPixelFormat *out_format,
guint *out_rowstride,
guint *out_max_waste)
{
CoglTexture *tex;
/* Check if valid texture handle */
if (!cogl_is_texture (handle))
return;
tex = _cogl_texture_pointer_from_handle (handle);
/* Output requested properties */
if (out_width != NULL)
*out_width = tex->bitmap.width;
if (out_height != NULL)
*out_height = tex->bitmap.height;
if (out_format != NULL)
*out_format = tex->bitmap.format;
if (out_rowstride != NULL)
*out_rowstride = tex->bitmap.rowstride;
if (out_max_waste != NULL)
*out_max_waste = tex->max_waste;
return _cogl_texture_handle_new (tex);
}
guint
@ -1698,9 +1859,9 @@ cogl_texture_set_filters (CoglHandle handle,
{
gl_handle = g_array_index (tex->slice_gl_handles, GLuint, i);
GE( glBindTexture (tex->gl_target, gl_handle) );
GE( cogl_wrap_glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER,
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MAG_FILTER,
tex->mag_filter) );
GE( cogl_wrap_glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER,
GE( glTexParameteri (tex->gl_target, GL_TEXTURE_MIN_FILTER,
tex->min_filter) );
}
}
@ -1906,18 +2067,19 @@ _cogl_texture_quad_sw (CoglTexture *tex,
CoglFixed slice_tx2 , slice_ty2;
CoglFixed slice_qx1 , slice_qy1;
CoglFixed slice_qx2 , slice_qy2;
GLfixed tex_coords[8];
GLfixed quad_coords[8];
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
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
/* Prepare GL state */
if (ctx->color_alpha < 255
@ -1954,8 +2116,8 @@ _cogl_texture_quad_sw (CoglTexture *tex,
ty2 = temp;
}
GE( cogl_wrap_glTexCoordPointer (2, GL_FIXED, 0, tex_coords) );
GE( cogl_wrap_glVertexPointer (2, GL_FIXED, 0, quad_coords) );
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);
@ -2001,7 +2163,8 @@ _cogl_texture_quad_sw (CoglTexture *tex,
slice_ty1 = iter_y.intersect_start - iter_y.pos;
slice_ty2 = iter_y.intersect_end - iter_y.pos;
/* Normalize texture coordinates to current slice */
/* Normalize texture coordinates to current slice
(rectangle texture targets take denormalized) */
slice_ty1 /= iter_y.span->size;
slice_ty2 /= iter_y.span->size;
@ -2026,7 +2189,8 @@ _cogl_texture_quad_sw (CoglTexture *tex,
slice_tx1 = iter_x.intersect_start - iter_x.pos;
slice_tx2 = iter_x.intersect_end - iter_x.pos;
/* Normalize texture coordinates to current slice */
/* Normalize texture coordinates to current slice
(rectangle texture targets take denormalized) */
slice_tx1 /= iter_x.span->size;
slice_tx2 /= iter_x.span->size;
@ -2050,18 +2214,22 @@ _cogl_texture_quad_sw (CoglTexture *tex,
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] = slice_tx1; tex_coords[1] = slice_ty2;
tex_coords[2] = slice_tx2; tex_coords[3] = slice_ty2;
tex_coords[4] = slice_tx1; tex_coords[5] = slice_ty1;
tex_coords[6] = slice_tx2; tex_coords[7] = slice_ty1;
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] = slice_qx1; quad_coords[1] = slice_qy2;
quad_coords[2] = slice_qx2; quad_coords[3] = slice_qy2;
quad_coords[4] = slice_qx1; quad_coords[5] = slice_qy1;
quad_coords[6] = slice_qx2; quad_coords[7] = 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);
GE (cogl_wrap_glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
#undef CFX_F
}
}
}
@ -2077,8 +2245,8 @@ _cogl_texture_quad_hw (CoglTexture *tex,
CoglFixed tx2,
CoglFixed ty2)
{
GLfixed tex_coords[8];
GLfixed quad_coords[8];
GLfloat tex_coords[8];
GLfloat quad_coords[8];
GLuint gl_handle;
CoglTexSliceSpan *x_span;
CoglTexSliceSpan *y_span;
@ -2104,8 +2272,8 @@ _cogl_texture_quad_hw (CoglTexture *tex,
cogl_enable (enable_flags);
GE( cogl_wrap_glTexCoordPointer (2, GL_FIXED, 0, tex_coords) );
GE( cogl_wrap_glVertexPointer (2, GL_FIXED, 0, quad_coords) );
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);
@ -2115,23 +2283,29 @@ _cogl_texture_quad_hw (CoglTexture *tex,
/* 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);
/* Don't include the waste in the texture coordinates */
tx1 = tx1 * (x_span->size - x_span->waste) / x_span->size;
tx2 = tx2 * (x_span->size - x_span->waste) / x_span->size;
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)
/* Draw textured quad */
tex_coords[0] = tx1; tex_coords[1] = ty2;
tex_coords[2] = tx2; tex_coords[3] = ty2;
tex_coords[4] = tx1; tex_coords[5] = ty1;
tex_coords[6] = tx2; tex_coords[7] = ty1;
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] = x1; quad_coords[1] = y2;
quad_coords[2] = x2; quad_coords[3] = y2;
quad_coords[4] = x1; quad_coords[5] = y1;
quad_coords[6] = x2; quad_coords[7] = 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);
GE (cogl_wrap_glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
#undef CFX_F
}
void
@ -2163,10 +2337,19 @@ cogl_texture_rectangle (CoglHandle handle,
if (tx1 == tx2 || ty1 == ty2)
return;
/* Tile textured quads */
if (tex->slice_gl_handles->len == 1 &&
tx1 >= -COGL_FIXED_1 && tx2 <= COGL_FIXED_1 &&
ty1 >= -COGL_FIXED_1 && ty2 <= COGL_FIXED_1)
/* 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);
}
@ -2175,6 +2358,7 @@ cogl_texture_rectangle (CoglHandle handle,
_cogl_texture_quad_sw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2);
}
}
}
void
cogl_texture_polygon (CoglHandle handle,
@ -2183,12 +2367,11 @@ cogl_texture_polygon (CoglHandle handle,
gboolean use_color)
{
CoglTexture *tex;
GLuint gl_handle;
gulong enable_flags;
int i;
GLuint gl_handle;
CoglTexSliceSpan *y_span, *x_span;
gulong enable_flags;
CoglTextureGLVertex *p;
CoglTexSliceSpan *x_span;
CoglTexSliceSpan *y_span;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@ -2230,13 +2413,9 @@ cogl_texture_polygon (CoglHandle handle,
ctx->texture_vertices_size = nsize;
if (ctx->texture_vertices)
ctx->texture_vertices = g_realloc (ctx->texture_vertices,
nsize
* sizeof (CoglTextureGLVertex));
else
ctx->texture_vertices = g_malloc (nsize
* sizeof (CoglTextureGLVertex));
}
/* Prepare GL state */
@ -2249,7 +2428,7 @@ cogl_texture_polygon (CoglHandle handle,
else if (use_color)
{
for (i = 0; i < n_vertices; i++)
if (vertices[i].color.alpha < 255)
if (cogl_color_get_alpha_byte(&vertices[i].color) < 255)
{
enable_flags |= COGL_ENABLE_BLEND;
break;
@ -2264,13 +2443,13 @@ cogl_texture_polygon (CoglHandle handle,
if (use_color)
{
enable_flags |= COGL_ENABLE_COLOR_ARRAY;
GE( cogl_wrap_glColorPointer (4, GL_FIXED, sizeof (CoglTextureGLVertex),
GE( glColorPointer (4, GL_UNSIGNED_BYTE, sizeof (CoglTextureGLVertex),
ctx->texture_vertices[0].c) );
}
GE( cogl_wrap_glVertexPointer (3, GL_FIXED, sizeof (CoglTextureGLVertex),
GE( glVertexPointer (3, GL_FLOAT, sizeof (CoglTextureGLVertex),
ctx->texture_vertices[0].v) );
GE( cogl_wrap_glTexCoordPointer (2, GL_FIXED, sizeof (CoglTextureGLVertex),
GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex),
ctx->texture_vertices[0].t) );
cogl_enable (enable_flags);
@ -2279,25 +2458,31 @@ cogl_texture_polygon (CoglHandle handle,
x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0);
y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 0);
/* Convert the vertices into an array of GLfixeds ready to pass to
/* 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++)
{
p->v[0] = vertices[i].x;
p->v[1] = vertices[i].y;
p->v[2] = vertices[i].z;
p->t[0] = vertices[i].tx * (x_span->size - x_span->waste) / x_span->size;
p->t[1] = vertices[i].ty * (y_span->size - y_span->waste) / y_span->size;
p->c[0] = (vertices[i].color.red << 16) / 0xff;
p->c[1] = (vertices[i].color.green << 16) / 0xff;
p->c[2] = (vertices[i].color.blue << 16) / 0xff;
p->c[3] = (vertices[i].color.alpha << 16) / 0xff;
#define CFX_F COGL_FIXED_TO_FLOAT
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);
#undef CFX_F
}
GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle,
tex->gl_intformat) );
GE( cogl_wrap_glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) );
GE( glDrawArrays (GL_TRIANGLE_FAN, 0, n_vertices) );
/* Set the last color so that the cache of the alpha value will work
properly */