From 1a30f4fb1535c9bca26859b97575877a6299d2c8 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Thu, 13 Oct 2011 14:02:37 +0100 Subject: [PATCH] Adds support for a mirrored repeat wrap mode This adds COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT enum so that mirrored texture repeating can be used. This also adds support for emulating the MIRRORED_REPEAT mode via the cogl-spans API so it can also be used with meta textures such as sliced and atlas textures. Reviewed-by: Neil Roberts --- cogl/cogl-pipeline-layer-private.h | 4 ++++ cogl/cogl-pipeline-layer-state.h | 3 ++- cogl/cogl-primitives.c | 8 +++---- cogl/cogl-spans.c | 38 +++++++++++++++++++++++++++--- cogl/cogl-spans.h | 1 + cogl/cogl.h | 3 +++ cogl/driver/gl/cogl-gl.c | 3 +++ cogl/driver/gles/cogl-gles.c | 2 ++ 8 files changed, 54 insertions(+), 8 deletions(-) diff --git a/cogl/cogl-pipeline-layer-private.h b/cogl/cogl-pipeline-layer-private.h index 5df32c468..76fcf23bf 100644 --- a/cogl/cogl-pipeline-layer-private.h +++ b/cogl/cogl-pipeline-layer-private.h @@ -41,6 +41,9 @@ #ifndef GL_CLAMP_TO_BORDER #define GL_CLAMP_TO_BORDER 0x812d #endif +#ifndef GL_MIRRORED_REPEAT +#define GL_MIRRORED_REPEAT 0x8370 +#endif typedef struct _CoglPipelineLayer CoglPipelineLayer; #define COGL_PIPELINE_LAYER(OBJECT) ((CoglPipelineLayer *)OBJECT) @@ -54,6 +57,7 @@ typedef struct _CoglPipelineLayer CoglPipelineLayer; typedef enum _CoglPipelineWrapModeInternal { COGL_PIPELINE_WRAP_MODE_INTERNAL_REPEAT = GL_REPEAT, + COGL_PIPELINE_WRAP_MODE_INTERNAL_MIRRORED_REPEAT = GL_MIRRORED_REPEAT, COGL_PIPELINE_WRAP_MODE_INTERNAL_CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE, COGL_PIPELINE_WRAP_MODE_INTERNAL_CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER, COGL_PIPELINE_WRAP_MODE_INTERNAL_AUTOMATIC = GL_ALWAYS diff --git a/cogl/cogl-pipeline-layer-state.h b/cogl/cogl-pipeline-layer-state.h index cf31bf552..b1f57367e 100644 --- a/cogl/cogl-pipeline-layer-state.h +++ b/cogl/cogl-pipeline-layer-state.h @@ -111,8 +111,9 @@ typedef enum { */ typedef enum { COGL_PIPELINE_WRAP_MODE_REPEAT = 0x2901, + COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT = 0x8370, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE = 0x812F, - COGL_PIPELINE_WRAP_MODE_AUTOMATIC = 0x0207 + COGL_PIPELINE_WRAP_MODE_AUTOMATIC = 0x0207 /* GL_ALWAYS */ } CoglPipelineWrapMode; /* NB: these values come from the equivalents in gl.h */ diff --git a/cogl/cogl-primitives.c b/cogl/cogl-primitives.c index 27707bb32..84b6bb4e4 100644 --- a/cogl/cogl-primitives.c +++ b/cogl/cogl-primitives.c @@ -368,10 +368,10 @@ _cogl_texture_quad_multiple_primitives (CoglTexture *texture, state.v_to_q_scale_x = fabs (state.quad_len_x / (tx_2 - tx_1)); state.v_to_q_scale_y = fabs (state.quad_len_y / (ty_2 - ty_1)); - /* cogl_meta_texture_foreach_in_region only allows WRAP_MODE_REPEAT. - * If CLAMP_TO_EDGE is in use then we have already dealt with - * emulation for that and we can just pass WRAP_MODE_REPEAT here... - */ + /* cogl_meta_texture_foreach_in_region only allows WRAP_MODE_REPEAT + * and WRAP_MODE_MIRRORED_REPEAT. If CLAMP_TO_EDGE is in use then we + * have already dealt with emulation for that and we can just pass + * WRAP_MODE_REPEAT here... */ if (wrap_s == COGL_PIPELINE_WRAP_MODE_AUTOMATIC || wrap_s == COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE) wrap_s = COGL_PIPELINE_WRAP_MODE_REPEAT; diff --git a/cogl/cogl-spans.c b/cogl/cogl-spans.c index 3d9d3e516..3935e9768 100644 --- a/cogl/cogl-spans.c +++ b/cogl/cogl-spans.c @@ -77,9 +77,9 @@ _cogl_span_iter_begin (CoglSpanIter *iter, /* XXX: If CLAMP_TO_EDGE needs to be emulated then it needs to be * done at a higher level than here... */ - g_return_if_fail (wrap_mode == COGL_PIPELINE_WRAP_MODE_REPEAT); + g_return_if_fail (wrap_mode == COGL_PIPELINE_WRAP_MODE_REPEAT || + wrap_mode == COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT); - iter->index = 0; iter->span = NULL; iter->spans = spans; @@ -109,6 +109,25 @@ _cogl_span_iter_begin (CoglSpanIter *iter, iter->wrap_mode = wrap_mode; + if (wrap_mode == COGL_PIPELINE_WRAP_MODE_REPEAT) + iter->index = 0; + else if (wrap_mode == COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT) + { + if ((int)iter->origin % 2) + { + iter->index = iter->n_spans - 1; + iter->mirror_direction = -1; + iter->flipped = !iter->flipped; + } + else + { + iter->index = 0; + iter->mirror_direction = 1; + } + } + else + g_warn_if_reached (); + iter->cover_start = cover_start; iter->cover_end = cover_end; iter->pos = iter->origin; @@ -126,7 +145,20 @@ _cogl_span_iter_next (CoglSpanIter *iter) /* Move current position */ iter->pos = iter->next_pos; - iter->index = (iter->index + 1) % iter->n_spans; + if (iter->wrap_mode == COGL_PIPELINE_WRAP_MODE_REPEAT) + iter->index = (iter->index + 1) % iter->n_spans; + else if (iter->wrap_mode == COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT) + { + iter->index += iter->mirror_direction; + if (iter->index == iter->n_spans || iter->index == -1) + { + iter->mirror_direction = -iter->mirror_direction; + iter->index += iter->mirror_direction; + iter->flipped = !iter->flipped; + } + } + else + g_warn_if_reached (); /* Update intersection */ _cogl_span_iter_update (iter); diff --git a/cogl/cogl-spans.h b/cogl/cogl-spans.h index e328b72ac..ac8d13aab 100644 --- a/cogl/cogl-spans.h +++ b/cogl/cogl-spans.h @@ -50,6 +50,7 @@ typedef struct _CoglSpanIter gboolean intersects; gboolean flipped; CoglPipelineWrapMode wrap_mode; + int mirror_direction; } CoglSpanIter; void diff --git a/cogl/cogl.h b/cogl/cogl.h index 3925a0b98..892103933 100644 --- a/cogl/cogl.h +++ b/cogl/cogl.h @@ -198,6 +198,8 @@ cogl_features_available (CoglFeatureFlags features); * supported with CoglBufferAccess including read support. * @COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE: Whether cogl_buffer_map() is * supported with CoglBufferAccess including write support. + * @COGL_FEATURE_ID_MIRRORED_REPEAT: Whether + * %COGL_PIPELINE_WRAP_MODE_MIRRORED_REPEAT is supported. * * * All the capabilities that can vary between different GPUs supported @@ -224,6 +226,7 @@ typedef enum _CoglFeatureID COGL_FEATURE_ID_POINT_SPRITE, COGL_FEATURE_ID_MAP_BUFFER_FOR_READ, COGL_FEATURE_ID_MAP_BUFFER_FOR_WRITE, + COGL_FEATURE_ID_MIRRORED_REPEAT, /*< private > */ _COGL_N_FEATURE_IDS diff --git a/cogl/driver/gl/cogl-gl.c b/cogl/driver/gl/cogl-gl.c index 22d16b6e9..08fdecdfb 100644 --- a/cogl/driver/gl/cogl-gl.c +++ b/cogl/driver/gl/cogl-gl.c @@ -164,6 +164,9 @@ _cogl_gl_update_features (CoglContext *context, COGL_FEATURE_ID_UNSIGNED_INT_INDICES, TRUE); COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE); + if (COGL_CHECK_GL_VERSION (gl_major, gl_minor, 1, 4)) + COGL_FLAGS_SET (ctx->features, COGL_FEATURE_ID_MIRRORED_REPEAT, TRUE); + gl_extensions = (const char *)ctx->glGetString (GL_EXTENSIONS); _cogl_feature_check_ext_functions (context, diff --git a/cogl/driver/gles/cogl-gles.c b/cogl/driver/gles/cogl-gles.c index 988a34e10..df90c57f7 100644 --- a/cogl/driver/gles/cogl-gles.c +++ b/cogl/driver/gles/cogl-gles.c @@ -94,6 +94,8 @@ _cogl_gles_update_features (CoglContext *context, COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_TEXTURE_NPOT_BASIC, TRUE); COGL_FLAGS_SET (context->features, COGL_FEATURE_ID_DEPTH_RANGE, TRUE); + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_MIRRORED_REPEAT, TRUE); } private_flags |= COGL_PRIVATE_FEATURE_VBOS;