2011-10-08 13:13:03 +00:00
|
|
|
/*
|
|
|
|
* Cogl
|
|
|
|
*
|
|
|
|
* An object oriented GL/GLES Abstraction/Utility Layer
|
|
|
|
*
|
|
|
|
* Copyright (C) 2011 Intel Corporation.
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library. If not, see
|
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Robert Bragg <robert@linux.intel.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "cogl-texture.h"
|
|
|
|
#include "cogl-matrix.h"
|
|
|
|
#include "cogl-spans.h"
|
|
|
|
#include "cogl-meta-texture.h"
|
|
|
|
#include "cogl-texture-rectangle-private.h"
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
typedef struct _ForeachData
|
|
|
|
{
|
|
|
|
float meta_region_coords[4];
|
|
|
|
CoglPipelineWrapMode wrap_s;
|
|
|
|
CoglPipelineWrapMode wrap_t;
|
|
|
|
CoglMetaTextureCallback callback;
|
|
|
|
void *user_data;
|
|
|
|
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
|
|
|
|
CoglTexture *padded_textures[9];
|
|
|
|
const float *grid_slice_texture_coords;
|
|
|
|
float slice_offset_s;
|
|
|
|
float slice_offset_t;
|
|
|
|
float slice_range_s;
|
|
|
|
float slice_range_t;
|
|
|
|
} ForeachData;
|
|
|
|
|
|
|
|
static void
|
|
|
|
padded_grid_repeat_cb (CoglTexture *slice_texture,
|
|
|
|
const float *slice_texture_coords,
|
|
|
|
const float *meta_coords,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
ForeachData *data;
|
|
|
|
float mapped_coords[4];
|
|
|
|
|
|
|
|
/* Ignore padding slices for the current grid */
|
|
|
|
if (!slice_texture)
|
|
|
|
return;
|
|
|
|
|
|
|
|
data = user_data;
|
|
|
|
|
|
|
|
/* NB: the slice_texture_coords[] we get here will always be
|
|
|
|
* normalized.
|
|
|
|
*
|
|
|
|
* We now need to map the normalized slice_texture_coords[] we have
|
|
|
|
* here back to the real slice coordinates we saved in the previous
|
|
|
|
* stage...
|
|
|
|
*/
|
|
|
|
mapped_coords[0] =
|
|
|
|
slice_texture_coords[0] * data->slice_range_s + data->slice_offset_s;
|
|
|
|
mapped_coords[1] =
|
|
|
|
slice_texture_coords[1] * data->slice_range_t + data->slice_offset_t;
|
|
|
|
mapped_coords[2] =
|
|
|
|
slice_texture_coords[2] * data->slice_range_s + data->slice_offset_s;
|
|
|
|
mapped_coords[3] =
|
|
|
|
slice_texture_coords[3] * data->slice_range_t + data->slice_offset_t;
|
|
|
|
|
|
|
|
data->callback (slice_texture,
|
|
|
|
mapped_coords, meta_coords, data->user_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
setup_padded_spans (CoglSpan *spans,
|
|
|
|
float start,
|
|
|
|
float end,
|
|
|
|
float range,
|
|
|
|
int *real_index)
|
|
|
|
{
|
|
|
|
int span_index = 0;
|
|
|
|
|
|
|
|
if (start > 0)
|
|
|
|
{
|
|
|
|
spans[0].start = 0;
|
|
|
|
spans[0].size = start;
|
|
|
|
spans[0].waste = 0;
|
|
|
|
span_index++;
|
|
|
|
spans[1].start = spans[0].size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
spans[span_index].start = 0;
|
|
|
|
|
|
|
|
spans[span_index].size = end - start;
|
|
|
|
spans[span_index].waste = 0;
|
|
|
|
*real_index = span_index;
|
|
|
|
span_index++;
|
|
|
|
|
|
|
|
if (end < range)
|
|
|
|
{
|
|
|
|
spans[span_index].start =
|
|
|
|
spans[span_index - 1].start + spans[span_index - 1].size;
|
|
|
|
spans[span_index].size = range - end;
|
|
|
|
spans[span_index].waste = 0;
|
|
|
|
span_index++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return span_index;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This handles each sub-texture within the range [0,1] of our
|
|
|
|
* original meta texture and repeats each one separately across the
|
|
|
|
* users requested virtual texture coordinates.
|
|
|
|
*
|
|
|
|
* A notable advantage of this approach is that we will batch
|
|
|
|
* together callbacks corresponding to the same underlying slice
|
|
|
|
* together.
|
|
|
|
*/
|
2012-03-06 18:21:28 +00:00
|
|
|
static void
|
2011-10-08 13:13:03 +00:00
|
|
|
create_grid_and_repeat_cb (CoglTexture *slice_texture,
|
|
|
|
const float *slice_texture_coords,
|
|
|
|
const float *meta_coords,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
ForeachData *data = user_data;
|
|
|
|
CoglSpan x_spans[3];
|
|
|
|
int n_x_spans;
|
|
|
|
int x_real_index;
|
|
|
|
CoglSpan y_spans[3];
|
|
|
|
int n_y_spans;
|
|
|
|
int y_real_index;
|
|
|
|
|
|
|
|
/* NB: This callback is called for each slice of the meta-texture
|
|
|
|
* in the range [0,1].
|
|
|
|
*
|
|
|
|
* We define a "padded grid" for each slice of the meta-texture in
|
|
|
|
* the range [0,1]. The x axis and y axis grid lines are defined
|
|
|
|
* using CoglSpans.
|
|
|
|
*
|
|
|
|
* The padded grid maps over the meta-texture coordinates in the
|
|
|
|
* range [0,1] but only contains one valid cell that corresponds to
|
|
|
|
* current slice being iterated and all the surrounding cells just
|
|
|
|
* provide padding.
|
|
|
|
*
|
|
|
|
* Once we've defined our padded grid we then repeat that across
|
|
|
|
* the user's original region, calling their callback whenever
|
|
|
|
* we see our current slice - ignoring padding.
|
|
|
|
*
|
|
|
|
* NB: we can assume meta_coords[] are normalized at this point
|
|
|
|
* since TextureRectangles aren't iterated with this code-path.
|
|
|
|
*
|
|
|
|
* NB: spans are always defined using non-normalized coordinates
|
|
|
|
*/
|
|
|
|
n_x_spans = setup_padded_spans (x_spans,
|
|
|
|
meta_coords[0] * data->width,
|
|
|
|
meta_coords[2] * data->width,
|
|
|
|
data->width,
|
|
|
|
&x_real_index);
|
|
|
|
n_y_spans = setup_padded_spans (y_spans,
|
|
|
|
meta_coords[1] * data->height,
|
|
|
|
meta_coords[3] * data->height,
|
|
|
|
data->height,
|
|
|
|
&y_real_index);
|
|
|
|
|
meta-texture: Fix textures[] index
textures[iter_y.index * n_y_spans + iter_x.index]
only works for vertical rectangles when n_x_spans > 0 (ie x != {0} )
is also wrong for horizontal rectangles ( x = {0, 1, 2, 3} , y = {0, 1}
-> second line will start at 2 = iter_y.index * n_y_spans + iter_x.index
-> iteration are 0, 1, 2, 3, \n 2, 3, 4, 5 instead of 0, 1, 2, 3 \n 4, 5, 6, 7
Reviewed-by: Robert Bragg <robert@linux.inte.com>
(cherry picked from commit bf0d187f1b5423b9ce1281aab1333fa2dfb9863f)
2012-08-31 07:17:55 +00:00
|
|
|
data->padded_textures[n_x_spans * y_real_index + x_real_index] =
|
2011-10-08 13:13:03 +00:00
|
|
|
slice_texture;
|
|
|
|
|
|
|
|
/* Our callback is going to be passed normalized slice texture
|
|
|
|
* coordinates, and we will need to map the range [0,1] to the real
|
|
|
|
* slice_texture_coords we have here... */
|
|
|
|
data->grid_slice_texture_coords = slice_texture_coords;
|
|
|
|
data->slice_range_s = fabs (data->grid_slice_texture_coords[2] -
|
|
|
|
data->grid_slice_texture_coords[0]);
|
|
|
|
data->slice_range_t = fabs (data->grid_slice_texture_coords[3] -
|
|
|
|
data->grid_slice_texture_coords[1]);
|
|
|
|
data->slice_offset_s = MIN (data->grid_slice_texture_coords[0],
|
|
|
|
data->grid_slice_texture_coords[2]);
|
|
|
|
data->slice_offset_t = MIN (data->grid_slice_texture_coords[1],
|
|
|
|
data->grid_slice_texture_coords[3]);
|
|
|
|
|
|
|
|
/* Now actually iterate the region the user originally requested
|
|
|
|
* using the current padded grid */
|
|
|
|
_cogl_texture_spans_foreach_in_region (x_spans,
|
|
|
|
n_x_spans,
|
|
|
|
y_spans,
|
|
|
|
n_y_spans,
|
|
|
|
data->padded_textures,
|
|
|
|
data->meta_region_coords,
|
|
|
|
data->width,
|
|
|
|
data->height,
|
|
|
|
data->wrap_s,
|
|
|
|
data->wrap_t,
|
|
|
|
padded_grid_repeat_cb,
|
|
|
|
data);
|
|
|
|
|
|
|
|
/* Clear the padded_textures ready for the next iteration */
|
meta-texture: Fix textures[] index
textures[iter_y.index * n_y_spans + iter_x.index]
only works for vertical rectangles when n_x_spans > 0 (ie x != {0} )
is also wrong for horizontal rectangles ( x = {0, 1, 2, 3} , y = {0, 1}
-> second line will start at 2 = iter_y.index * n_y_spans + iter_x.index
-> iteration are 0, 1, 2, 3, \n 2, 3, 4, 5 instead of 0, 1, 2, 3 \n 4, 5, 6, 7
Reviewed-by: Robert Bragg <robert@linux.inte.com>
(cherry picked from commit bf0d187f1b5423b9ce1281aab1333fa2dfb9863f)
2012-08-31 07:17:55 +00:00
|
|
|
data->padded_textures[n_x_spans * y_real_index + x_real_index] = NULL;
|
2011-10-08 13:13:03 +00:00
|
|
|
}
|
|
|
|
|
2011-10-27 13:31:15 +00:00
|
|
|
#define SWAP(A,B) do { float tmp = B; B = A; A = tmp; } while (0)
|
|
|
|
|
|
|
|
typedef struct _ClampData
|
|
|
|
{
|
|
|
|
float start;
|
|
|
|
float end;
|
Switch use of primitive glib types to c99 equivalents
The coding style has for a long time said to avoid using redundant glib
data types such as gint or gchar etc because we feel that they make the
code look unnecessarily foreign to developers coming from outside of the
Gnome developer community.
Note: When we tried to find the historical rationale for the types we
just found that they were apparently only added for consistent syntax
highlighting which didn't seem that compelling.
Up until now we have been continuing to use some of the platform
specific type such as gint{8,16,32,64} and gsize but this patch switches
us over to using the standard c99 equivalents instead so we can further
ensure that our code looks familiar to the widest range of C developers
who might potentially contribute to Cogl.
So instead of using the gint{8,16,32,64} and guint{8,16,32,64} types this
switches all Cogl code to instead use the int{8,16,32,64}_t and
uint{8,16,32,64}_t c99 types instead.
Instead of gsize we now use size_t
For now we are not going to use the c99 _Bool type and instead we have
introduced a new CoglBool type to use instead of gboolean.
Reviewed-by: Neil Roberts <neil@linux.intel.com>
(cherry picked from commit 5967dad2400d32ca6319cef6cb572e81bf2c15f0)
2012-04-16 20:56:40 +00:00
|
|
|
CoglBool s_flipped;
|
|
|
|
CoglBool t_flipped;
|
2011-10-27 13:31:15 +00:00
|
|
|
CoglMetaTextureCallback callback;
|
|
|
|
void *user_data;
|
|
|
|
} ClampData;
|
|
|
|
|
|
|
|
static void
|
|
|
|
clamp_s_cb (CoglTexture *sub_texture,
|
|
|
|
const float *sub_texture_coords,
|
|
|
|
const float *meta_coords,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
ClampData *clamp_data = user_data;
|
|
|
|
float mapped_meta_coords[4] = {
|
|
|
|
clamp_data->start,
|
|
|
|
meta_coords[1],
|
|
|
|
clamp_data->end,
|
|
|
|
meta_coords[3]
|
|
|
|
};
|
|
|
|
if (clamp_data->s_flipped)
|
|
|
|
SWAP (mapped_meta_coords[0], mapped_meta_coords[2]);
|
|
|
|
/* NB: we never need to flip the t coords when dealing with
|
|
|
|
* s-axis clamping so no need to check if ->t_flipped */
|
|
|
|
clamp_data->callback (sub_texture,
|
|
|
|
sub_texture_coords, mapped_meta_coords,
|
|
|
|
clamp_data->user_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
clamp_t_cb (CoglTexture *sub_texture,
|
|
|
|
const float *sub_texture_coords,
|
|
|
|
const float *meta_coords,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
ClampData *clamp_data = user_data;
|
|
|
|
float mapped_meta_coords[4] = {
|
|
|
|
meta_coords[0],
|
|
|
|
clamp_data->start,
|
|
|
|
meta_coords[2],
|
|
|
|
clamp_data->end,
|
|
|
|
};
|
|
|
|
if (clamp_data->s_flipped)
|
|
|
|
SWAP (mapped_meta_coords[0], mapped_meta_coords[2]);
|
|
|
|
if (clamp_data->t_flipped)
|
|
|
|
SWAP (mapped_meta_coords[1], mapped_meta_coords[3]);
|
|
|
|
clamp_data->callback (sub_texture,
|
|
|
|
sub_texture_coords, mapped_meta_coords,
|
|
|
|
clamp_data->user_data);
|
|
|
|
}
|
|
|
|
|
Switch use of primitive glib types to c99 equivalents
The coding style has for a long time said to avoid using redundant glib
data types such as gint or gchar etc because we feel that they make the
code look unnecessarily foreign to developers coming from outside of the
Gnome developer community.
Note: When we tried to find the historical rationale for the types we
just found that they were apparently only added for consistent syntax
highlighting which didn't seem that compelling.
Up until now we have been continuing to use some of the platform
specific type such as gint{8,16,32,64} and gsize but this patch switches
us over to using the standard c99 equivalents instead so we can further
ensure that our code looks familiar to the widest range of C developers
who might potentially contribute to Cogl.
So instead of using the gint{8,16,32,64} and guint{8,16,32,64} types this
switches all Cogl code to instead use the int{8,16,32,64}_t and
uint{8,16,32,64}_t c99 types instead.
Instead of gsize we now use size_t
For now we are not going to use the c99 _Bool type and instead we have
introduced a new CoglBool type to use instead of gboolean.
Reviewed-by: Neil Roberts <neil@linux.intel.com>
(cherry picked from commit 5967dad2400d32ca6319cef6cb572e81bf2c15f0)
2012-04-16 20:56:40 +00:00
|
|
|
static CoglBool
|
2011-10-27 13:31:15 +00:00
|
|
|
foreach_clamped_region (CoglMetaTexture *meta_texture,
|
|
|
|
float *tx_1,
|
|
|
|
float *ty_1,
|
|
|
|
float *tx_2,
|
|
|
|
float *ty_2,
|
|
|
|
CoglPipelineWrapMode wrap_s,
|
|
|
|
CoglPipelineWrapMode wrap_t,
|
|
|
|
CoglMetaTextureCallback callback,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
float width = cogl_texture_get_width (COGL_TEXTURE (meta_texture));
|
|
|
|
ClampData clamp_data;
|
|
|
|
|
|
|
|
/* Consider that *tx_1 may be > *tx_2 and to simplify things
|
|
|
|
* we just flip them around if that's the case and keep a note
|
|
|
|
* of the fact that they are flipped. */
|
|
|
|
if (*tx_1 > *tx_2)
|
|
|
|
{
|
|
|
|
SWAP (*tx_1, *tx_2);
|
|
|
|
clamp_data.s_flipped = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
clamp_data.s_flipped = FALSE;
|
|
|
|
|
|
|
|
/* The same goes for ty_1 and ty_2... */
|
|
|
|
if (*ty_1 > *ty_2)
|
|
|
|
{
|
|
|
|
SWAP (*ty_1, *ty_2);
|
|
|
|
clamp_data.t_flipped = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
clamp_data.t_flipped = FALSE;
|
|
|
|
|
|
|
|
clamp_data.callback = callback;
|
|
|
|
clamp_data.user_data = user_data;
|
|
|
|
|
|
|
|
if (wrap_s == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE)
|
|
|
|
{
|
|
|
|
float max_s_coord;
|
|
|
|
float half_texel_width;
|
|
|
|
|
|
|
|
/* Consider that rectangle textures have non-normalized
|
|
|
|
* coordinates... */
|
|
|
|
if (cogl_is_texture_rectangle (meta_texture))
|
|
|
|
max_s_coord = width;
|
|
|
|
else
|
|
|
|
max_s_coord = 1.0;
|
|
|
|
|
|
|
|
half_texel_width = max_s_coord / (width * 2);
|
|
|
|
|
|
|
|
/* Handle any left clamped region */
|
|
|
|
if (*tx_1 < 0)
|
|
|
|
{
|
|
|
|
clamp_data.start = *tx_1;
|
|
|
|
clamp_data.end = MIN (0, *tx_2);;
|
|
|
|
cogl_meta_texture_foreach_in_region (meta_texture,
|
|
|
|
half_texel_width, *ty_1,
|
|
|
|
half_texel_width, *ty_2,
|
|
|
|
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
|
|
|
wrap_t,
|
|
|
|
clamp_s_cb,
|
|
|
|
&clamp_data);
|
|
|
|
/* Have we handled everything? */
|
|
|
|
if (tx_2 <= 0)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* clamp tx_1 since we've handled everything with x < 0 */
|
|
|
|
*tx_1 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle any right clamped region - including the corners */
|
|
|
|
if (*tx_2 > max_s_coord)
|
|
|
|
{
|
|
|
|
clamp_data.start = MAX (max_s_coord, *tx_1);
|
|
|
|
clamp_data.end = *tx_2;
|
|
|
|
cogl_meta_texture_foreach_in_region (meta_texture,
|
|
|
|
max_s_coord - half_texel_width,
|
|
|
|
*ty_1,
|
|
|
|
max_s_coord - half_texel_width,
|
|
|
|
*ty_2,
|
|
|
|
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
|
|
|
wrap_t,
|
|
|
|
clamp_s_cb,
|
|
|
|
&clamp_data);
|
|
|
|
/* Have we handled everything? */
|
|
|
|
if (*tx_1 >= max_s_coord)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* clamp tx_2 since we've handled everything with x >
|
|
|
|
* max_s_coord */
|
|
|
|
*tx_2 = max_s_coord;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wrap_t == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE)
|
|
|
|
{
|
|
|
|
float height = cogl_texture_get_height (COGL_TEXTURE (meta_texture));
|
|
|
|
float max_t_coord;
|
|
|
|
float half_texel_height;
|
|
|
|
|
|
|
|
/* Consider that rectangle textures have non-normalized
|
|
|
|
* coordinates... */
|
|
|
|
if (cogl_is_texture_rectangle (meta_texture))
|
|
|
|
max_t_coord = height;
|
|
|
|
else
|
|
|
|
max_t_coord = 1.0;
|
|
|
|
|
|
|
|
half_texel_height = max_t_coord / (height * 2);
|
|
|
|
|
|
|
|
/* Handle any top clamped region */
|
|
|
|
if (*ty_1 < 0)
|
|
|
|
{
|
|
|
|
clamp_data.start = *ty_1;
|
|
|
|
clamp_data.end = MIN (0, *ty_2);;
|
|
|
|
cogl_meta_texture_foreach_in_region (meta_texture,
|
|
|
|
*tx_1, half_texel_height,
|
|
|
|
*tx_2, half_texel_height,
|
|
|
|
wrap_s,
|
|
|
|
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
|
|
|
clamp_t_cb,
|
|
|
|
&clamp_data);
|
|
|
|
/* Have we handled everything? */
|
|
|
|
if (tx_2 <= 0)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* clamp ty_1 since we've handled everything with y < 0 */
|
|
|
|
*ty_1 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle any bottom clamped region */
|
|
|
|
if (*ty_2 > max_t_coord)
|
|
|
|
{
|
|
|
|
clamp_data.start = MAX (max_t_coord, *ty_1);;
|
|
|
|
clamp_data.end = *ty_2;
|
|
|
|
cogl_meta_texture_foreach_in_region (meta_texture,
|
|
|
|
*tx_1,
|
|
|
|
max_t_coord - half_texel_height,
|
|
|
|
*tx_2,
|
|
|
|
max_t_coord - half_texel_height,
|
|
|
|
wrap_s,
|
|
|
|
COGL_PIPELINE_WRAP_MODE_REPEAT,
|
|
|
|
clamp_t_cb,
|
|
|
|
&clamp_data);
|
|
|
|
/* Have we handled everything? */
|
|
|
|
if (*ty_1 >= max_t_coord)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* clamp ty_2 since we've handled everything with y >
|
|
|
|
* max_t_coord */
|
|
|
|
*ty_2 = max_t_coord;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (clamp_data.s_flipped)
|
|
|
|
SWAP (*tx_1, *tx_2);
|
|
|
|
if (clamp_data.t_flipped)
|
|
|
|
SWAP (*ty_1, *ty_2);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2011-10-08 13:13:03 +00:00
|
|
|
typedef struct _NormalizeData
|
|
|
|
{
|
|
|
|
CoglMetaTextureCallback callback;
|
|
|
|
void *user_data;
|
|
|
|
float s_normalize_factor;
|
|
|
|
float t_normalize_factor;
|
|
|
|
} NormalizeData;
|
|
|
|
|
|
|
|
static void
|
|
|
|
normalize_meta_coords_cb (CoglTexture *slice_texture,
|
|
|
|
const float *slice_coords,
|
|
|
|
const float *meta_coords,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
NormalizeData *data = user_data;
|
|
|
|
float normalized_meta_coords[4] = {
|
|
|
|
meta_coords[0] * data->s_normalize_factor,
|
|
|
|
meta_coords[1] * data->t_normalize_factor,
|
|
|
|
meta_coords[2] * data->s_normalize_factor,
|
|
|
|
meta_coords[3] * data->t_normalize_factor
|
|
|
|
};
|
|
|
|
|
|
|
|
data->callback (slice_texture,
|
|
|
|
slice_coords, normalized_meta_coords,
|
|
|
|
data->user_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct _UnNormalizeData
|
|
|
|
{
|
|
|
|
CoglMetaTextureCallback callback;
|
|
|
|
void *user_data;
|
|
|
|
float width;
|
|
|
|
float height;
|
|
|
|
} UnNormalizeData;
|
|
|
|
|
|
|
|
static void
|
|
|
|
un_normalize_slice_coords_cb (CoglTexture *slice_texture,
|
|
|
|
const float *slice_coords,
|
|
|
|
const float *meta_coords,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
UnNormalizeData *data = user_data;
|
|
|
|
float un_normalized_slice_coords[4] = {
|
|
|
|
slice_coords[0] * data->width,
|
|
|
|
slice_coords[1] * data->height,
|
|
|
|
slice_coords[2] * data->width,
|
|
|
|
slice_coords[3] * data->height
|
|
|
|
};
|
|
|
|
|
|
|
|
data->callback (slice_texture,
|
|
|
|
un_normalized_slice_coords, meta_coords,
|
|
|
|
data->user_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
cogl_meta_texture_foreach_in_region (CoglMetaTexture *meta_texture,
|
|
|
|
float tx_1,
|
|
|
|
float ty_1,
|
|
|
|
float tx_2,
|
|
|
|
float ty_2,
|
|
|
|
CoglPipelineWrapMode wrap_s,
|
|
|
|
CoglPipelineWrapMode wrap_t,
|
|
|
|
CoglMetaTextureCallback callback,
|
|
|
|
void *user_data)
|
|
|
|
{
|
|
|
|
CoglTexture *texture = COGL_TEXTURE (meta_texture);
|
|
|
|
float width = cogl_texture_get_width (texture);
|
|
|
|
float height = cogl_texture_get_height (texture);
|
|
|
|
NormalizeData normalize_data;
|
|
|
|
|
2011-10-27 13:31:15 +00:00
|
|
|
if (wrap_s == COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
|
|
|
|
wrap_s = COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE;
|
|
|
|
if (wrap_t == COGL_PIPELINE_WRAP_MODE_AUTOMATIC)
|
|
|
|
wrap_t = COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE;
|
|
|
|
|
|
|
|
if (wrap_s == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE ||
|
|
|
|
wrap_t == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE)
|
|
|
|
{
|
Switch use of primitive glib types to c99 equivalents
The coding style has for a long time said to avoid using redundant glib
data types such as gint or gchar etc because we feel that they make the
code look unnecessarily foreign to developers coming from outside of the
Gnome developer community.
Note: When we tried to find the historical rationale for the types we
just found that they were apparently only added for consistent syntax
highlighting which didn't seem that compelling.
Up until now we have been continuing to use some of the platform
specific type such as gint{8,16,32,64} and gsize but this patch switches
us over to using the standard c99 equivalents instead so we can further
ensure that our code looks familiar to the widest range of C developers
who might potentially contribute to Cogl.
So instead of using the gint{8,16,32,64} and guint{8,16,32,64} types this
switches all Cogl code to instead use the int{8,16,32,64}_t and
uint{8,16,32,64}_t c99 types instead.
Instead of gsize we now use size_t
For now we are not going to use the c99 _Bool type and instead we have
introduced a new CoglBool type to use instead of gboolean.
Reviewed-by: Neil Roberts <neil@linux.intel.com>
(cherry picked from commit 5967dad2400d32ca6319cef6cb572e81bf2c15f0)
2012-04-16 20:56:40 +00:00
|
|
|
CoglBool finished = foreach_clamped_region (meta_texture,
|
2011-10-27 13:31:15 +00:00
|
|
|
&tx_1, &ty_1, &tx_2, &ty_2,
|
|
|
|
wrap_s, wrap_t,
|
|
|
|
callback,
|
|
|
|
user_data);
|
|
|
|
if (finished)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Since clamping has been handled we now want to normalize our
|
|
|
|
* wrap modes we se can assume from this point on we don't
|
|
|
|
* need to consider CLAMP_TO_EDGE. (NB: The spans code will
|
|
|
|
* assert that CLAMP_TO_EDGE isn't requested) */
|
|
|
|
if (wrap_s == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE)
|
|
|
|
wrap_s = COGL_PIPELINE_WRAP_MODE_REPEAT;
|
|
|
|
if (wrap_t == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE)
|
|
|
|
wrap_t = COGL_PIPELINE_WRAP_MODE_REPEAT;
|
|
|
|
}
|
|
|
|
|
2011-10-08 13:13:03 +00:00
|
|
|
/* It makes things simpler to deal with non-normalized region
|
|
|
|
* coordinates beyond this point and only re-normalize just before
|
|
|
|
* calling the user's callback... */
|
|
|
|
|
2011-10-14 08:25:12 +00:00
|
|
|
if (!cogl_is_texture_rectangle (COGL_TEXTURE (meta_texture)))
|
2011-10-08 13:13:03 +00:00
|
|
|
{
|
|
|
|
normalize_data.callback = callback;
|
|
|
|
normalize_data.user_data = user_data;
|
|
|
|
normalize_data.s_normalize_factor = 1.0f / width;
|
|
|
|
normalize_data.t_normalize_factor = 1.0f / height;
|
|
|
|
callback = normalize_meta_coords_cb;
|
|
|
|
user_data = &normalize_data;
|
|
|
|
tx_1 *= width;
|
|
|
|
ty_1 *= height;
|
|
|
|
tx_2 *= width;
|
|
|
|
ty_2 *= height;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX: at some point this wont be routed through the CoglTexture
|
|
|
|
* vtable, instead there will be a separate CoglMetaTexture
|
|
|
|
* interface vtable. */
|
|
|
|
|
|
|
|
if (texture->vtable->foreach_sub_texture_in_region)
|
|
|
|
{
|
|
|
|
ForeachData data;
|
|
|
|
|
|
|
|
data.meta_region_coords[0] = tx_1;
|
|
|
|
data.meta_region_coords[1] = ty_1;
|
|
|
|
data.meta_region_coords[2] = tx_2;
|
|
|
|
data.meta_region_coords[3] = ty_2;
|
|
|
|
data.wrap_s = wrap_s;
|
|
|
|
data.wrap_t = wrap_t;
|
|
|
|
data.callback = callback;
|
|
|
|
data.user_data = user_data;
|
|
|
|
|
|
|
|
data.width = width;
|
|
|
|
data.height = height;
|
|
|
|
|
|
|
|
memset (data.padded_textures, 0, sizeof (data.padded_textures));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 1) We iterate all the slices of the meta-texture only within
|
|
|
|
* the range [0,1].
|
|
|
|
*
|
|
|
|
* 2) We define a "padded grid" for each slice of the
|
|
|
|
* meta-texture in the range [0,1].
|
|
|
|
*
|
|
|
|
* The padded grid maps over the meta-texture coordinates in
|
|
|
|
* the range [0,1] but only contains one valid cell that
|
|
|
|
* corresponds to current slice being iterated and all the
|
|
|
|
* surrounding cells just provide padding.
|
|
|
|
*
|
|
|
|
* 3) Once we've defined our padded grid we then repeat that
|
|
|
|
* across the user's original region, calling their callback
|
|
|
|
* whenever we see our current slice - ignoring padding.
|
|
|
|
*
|
|
|
|
* A notable benefit of this design is that repeating a texture
|
|
|
|
* made of multiple slices will result in us repeating each
|
|
|
|
* slice in-turn so the user gets repeat callbacks for the same
|
|
|
|
* texture batched together. For manual emulation of texture
|
|
|
|
* repeats done by drawing geometry this makes it more likely
|
|
|
|
* that we can batch geometry.
|
|
|
|
*/
|
|
|
|
|
|
|
|
texture->vtable->foreach_sub_texture_in_region (texture,
|
|
|
|
0, 0, 1, 1,
|
|
|
|
create_grid_and_repeat_cb,
|
|
|
|
&data);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CoglSpan x_span = { 0, width, 0 };
|
|
|
|
CoglSpan y_span = { 0, height, 0 };
|
|
|
|
float meta_region_coords[4] = { tx_1, ty_1, tx_2, ty_2 };
|
|
|
|
UnNormalizeData un_normalize_data;
|
|
|
|
|
|
|
|
/* If we are dealing with a CoglTextureRectangle then we need a shim
|
|
|
|
* callback that un_normalizes the slice coordinates we get from
|
|
|
|
* _cogl_texture_spans_foreach_in_region before passing them to
|
|
|
|
* the user's callback. */
|
2011-10-14 08:25:12 +00:00
|
|
|
if (cogl_is_texture_rectangle (meta_texture))
|
2011-10-08 13:13:03 +00:00
|
|
|
{
|
|
|
|
un_normalize_data.callback = callback;
|
|
|
|
un_normalize_data.user_data = user_data;
|
|
|
|
un_normalize_data.width = width;
|
|
|
|
un_normalize_data.height = height;
|
|
|
|
callback = un_normalize_slice_coords_cb;
|
|
|
|
user_data = &un_normalize_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
_cogl_texture_spans_foreach_in_region (&x_span, 1,
|
|
|
|
&y_span, 1,
|
|
|
|
&texture,
|
|
|
|
meta_region_coords,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
wrap_s,
|
|
|
|
wrap_t,
|
|
|
|
callback,
|
|
|
|
user_data);
|
|
|
|
}
|
|
|
|
}
|
2011-10-27 13:31:15 +00:00
|
|
|
#undef SWAP
|