cogl: Add a texture utility function for manually repeating
Given a region of texture coordinates this utility invokes a callback enough times to cover the region with a subregion that spans the texture at most once. Eg, if called with tx1 and tx2 as 0.5 and 3.0 it it would invoke the callback with: 0.5,1.0 1.0,2.0 2.0,3.0 Manual repeating is needed by all texture backends regardless of whether they can support hardware repeating because when Cogl calls the foreach_sub_texture_in_region method then it sets the wrap mode to GL_CLAMP_TO_EDGE and no hardware repeating is possible.
This commit is contained in:
parent
5fcb29c916
commit
1a1de0e278
@ -41,6 +41,9 @@ typedef void (*CoglTextureSliceCallback) (CoglHandle handle,
|
|||||||
float *virtual_coords,
|
float *virtual_coords,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
|
typedef void (* CoglTextureManualRepeatCallback) (const float *coords,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
struct _CoglTextureVtable
|
struct _CoglTextureVtable
|
||||||
{
|
{
|
||||||
/* Virtual functions that must be implemented for a texture
|
/* Virtual functions that must be implemented for a texture
|
||||||
@ -169,6 +172,17 @@ _cogl_texture_prep_gl_alignment_for_pixels_upload (int pixels_rowstride);
|
|||||||
void
|
void
|
||||||
_cogl_texture_prep_gl_alignment_for_pixels_download (int pixels_rowstride);
|
_cogl_texture_prep_gl_alignment_for_pixels_download (int pixels_rowstride);
|
||||||
|
|
||||||
|
/* Utility function for implementing manual repeating. Even texture
|
||||||
|
backends that always support hardware repeating need this because
|
||||||
|
when foreach_sub_texture_in_region is invoked Cogl will set the
|
||||||
|
wrap mode to GL_CLAMP_TO_EDGE so hardware repeating can't be
|
||||||
|
done */
|
||||||
|
void
|
||||||
|
_cogl_texture_iterate_manual_repeats (CoglTextureManualRepeatCallback callback,
|
||||||
|
float tx_1, float ty_1,
|
||||||
|
float tx_2, float ty_2,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
/* Utility function to use as a fallback for getting the data of any
|
/* Utility function to use as a fallback for getting the data of any
|
||||||
texture via the framebuffer */
|
texture via the framebuffer */
|
||||||
|
|
||||||
|
@ -195,6 +195,108 @@ _cogl_texture_upload_data_prepare (CoglTextureUploadData *data,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
_cogl_texture_upload_data_prepare (CoglTextureUploadData *data,
|
||||||
|
CoglPixelFormat internal_format)
|
||||||
|
{
|
||||||
|
return (_cogl_texture_upload_data_prepare_format (data, &internal_format) &&
|
||||||
|
_cogl_texture_upload_data_convert (data, internal_format));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is like CoglSpanIter except it deals with floats and it
|
||||||
|
effectively assumes there is only one span from 0.0 to 1.0 */
|
||||||
|
typedef struct _CoglTextureIter
|
||||||
|
{
|
||||||
|
gfloat pos, end, next_pos;
|
||||||
|
gboolean flipped;
|
||||||
|
gfloat t_1, t_2;
|
||||||
|
} CoglTextureIter;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_texture_iter_update (CoglTextureIter *iter)
|
||||||
|
{
|
||||||
|
gfloat t_2;
|
||||||
|
|
||||||
|
modff (iter->pos, &iter->next_pos);
|
||||||
|
|
||||||
|
/* modff rounds the int part towards zero so we need to add one if
|
||||||
|
we're meant to be heading away from zero */
|
||||||
|
if (iter->pos >= 0.0f)
|
||||||
|
iter->next_pos += 1.0f;
|
||||||
|
|
||||||
|
if (iter->next_pos > iter->end)
|
||||||
|
t_2 = iter->end;
|
||||||
|
else
|
||||||
|
t_2 = iter->next_pos;
|
||||||
|
|
||||||
|
if (iter->flipped)
|
||||||
|
{
|
||||||
|
iter->t_1 = t_2;
|
||||||
|
iter->t_2 = iter->pos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iter->t_1 = iter->pos;
|
||||||
|
iter->t_2 = t_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_texture_iter_begin (CoglTextureIter *iter,
|
||||||
|
gfloat t_1, gfloat t_2)
|
||||||
|
{
|
||||||
|
if (t_1 <= t_2)
|
||||||
|
{
|
||||||
|
iter->pos = t_1;
|
||||||
|
iter->end = t_2;
|
||||||
|
iter->flipped = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
iter->pos = t_2;
|
||||||
|
iter->end = t_1;
|
||||||
|
iter->flipped = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cogl_texture_iter_update (iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_cogl_texture_iter_next (CoglTextureIter *iter)
|
||||||
|
{
|
||||||
|
iter->pos = iter->next_pos;
|
||||||
|
_cogl_texture_iter_update (iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_cogl_texture_iter_end (CoglTextureIter *iter)
|
||||||
|
{
|
||||||
|
return iter->pos >= iter->end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This invokes the callback with enough quads to cover the manually
|
||||||
|
repeated range specified by the virtual texture coordinates without
|
||||||
|
emitting coordinates outside the range [0,1] */
|
||||||
|
void
|
||||||
|
_cogl_texture_iterate_manual_repeats (CoglTextureManualRepeatCallback callback,
|
||||||
|
float tx_1, float ty_1,
|
||||||
|
float tx_2, float ty_2,
|
||||||
|
void *user_data)
|
||||||
|
{
|
||||||
|
CoglTextureIter x_iter, y_iter;
|
||||||
|
|
||||||
|
for (_cogl_texture_iter_begin (&y_iter, ty_1, ty_2);
|
||||||
|
!_cogl_texture_iter_end (&y_iter);
|
||||||
|
_cogl_texture_iter_next (&y_iter))
|
||||||
|
for (_cogl_texture_iter_begin (&x_iter, tx_1, tx_2);
|
||||||
|
!_cogl_texture_iter_end (&x_iter);
|
||||||
|
_cogl_texture_iter_next (&x_iter))
|
||||||
|
{
|
||||||
|
float coords[4] = { x_iter.t_1, y_iter.t_1, x_iter.t_2, y_iter.t_2 };
|
||||||
|
callback (coords, user_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CoglHandle
|
CoglHandle
|
||||||
cogl_texture_new_with_size (guint width,
|
cogl_texture_new_with_size (guint width,
|
||||||
guint height,
|
guint height,
|
||||||
|
Loading…
Reference in New Issue
Block a user