From 2f628b1a8a405d2e4c08f2b2d125002ded0d8981 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Wed, 23 Sep 2009 15:11:55 +0100 Subject: [PATCH] [cogl-spans] split out cogl-spans code from cogl-texture-2d-sliced When we implement atlas textures we will probably want to use the spans API to handle texture repeating so it doesn't make sense to leave the code in cogl-texture-2d-sliced.c. Since it's a standalone set of data structures and algorithms it also seems reasonable to split out from cogl-texture. --- clutter/cogl/cogl/Makefile.am | 2 + clutter/cogl/cogl/cogl-spans.c | 132 ++++++++++++ clutter/cogl/cogl/cogl-spans.h | 70 +++++++ .../cogl/cogl-texture-2d-sliced-private.h | 27 --- clutter/cogl/cogl/cogl-texture-2d-sliced.c | 195 ++++-------------- 5 files changed, 248 insertions(+), 178 deletions(-) create mode 100644 clutter/cogl/cogl/cogl-spans.c create mode 100644 clutter/cogl/cogl/cogl-spans.h diff --git a/clutter/cogl/cogl/Makefile.am b/clutter/cogl/cogl/Makefile.am index fbfbd02af..06c493cad 100644 --- a/clutter/cogl/cogl/Makefile.am +++ b/clutter/cogl/cogl/Makefile.am @@ -118,6 +118,8 @@ libclutter_cogl_la_SOURCES = \ cogl-texture-driver.h \ cogl-texture.c \ cogl-texture-2d-sliced.c \ + cogl-spans.h \ + cogl-spans.c \ $(NULL) EXTRA_DIST += stb_image.c cogl-enum-types.h.in cogl-enum-types.c.in diff --git a/clutter/cogl/cogl/cogl-spans.c b/clutter/cogl/cogl/cogl-spans.c new file mode 100644 index 000000000..5d01fb23f --- /dev/null +++ b/clutter/cogl/cogl/cogl-spans.c @@ -0,0 +1,132 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2007,2008,2009 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "math.h" + +#include "cogl.h" +#include "cogl-internal.h" +#include "cogl-spans.h" + +void +_cogl_span_iter_update (CoglSpanIter *iter) +{ + /* Pick current span */ + iter->span = &g_array_index (iter->array, CoglSpan, iter->index); + + /* Offset next position by span size */ + iter->next_pos = iter->pos + + (float)(iter->span->size - iter->span->waste); + + /* Check if span intersects the area to cover */ + if (iter->next_pos <= iter->cover_start || + iter->pos >= iter->cover_end) + { + /* Intersection undefined */ + iter->intersects = FALSE; + return; + } + + iter->intersects = TRUE; + + /* Clip start position to coverage area */ + if (iter->pos < iter->cover_start) + iter->intersect_start = iter->cover_start; + else + iter->intersect_start = iter->pos; + + /* Clip end position to coverage area */ + if (iter->next_pos > iter->cover_end) + iter->intersect_end = iter->cover_end; + else + iter->intersect_end = iter->next_pos; +} + +void +_cogl_span_iter_begin (CoglSpanIter *iter, + GArray *spans, + float normalize_factor, + float cover_start, + float cover_end) +{ + float cover_start_normalized; + + iter->index = 0; + iter->span = NULL; + + iter->array = spans; + + /* We always iterate in a positive direction from the origin. If + * iter->flipped == TRUE that means whoever is using this API should + * interpreted the current span as extending in the opposite direction. I.e. + * it extends to the left if iterating the X axis, or up if the Y axis. */ + if (cover_start > cover_end) + { + float tmp = cover_start; + cover_start = cover_end; + cover_end = tmp; + iter->flipped = TRUE; + } + else + iter->flipped = FALSE; + + /* The texture spans cover the normalized texture coordinate space ranging + * from [0,1] but to help support repeating of sliced textures we allow + * iteration of any range so we need to relate the start of the range to the + * nearest point equivalent to 0. + */ + cover_start_normalized = cover_start / normalize_factor; + iter->origin = floorf (cover_start_normalized) * normalize_factor; + + iter->cover_start = cover_start; + iter->cover_end = cover_end; + iter->pos = iter->origin; + + /* Update intersection */ + _cogl_span_iter_update (iter); +} + +void +_cogl_span_iter_next (CoglSpanIter *iter) +{ + /* Move current position */ + iter->pos = iter->next_pos; + + /* Pick next slice (wrap when last reached) */ + iter->index = (iter->index + 1) % iter->array->len; + + /* Update intersection */ + _cogl_span_iter_update (iter); +} + +gboolean +_cogl_span_iter_end (CoglSpanIter *iter) +{ + /* End reached when whole area covered */ + return iter->pos >= iter->cover_end; +} + + diff --git a/clutter/cogl/cogl/cogl-spans.h b/clutter/cogl/cogl/cogl-spans.h new file mode 100644 index 000000000..e33dffdc3 --- /dev/null +++ b/clutter/cogl/cogl/cogl-spans.h @@ -0,0 +1,70 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2007,2008,2009 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, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __COGL_SPANS_PRIVATE_H +#define __COGL_SPANS_PRIVATE_H + +#include "cogl-handle.h" + +typedef struct _CoglSpan +{ + int start; + int size; + int waste; +} CoglSpan; + +typedef struct _CoglSpanIter +{ + int index; + GArray *array; + CoglSpan *span; + float pos; + float next_pos; + float origin; + float cover_start; + float cover_end; + float intersect_start; + float intersect_end; + float intersect_start_local; + float intersect_end_local; + gboolean intersects; + gboolean flipped; +} CoglSpanIter; + +void +_cogl_span_iter_update (CoglSpanIter *iter); + +void +_cogl_span_iter_begin (CoglSpanIter *iter, + GArray *spans, + float normalize_factor, + float cover_start, + float cover_end); + +void +_cogl_span_iter_next (CoglSpanIter *iter); + +gboolean +_cogl_span_iter_end (CoglSpanIter *iter); + +#endif /* __COGL_SPANS_PRIVATE_H */ diff --git a/clutter/cogl/cogl/cogl-texture-2d-sliced-private.h b/clutter/cogl/cogl/cogl-texture-2d-sliced-private.h index 0b1699f57..81c44a5a3 100644 --- a/clutter/cogl/cogl/cogl-texture-2d-sliced-private.h +++ b/clutter/cogl/cogl/cogl-texture-2d-sliced-private.h @@ -32,35 +32,8 @@ #define COGL_TEXTURE_2D_SLICED(tex) ((CoglTexture2DSliced *)tex) typedef struct _CoglTexture2DSliced CoglTexture2DSliced; -typedef struct _CoglTexSliceSpan CoglTexSliceSpan; -typedef struct _CoglSpanIter CoglSpanIter; typedef struct _CoglTexturePixel CoglTexturePixel; -struct _CoglTexSliceSpan -{ - int start; - int size; - int waste; -}; - -struct _CoglSpanIter -{ - gint index; - GArray *array; - CoglTexSliceSpan *span; - float pos; - float next_pos; - float origin; - float cover_start; - float cover_end; - float intersect_start; - float intersect_end; - float intersect_start_local; - float intersect_end_local; - gboolean intersects; - gboolean flipped; -}; - /* This is used to store the first pixel of each slice. This is only used when glGenerateMipmap is not available */ struct _CoglTexturePixel diff --git a/clutter/cogl/cogl/cogl-texture-2d-sliced.c b/clutter/cogl/cogl/cogl-texture-2d-sliced.c index 8f2057f60..9b70860e8 100644 --- a/clutter/cogl/cogl/cogl-texture-2d-sliced.c +++ b/clutter/cogl/cogl/cogl-texture-2d-sliced.c @@ -38,10 +38,9 @@ #include "cogl-texture-private.h" #include "cogl-texture-2d-sliced-private.h" #include "cogl-texture-driver.h" -#include "cogl-material.h" #include "cogl-context.h" #include "cogl-handle.h" -#include "cogl-primitives.h" +#include "cogl-spans.h" #include #include @@ -51,112 +50,6 @@ static void _cogl_texture_2d_sliced_free (CoglTexture2DSliced *tex_2ds); COGL_HANDLE_DEFINE (Texture2DSliced, texture_2d_sliced); -typedef enum _CoglSpanIterAxis -{ - COGL_SPAN_ITER_AXIS_X, - COGL_SPAN_ITER_AXIS_Y -} CoglSpanIterAxis; - -static void -_cogl_span_iter_update (CoglSpanIter *iter) -{ - /* Pick current span */ - iter->span = &g_array_index (iter->array, - CoglTexSliceSpan, - iter->index); - - /* Offset next position by span size */ - iter->next_pos = iter->pos + - (float)(iter->span->size - iter->span->waste); - - /* Check if span intersects the area to cover */ - if (iter->next_pos <= iter->cover_start || - iter->pos >= iter->cover_end) - { - /* Intersection undefined */ - iter->intersects = FALSE; - return; - } - - iter->intersects = TRUE; - - /* Clip start position to coverage area */ - if (iter->pos < iter->cover_start) - iter->intersect_start = iter->cover_start; - else - iter->intersect_start = iter->pos; - - /* Clip end position to coverage area */ - if (iter->next_pos > iter->cover_end) - iter->intersect_end = iter->cover_end; - else - iter->intersect_end = iter->next_pos; -} - -void -_cogl_span_iter_begin (CoglSpanIter *iter, - GArray *spans, - float normalize_factor, - float cover_start, - float cover_end) -{ - float cover_start_normalized; - - iter->index = 0; - iter->span = NULL; - - iter->array = spans; - - /* We always iterate in a positive direction from the origin. If - * iter->flipped == TRUE that means whoever is using this API should - * interpreted the current span as extending in the opposite direction. I.e. - * it extends to the left if iterating the X axis, or up if the Y axis. */ - if (cover_start > cover_end) - { - float tmp = cover_start; - cover_start = cover_end; - cover_end = tmp; - iter->flipped = TRUE; - } - else - iter->flipped = FALSE; - - /* The texture spans cover the normalized texture coordinate space ranging - * from [0,1] but to help support repeating of sliced textures we allow - * iteration of any range so we need to relate the start of the range to the - * nearest point equivalent to 0. - */ - cover_start_normalized = cover_start / normalize_factor; - iter->origin = floorf (cover_start_normalized) * normalize_factor; - - iter->cover_start = cover_start; - iter->cover_end = cover_end; - iter->pos = iter->origin; - - /* Update intersection */ - _cogl_span_iter_update (iter); -} - -void -_cogl_span_iter_next (CoglSpanIter *iter) -{ - /* Move current position */ - iter->pos = iter->next_pos; - - /* Pick next slice (wrap when last reached) */ - iter->index = (iter->index + 1) % iter->array->len; - - /* Update intersection */ - _cogl_span_iter_update (iter); -} - -gboolean -_cogl_span_iter_end (CoglSpanIter *iter) -{ - /* End reached when whole area covered */ - return iter->pos >= iter->cover_end; -} - /* To differentiate between texture coordinates of a specific, real, slice * texture and the texture coordinates of the composite, sliced texture, the * coordinates of the sliced texture are called "virtual" coordinates and the @@ -289,24 +182,24 @@ _cogl_texture_2d_sliced_foreach_sub_texture_in_region ( static guchar * _cogl_texture_2d_sliced_allocate_waste_buffer (CoglTexture2DSliced *tex_2ds) { - CoglTexSliceSpan *last_x_span; - CoglTexSliceSpan *last_y_span; + CoglSpan *last_x_span; + CoglSpan *last_y_span; guchar *waste_buf = NULL; CoglTexture *tex = COGL_TEXTURE (tex_2ds); /* If the texture has any waste then allocate a buffer big enough to fill the gaps */ - last_x_span = &g_array_index (tex_2ds->slice_x_spans, CoglTexSliceSpan, + last_x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, tex_2ds->slice_x_spans->len - 1); - last_y_span = &g_array_index (tex_2ds->slice_y_spans, CoglTexSliceSpan, + last_y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, tex_2ds->slice_y_spans->len - 1); if (last_x_span->waste > 0 || last_y_span->waste > 0) { gint bpp = _cogl_get_format_bpp (tex->bitmap.format); - CoglTexSliceSpan *first_x_span - = &g_array_index (tex_2ds->slice_x_spans, CoglTexSliceSpan, 0); - CoglTexSliceSpan *first_y_span - = &g_array_index (tex_2ds->slice_y_spans, CoglTexSliceSpan, 0); + CoglSpan *first_x_span + = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0); + CoglSpan *first_y_span + = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, 0); guint right_size = first_y_span->size * last_x_span->waste; guint bottom_size = first_x_span->size * last_y_span->waste; @@ -319,8 +212,8 @@ _cogl_texture_2d_sliced_allocate_waste_buffer (CoglTexture2DSliced *tex_2ds) static gboolean _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds) { - CoglTexSliceSpan *x_span; - CoglTexSliceSpan *y_span; + CoglSpan *x_span; + CoglSpan *y_span; GLuint gl_handle; gint bpp; gint x,y; @@ -334,14 +227,14 @@ _cogl_texture_2d_sliced_upload_to_gl (CoglTexture2DSliced *tex_2ds) /* Iterate vertical slices */ for (y = 0; y < tex_2ds->slice_y_spans->len; ++y) { - y_span = &g_array_index (tex_2ds->slice_y_spans, CoglTexSliceSpan, y); + y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, y); /* Iterate horizontal slices */ for (x = 0; x < tex_2ds->slice_x_spans->len; ++x) { gint slice_num = y * tex_2ds->slice_x_spans->len + x; - x_span = &g_array_index (tex_2ds->slice_x_spans, CoglTexSliceSpan, x); + x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x); /* Pick the gl texture object handle */ gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint, slice_num); @@ -459,8 +352,8 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds, GLuint source_gl_type) { CoglTexture *tex = COGL_TEXTURE (tex_2ds); - CoglTexSliceSpan *x_span; - CoglTexSliceSpan *y_span; + CoglSpan *x_span; + CoglSpan *y_span; gint bpp; CoglSpanIter x_iter; CoglSpanIter y_iter; @@ -494,7 +387,7 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds, continue; } - y_span = &g_array_index (tex_2ds->slice_y_spans, CoglTexSliceSpan, + y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, y_iter.index); /* Iterate horizontal spans */ @@ -519,7 +412,7 @@ _cogl_texture_2d_sliced_upload_subregion_to_gl (CoglTexture2DSliced *tex_2ds, continue; } - x_span = &g_array_index (tex_2ds->slice_x_spans, CoglTexSliceSpan, + x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x_iter.index); /* Pick intersection width and height */ @@ -671,7 +564,7 @@ _cogl_rect_slices_for_size (int size_to_fill, GArray *out_spans) { int n_spans = 0; - CoglTexSliceSpan span; + CoglSpan span; /* Init first slice span */ span.start = 0; @@ -708,7 +601,7 @@ _cogl_pot_slices_for_size (gint size_to_fill, GArray *out_spans) { gint n_spans = 0; - CoglTexSliceSpan span; + CoglSpan span; /* Init first slice span */ span.start = 0; @@ -797,8 +690,8 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds) gint n_y_slices; gint n_slices; gint x, y; - CoglTexSliceSpan *x_span; - CoglTexSliceSpan *y_span; + CoglSpan *x_span; + CoglSpan *y_span; const GLfloat transparent_color[4] = { 0x00, 0x00, 0x00, 0x00 }; gint (*slices_for_size) (gint, gint, gint, GArray*); @@ -824,7 +717,7 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds) /* Negative number means no slicing forced by the user */ if (tex_2ds->max_waste <= -1) { - CoglTexSliceSpan span; + CoglSpan span; /* Check if size supported else bail out */ if (!_cogl_texture_driver_size_supported (tex->gl_target, @@ -841,11 +734,11 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds) /* Init span arrays */ tex_2ds->slice_x_spans = g_array_sized_new (FALSE, FALSE, - sizeof (CoglTexSliceSpan), + sizeof (CoglSpan), 1); tex_2ds->slice_y_spans = g_array_sized_new (FALSE, FALSE, - sizeof (CoglTexSliceSpan), + sizeof (CoglSpan), 1); /* Add a single span for width and height */ @@ -888,11 +781,11 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds) /* Init span arrays with reserved size */ tex_2ds->slice_x_spans = g_array_sized_new (FALSE, FALSE, - sizeof (CoglTexSliceSpan), + sizeof (CoglSpan), n_x_slices); tex_2ds->slice_y_spans = g_array_sized_new (FALSE, FALSE, - sizeof (CoglTexSliceSpan), + sizeof (CoglSpan), n_y_slices); /* Fill span arrays with info */ @@ -936,11 +829,11 @@ _cogl_texture_2d_sliced_slices_create (CoglTexture2DSliced *tex_2ds) /* Init each GL texture object */ for (y = 0; y < n_y_slices; ++y) { - y_span = &g_array_index (tex_2ds->slice_y_spans, CoglTexSliceSpan, y); + y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, y); for (x = 0; x < n_x_slices; ++x) { - x_span = &g_array_index (tex_2ds->slice_x_spans, CoglTexSliceSpan, x); + x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x); COGL_NOTE (TEXTURE, "CREATE SLICE (%d,%d)\tsize (%d,%d)", x, y, @@ -1268,8 +1161,8 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, guint bpp; CoglTexture2DSliced *tex_2ds; CoglTexture *tex; - CoglTexSliceSpan x_span; - CoglTexSliceSpan y_span; + CoglSpan x_span; + CoglSpan y_span; if (!_cogl_texture_driver_allows_foreign_gl_target (gl_target)) return COGL_INVALID_HANDLE; @@ -1378,11 +1271,11 @@ _cogl_texture_2d_sliced_new_from_foreign (GLuint gl_handle, /* Create slice arrays */ tex_2ds->slice_x_spans = g_array_sized_new (FALSE, FALSE, - sizeof (CoglTexSliceSpan), 1); + sizeof (CoglSpan), 1); tex_2ds->slice_y_spans = g_array_sized_new (FALSE, FALSE, - sizeof (CoglTexSliceSpan), 1); + sizeof (CoglSpan), 1); tex_2ds->slice_gl_handles = g_array_sized_new (FALSE, FALSE, @@ -1436,11 +1329,11 @@ gboolean _cogl_texture_2d_sliced_can_hardware_repeat (CoglHandle handle) { CoglTexture2DSliced *tex_2ds = COGL_TEXTURE_2D_SLICED (handle); - CoglTexSliceSpan *x_span; - CoglTexSliceSpan *y_span; + CoglSpan *x_span; + CoglSpan *y_span; - x_span = &g_array_index (tex_2ds->slice_x_spans, CoglTexSliceSpan, 0); - y_span = &g_array_index (tex_2ds->slice_y_spans, CoglTexSliceSpan, 0); + x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0); + y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, 0); return (x_span->waste || y_span->waste) ? FALSE : TRUE; } @@ -1451,14 +1344,14 @@ _cogl_texture_2d_sliced_transform_coords_to_gl (CoglTexture2DSliced *tex_2ds, float *t) { CoglTexture *tex = COGL_TEXTURE (tex_2ds); - CoglTexSliceSpan *x_span; - CoglTexSliceSpan *y_span; + CoglSpan *x_span; + CoglSpan *y_span; g_assert (!_cogl_texture_2d_sliced_is_sliced (tex_2ds)); /* Don't include the waste in the texture coordinates */ - x_span = &g_array_index (tex_2ds->slice_x_spans, CoglTexSliceSpan, 0); - y_span = &g_array_index (tex_2ds->slice_y_spans, CoglTexSliceSpan, 0); + x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, 0); + y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, 0); *s *= tex->bitmap.width / (float)x_span->size; *t *= tex->bitmap.height / (float)y_span->size; @@ -1677,8 +1570,8 @@ _cogl_texture_2d_sliced_download_from_gl ( GLuint target_gl_type) { CoglTexture *tex = COGL_TEXTURE (tex_2ds); - CoglTexSliceSpan *x_span; - CoglTexSliceSpan *y_span; + CoglSpan *x_span; + CoglSpan *y_span; GLuint gl_handle; gint bpp; gint x,y; @@ -1689,13 +1582,13 @@ _cogl_texture_2d_sliced_download_from_gl ( /* Iterate vertical slices */ for (y = 0; y < tex_2ds->slice_y_spans->len; ++y) { - y_span = &g_array_index (tex_2ds->slice_y_spans, CoglTexSliceSpan, y); + y_span = &g_array_index (tex_2ds->slice_y_spans, CoglSpan, y); /* Iterate horizontal slices */ for (x = 0; x < tex_2ds->slice_x_spans->len; ++x) { /*if (x != 0 || y != 1) continue;*/ - x_span = &g_array_index (tex_2ds->slice_x_spans, CoglTexSliceSpan, x); + x_span = &g_array_index (tex_2ds->slice_x_spans, CoglSpan, x); /* Pick the gl texture object handle */ gl_handle = g_array_index (tex_2ds->slice_gl_handles, GLuint,