From dab4ddc7184b25274c24fcec4c1e2d9dfff5e94a Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Wed, 26 May 2010 11:33:32 +0100 Subject: [PATCH] material: Make CoglMaterial responsible for depth state This redirects the legacy depth testing APIs through CoglMaterial and adds a new experimental cogl_material_ API for handling the depth testing state. This adds the following new functions: cogl_material_set_depth_test_enabled cogl_material_get_depth_test_enabled cogl_material_set_depth_writing_enabled cogl_material_get_depth_writing_enabled cogl_material_set_depth_test_function cogl_material_get_depth_test_function cogl_material_set_depth_range cogl_material_get_depth_range As with other experimental Cogl API you need to define COGL_ENABLE_EXPERIMENTAL_API to access them and their stability isn't yet guaranteed. --- cogl/cogl-context.c | 8 + cogl/cogl-context.h | 8 + cogl/cogl-material-private.h | 19 ++- cogl/cogl-material.c | 323 +++++++++++++++++++++++++++++++++-- cogl/cogl-material.h | 207 ++++++++++++++++++++++ cogl/cogl-types.h | 25 ++- cogl/cogl.c | 28 ++- cogl/cogl.h | 6 + 8 files changed, 596 insertions(+), 28 deletions(-) diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c index e227594f7..585e124f0 100644 --- a/cogl/cogl-context.c +++ b/cogl/cogl-context.c @@ -127,6 +127,14 @@ cogl_create_context (void) _context->gl_blend_enable_cache = FALSE; + _context->depth_test_enabled_cache = FALSE; + _context->depth_test_function_cache = COGL_DEPTH_TEST_FUNCTION_LESS; + _context->depth_writing_enabled_cache = TRUE; + _context->depth_range_near_cache = 0; + _context->depth_range_far_cache = 1; + + _context->legacy_depth_test_enabled = FALSE; + _context->framebuffer_stack = _cogl_create_framebuffer_stack (); window_buffer = _cogl_onscreen_new (); diff --git a/cogl/cogl-context.h b/cogl/cogl-context.h index 530184f0b..a56f465de 100644 --- a/cogl/cogl-context.h +++ b/cogl/cogl-context.h @@ -109,6 +109,14 @@ typedef struct gboolean gl_blend_enable_cache; + gboolean depth_test_enabled_cache; + CoglDepthTestFunction depth_test_function_cache; + gboolean depth_writing_enabled_cache; + float depth_range_near_cache; + float depth_range_far_cache; + + gboolean legacy_depth_test_enabled; + /* PBOs */ /* This can be used to check if a pbo is bound */ CoglBuffer *current_pbo; diff --git a/cogl/cogl-material-private.h b/cogl/cogl-material-private.h index 770b60058..f98bdb387 100644 --- a/cogl/cogl-material-private.h +++ b/cogl/cogl-material-private.h @@ -311,8 +311,9 @@ typedef enum _CoglMaterialState COGL_MATERIAL_STATE_ALPHA_FUNC = 1L<<4, COGL_MATERIAL_STATE_BLEND = 1L<<5, COGL_MATERIAL_STATE_USER_SHADER = 1L<<6, + COGL_MATERIAL_STATE_DEPTH = 1L<<7, - COGL_MATERIAL_STATE_REAL_BLEND_ENABLE = 1L<<7, + COGL_MATERIAL_STATE_REAL_BLEND_ENABLE = 1L<<8, COGL_MATERIAL_STATE_ALL_SPARSE = COGL_MATERIAL_STATE_COLOR | @@ -321,7 +322,8 @@ typedef enum _CoglMaterialState COGL_MATERIAL_STATE_LIGHTING | COGL_MATERIAL_STATE_ALPHA_FUNC | COGL_MATERIAL_STATE_BLEND | - COGL_MATERIAL_STATE_USER_SHADER, + COGL_MATERIAL_STATE_USER_SHADER | + COGL_MATERIAL_STATE_DEPTH, COGL_MATERIAL_STATE_AFFECTS_BLENDING = COGL_MATERIAL_STATE_COLOR | @@ -335,7 +337,8 @@ typedef enum _CoglMaterialState COGL_MATERIAL_STATE_LIGHTING | COGL_MATERIAL_STATE_ALPHA_FUNC | COGL_MATERIAL_STATE_BLEND | - COGL_MATERIAL_STATE_USER_SHADER + COGL_MATERIAL_STATE_USER_SHADER | + COGL_MATERIAL_STATE_DEPTH } CoglMaterialState; @@ -388,12 +391,22 @@ typedef struct GLint blend_dst_factor_rgb; } CoglMaterialBlendState; +typedef struct +{ + gboolean depth_test_enabled; + CoglDepthTestFunction depth_test_function; + gboolean depth_writing_enabled; + float depth_range_near; + float depth_range_far; +} CoglMaterialDepthState; + typedef struct { CoglMaterialLightingState lighting_state; CoglMaterialAlphaFuncState alpha_state; CoglMaterialBlendState blend_state; CoglHandle user_program; + CoglMaterialDepthState depth_state; } CoglMaterialBigState; typedef enum diff --git a/cogl/cogl-material.c b/cogl/cogl-material.c index bfd0b4340..f30c533cc 100644 --- a/cogl/cogl-material.c +++ b/cogl/cogl-material.c @@ -347,6 +347,7 @@ _cogl_material_init_default_material (void) CoglMaterialLightingState *lighting_state = &big_state->lighting_state; CoglMaterialAlphaFuncState *alpha_state = &big_state->alpha_state; CoglMaterialBlendState *blend_state = &big_state->blend_state; + CoglMaterialDepthState *depth_state = &big_state->depth_state; _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -409,6 +410,13 @@ _cogl_material_init_default_material (void) big_state->user_program = COGL_INVALID_HANDLE; + /* The same as the GL defaults */ + depth_state->depth_test_enabled = FALSE; + depth_state->depth_test_function = COGL_DEPTH_TEST_FUNCTION_LESS; + depth_state->depth_writing_enabled = TRUE; + depth_state->depth_range_near = 0; + depth_state->depth_range_far = 1; + ctx->default_material = _cogl_material_handle_new (material); } @@ -989,6 +997,13 @@ _cogl_material_copy_differences (CoglMaterial *dest, big_state->user_program = COGL_INVALID_HANDLE; } + if (differences & COGL_MATERIAL_STATE_DEPTH) + { + memcpy (&big_state->depth_state, + &src->big_state->depth_state, + sizeof (CoglMaterialDepthState)); + } + /* XXX: we shouldn't bother doing this in most cases since * _copy_differences is typically used to initialize material state * by copying it from the current authority, so it's not actually @@ -2890,6 +2905,15 @@ _cogl_material_blend_state_equal (CoglMaterial *authority0, return TRUE; } +static gboolean +_cogl_material_depth_state_equal (CoglMaterial *authority0, + CoglMaterial *authority1) +{ + return memcmp (&authority0->big_state->depth_state, + &authority1->big_state->depth_state, + sizeof (CoglMaterialDepthState)) == 0; +} + static gboolean _cogl_material_layers_equal (CoglMaterial *authority0, CoglMaterial *authority1) @@ -3103,6 +3127,19 @@ _cogl_material_equal (CoglHandle handle0, return FALSE; } + if (materials_difference & COGL_MATERIAL_STATE_DEPTH) + { + CoglMaterial *authority0 = + _cogl_material_get_authority (material0, + COGL_MATERIAL_STATE_DEPTH); + CoglMaterial *authority1 = + _cogl_material_get_authority (material1, + COGL_MATERIAL_STATE_DEPTH); + + if (!_cogl_material_depth_state_equal (authority0, authority1)) + return FALSE; + } + if (materials_difference & COGL_MATERIAL_STATE_LAYERS) { CoglMaterial *authority0 = @@ -3888,6 +3925,200 @@ _cogl_material_set_user_program (CoglHandle handle, handle_automatic_blend_enable (material, state); } +void +cogl_material_set_depth_test_enabled (CoglHandle handle, + gboolean enable) +{ + CoglMaterial *material = COGL_MATERIAL (handle); + CoglMaterialState state = COGL_MATERIAL_STATE_DEPTH; + CoglMaterial *authority; + CoglMaterialDepthState *depth_state; + + g_return_if_fail (cogl_is_material (handle)); + + authority = _cogl_material_get_authority (material, state); + + depth_state = &authority->big_state->depth_state; + if (depth_state->depth_test_enabled == enable) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the material has no dependants so it may be modified. + * - If the material isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_material_pre_change_notify (material, state, NULL); + + material->big_state->depth_state.depth_test_enabled = enable; + + _cogl_material_update_authority (material, authority, state, + _cogl_material_depth_state_equal); +} + +gboolean +cogl_material_get_depth_test_enabled (CoglHandle handle) +{ + CoglMaterial *material = COGL_MATERIAL (handle); + CoglMaterial *authority; + + g_return_val_if_fail (cogl_is_material (handle), FALSE); + + authority = + _cogl_material_get_authority (material, COGL_MATERIAL_STATE_DEPTH); + + return authority->big_state->depth_state.depth_test_enabled; +} + +void +cogl_material_set_depth_writing_enabled (CoglHandle handle, + gboolean enable) +{ + CoglMaterial *material = COGL_MATERIAL (handle); + CoglMaterialState state = COGL_MATERIAL_STATE_DEPTH; + CoglMaterial *authority; + CoglMaterialDepthState *depth_state; + + g_return_if_fail (cogl_is_material (handle)); + + authority = _cogl_material_get_authority (material, state); + + depth_state = &authority->big_state->depth_state; + if (depth_state->depth_writing_enabled == enable) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the material has no dependants so it may be modified. + * - If the material isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_material_pre_change_notify (material, state, NULL); + + material->big_state->depth_state.depth_writing_enabled = enable; + + _cogl_material_update_authority (material, authority, state, + _cogl_material_depth_state_equal); +} + +gboolean +cogl_material_get_depth_writing_enabled (CoglHandle handle) +{ + CoglMaterial *material = COGL_MATERIAL (handle); + CoglMaterial *authority; + + g_return_val_if_fail (cogl_is_material (handle), TRUE); + + authority = + _cogl_material_get_authority (material, COGL_MATERIAL_STATE_DEPTH); + + return authority->big_state->depth_state.depth_writing_enabled; +} + +void +cogl_material_set_depth_test_function (CoglHandle handle, + CoglDepthTestFunction function) +{ + CoglMaterial *material = COGL_MATERIAL (handle); + CoglMaterialState state = COGL_MATERIAL_STATE_DEPTH; + CoglMaterial *authority; + CoglMaterialDepthState *depth_state; + + g_return_if_fail (cogl_is_material (handle)); + + authority = _cogl_material_get_authority (material, state); + + depth_state = &authority->big_state->depth_state; + if (depth_state->depth_test_function == function) + return; + + /* - Flush journal primitives referencing the current state. + * - Make sure the material has no dependants so it may be modified. + * - If the material isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_material_pre_change_notify (material, state, NULL); + + material->big_state->depth_state.depth_test_function = function; + + _cogl_material_update_authority (material, authority, state, + _cogl_material_depth_state_equal); +} + +CoglDepthTestFunction +cogl_material_get_depth_test_function (CoglHandle handle) +{ + CoglMaterial *material = COGL_MATERIAL (handle); + CoglMaterial *authority; + + g_return_val_if_fail (cogl_is_material (handle), + COGL_DEPTH_TEST_FUNCTION_LESS); + + authority = + _cogl_material_get_authority (material, COGL_MATERIAL_STATE_DEPTH); + + return authority->big_state->depth_state.depth_test_function; +} + + +gboolean +cogl_material_set_depth_range (CoglHandle handle, + float near, + float far, + GError **error) +{ +#ifndef COGL_HAS_GLES + CoglMaterial *material = COGL_MATERIAL (handle); + CoglMaterialState state = COGL_MATERIAL_STATE_DEPTH; + CoglMaterial *authority; + CoglMaterialDepthState *depth_state; + + g_return_val_if_fail (cogl_is_material (handle), FALSE); + + authority = _cogl_material_get_authority (material, state); + + depth_state = &authority->big_state->depth_state; + if (depth_state->depth_range_near == near && + depth_state->depth_range_far == far) + return TRUE; + + /* - Flush journal primitives referencing the current state. + * - Make sure the material has no dependants so it may be modified. + * - If the material isn't currently an authority for the state being + * changed, then initialize that state from the current authority. + */ + _cogl_material_pre_change_notify (material, state, NULL); + + material->big_state->depth_state.depth_range_near = near; + material->big_state->depth_state.depth_range_far = far; + + _cogl_material_update_authority (material, authority, state, + _cogl_material_depth_state_equal); + return TRUE; +#else + g_set_error (error, + COGL_ERROR, + COGL_ERROR_MISSING_FEATURE, + "glDepthRange not available on GLES 1"); + return FALSE; +#endif +} + +void +cogl_material_get_depth_range (CoglHandle handle, + float *near, + float *far) +{ + CoglMaterial *material = COGL_MATERIAL (handle); + CoglMaterial *authority; + + g_return_if_fail (cogl_is_material (handle)); + + authority = + _cogl_material_get_authority (material, COGL_MATERIAL_STATE_DEPTH); + + *near = authority->big_state->depth_state.depth_range_near; + *far = authority->big_state->depth_state.depth_range_far; +} + static CoglMaterialLayer * _cogl_material_layer_copy (CoglMaterialLayer *src) { @@ -5838,9 +6069,45 @@ blend_factor_uses_constant (GLenum blend_factor) #endif static void -_cogl_material_flush_color_blend_alpha_state (CoglMaterial *material, - unsigned long materials_difference, - gboolean skip_gl_color) +flush_depth_state (CoglMaterialDepthState *depth_state) +{ + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + if (ctx->depth_test_function_cache != depth_state->depth_test_function) + { + GE (glDepthFunc (depth_state->depth_test_function)); + ctx->depth_test_function_cache = depth_state->depth_test_function; + } + + if (ctx->depth_writing_enabled_cache != depth_state->depth_writing_enabled) + { + GE (glDepthMask (depth_state->depth_writing_enabled ? + GL_TRUE : GL_FALSE)); + ctx->depth_writing_enabled_cache = depth_state->depth_writing_enabled; + } + +#ifndef COGL_HAS_GLES + if (ctx->depth_range_near_cache != depth_state->depth_range_near || + ctx->depth_range_far_cache != depth_state->depth_range_far) + { +#ifdef COGL_HAS_GLES2 + GE (glDepthRangef (depth_state->depth_range_near, + depth_state->depth_range_far)); +#else + GE (glDepthRange (depth_state->depth_range_near, + depth_state->depth_range_far)); +#endif + ctx->depth_range_near_cache = depth_state->depth_range_near; + ctx->depth_range_far_cache = depth_state->depth_range_far; + } +#endif /* COGL_HAS_GLES */ +} + +static void +_cogl_material_flush_color_blend_alpha_depth_state ( + CoglMaterial *material, + unsigned long materials_difference, + gboolean skip_gl_color) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -5948,12 +6215,36 @@ _cogl_material_flush_color_blend_alpha_state (CoglMaterial *material, alpha_state->alpha_func_reference)); } + if (materials_difference & COGL_MATERIAL_STATE_DEPTH) + { + CoglMaterial *authority = + _cogl_material_get_authority (material, COGL_MATERIAL_STATE_DEPTH); + CoglMaterialDepthState *depth_state = &authority->big_state->depth_state; + + if (depth_state->depth_test_enabled) + { + if (ctx->depth_test_enabled_cache != TRUE) + { + GE (glEnable (GL_DEPTH_TEST)); + ctx->depth_test_enabled_cache = depth_state->depth_test_enabled; + } + flush_depth_state (depth_state); + } + else if (ctx->depth_test_enabled_cache != FALSE) + { + GE (glDisable (GL_DEPTH_TEST)); + ctx->depth_test_enabled_cache = depth_state->depth_test_enabled; + } + } + if (material->real_blend_enable != ctx->gl_blend_enable_cache) { if (material->real_blend_enable) GE (glEnable (GL_BLEND)); else GE (glDisable (GL_BLEND)); + /* XXX: we shouldn't update any other blend state if blending + * is disabled! */ ctx->gl_blend_enable_cache = material->real_blend_enable; } } @@ -6129,9 +6420,9 @@ _cogl_material_flush_common_gl_state (CoglMaterial *material, _COGL_GET_CONTEXT (ctx, NO_RETVAL); - _cogl_material_flush_color_blend_alpha_state (material, - materials_difference, - skip_gl_color); + _cogl_material_flush_color_blend_alpha_depth_state (material, + materials_difference, + skip_gl_color); state.i = 0; state.layer_differences = layer_differences; @@ -6568,16 +6859,18 @@ _cogl_material_apply_legacy_state (CoglHandle handle) { _COGL_GET_CONTEXT (ctx, NO_RETVAL); + /* It was a mistake that we ever copied the OpenGL style API for + * associating these things directly with the context when we + * originally wrote Cogl. Until the corresponding deprecated APIs + * can be removed though we now shoehorn the state changes through + * the cogl_material API instead. + */ + if (ctx->current_program) - { - /* It was a mistake that we ever copied the OpenGL style API for - * making a program current (cogl_program_use) on the context. - * Until cogl_program_use is removed we will transparently set - * the program on the material because the cogl-material code is - * in the best position to juggle the corresponding GL state. */ - _cogl_material_set_user_program (handle, - ctx->current_program); - } + _cogl_material_set_user_program (handle, ctx->current_program); + + if (ctx->legacy_depth_test_enabled) + cogl_material_set_depth_test_enabled (handle, TRUE); } void diff --git a/cogl/cogl-material.h b/cogl/cogl-material.h index 12c9b39a0..0071dc36a 100644 --- a/cogl/cogl-material.h +++ b/cogl/cogl-material.h @@ -944,6 +944,213 @@ cogl_material_layer_get_wrap_mode_s (CoglHandle layer); CoglMaterialWrapMode cogl_material_layer_get_wrap_mode_t (CoglHandle layer); + +/* XXX: should this be CoglMaterialDepthTestFunction? + * It makes it very verbose but would be consistent with + * CoglMaterialWrapMode */ + +/** + * CoglDepthTestFunction: + * @COGL_DEPTH_TEST_FUNCTION_NEVER: Never passes. + * @COGL_DEPTH_TEST_FUNCTION_LESS: Passes if the fragment's depth + * value is less than the value currently in the depth buffer. + * @COGL_DEPTH_TEST_FUNCTION_EQUAL: Passes if the fragment's depth + * value is equal to the value currently in the depth buffer. + * @COGL_DEPTH_TEST_FUNCTION_LEQUAL: Passes if the fragment's depth + * value is less or equal to the value currently in the depth buffer. + * @COGL_DEPTH_TEST_FUNCTION_GREATER: Passes if the fragment's depth + * value is greater than the value currently in the depth buffer. + * @COGL_DEPTH_TEST_FUNCTION_NOTEQUAL: Passes if the fragment's depth + * value is not equal to the value currently in the depth buffer. + * @COGL_DEPTH_TEST_FUNCTION_GEQUAL: Passes if the fragment's depth + * value greater than or equal to the value currently in the depth buffer. + * @COGL_DEPTH_TEST_FUNCTION_ALWAYS: Always passes. + * + * When using depth testing one of these functions is used to compare + * the depth of an incoming fragment against the depth value currently + * stored in the depth buffer. The function is changed using + * cogl_material_set_depth_test_function(). + * + * The test is only done when depth testing is explicitly enabled. (See + * cogl_material_set_depth_test_enabled()) + */ +typedef enum +{ + COGL_DEPTH_TEST_FUNCTION_NEVER = GL_NEVER, + COGL_DEPTH_TEST_FUNCTION_LESS = GL_LESS, + COGL_DEPTH_TEST_FUNCTION_EQUAL = GL_EQUAL, + COGL_DEPTH_TEST_FUNCTION_LEQUAL = GL_LEQUAL, + COGL_DEPTH_TEST_FUNCTION_GREATER = GL_GREATER, + COGL_DEPTH_TEST_FUNCTION_NOTEQUAL = GL_NOTEQUAL, + COGL_DEPTH_TEST_FUNCTION_GEQUAL = GL_GEQUAL, + COGL_DEPTH_TEST_FUNCTION_ALWAYS = GL_ALWAYS +} CoglDepthTestFunction; +/* XXX: to avoid having to split this into a separate include that can + * in #included internally without needing the + * COGL_ENABLE_EXPERIMENTAL_API define this isn't guarded. It's still + * considered experimental but it's guarded instead by the fact that + * there's no corresponding API. */ + +#ifdef COGL_ENABLE_EXPERIMENTAL_API + +/** + * cogl_material_set_depth_test_enabled: + * @handle: A CoglMaterial handle + * @enable: The enable state you want + * + * Enables or disables depth testing according to the value of + * @enable. + * + * If depth testing is enable then the #CoglDepthTestFunction set + * using cogl_material_set_depth_test_function() us used to evaluate + * the depth value of incoming fragments against the corresponding + * value stored in the current depth buffer, and if the test passes + * then the fragments depth value is used to update the depth buffer. + * (unless you have disabled depth writing via + * cogl_material_set_depth_writing_enabled ()) + * + * By default depth testing is disabled. + * + * Since: 1.4 + */ +void +cogl_material_set_depth_test_enabled (CoglHandle handle, + gboolean enable); + +/** + * cogl_material_get_depth_test_enabled: + * @handle: A CoglMaterial handle + * + * Gets the current depth test enabled state as previously set by + * cogl_material_set_depth_test_enabled(). + * + * Returns: The material's current depth test enabled state. + * Since: 1.4 + */ +gboolean +cogl_material_get_depth_test_enabled (CoglHandle handle); + +/** + * cogl_material_set_depth_writing_enabled: + * @handle: A CoglMaterial handle + * @enable: The enable state you want + * + * Enables or disables depth buffer writing according to the value of + * @enable. Normally when depth testing is enabled and the comparison + * between a fragment's depth value and the corresponding depth buffer + * value passes then the fragment's depth is written to the depth + * buffer unless writing is disabled here. + * + * By default depth writing is enabled + * + * Since: 1.4 + */ +void +cogl_material_set_depth_writing_enabled (CoglHandle handle, + gboolean enable); + +/** + * cogl_material_get_depth_writing_enabled: + * @handle: A CoglMaterial handle + * Since: 1.4 + * + * Gets the depth writing enable state as set by the corresponding + * cogl_material_set_depth_writing_enabled. + * + * Returns: The current depth writing enable state + * Since: 1.4 + */ +gboolean +cogl_material_get_depth_writing_enabled (CoglHandle handle); + +/** + * cogl_material_set_depth_test_function: + * @handle: A CoglMaterial handle + * @function: The #CoglDepthTestFunction to set + * + * Sets the #CoglDepthTestFunction used to compare the depth value of + * an incoming fragment against the corresponding value in the current + * depth buffer. + * + * Since: 1.4 + */ +void +cogl_material_set_depth_test_function (CoglHandle handle, + CoglDepthTestFunction function); + +/** + * cogl_material_get_depth_test_function: + * @handle: A CoglMaterial handle + * + * Gets the current depth test enable state as previously set via + * cogl_material_set_depth_test_enabled(). + * + * Returns: The current depth test enable state. + * Since: 1.4 + */ +CoglDepthTestFunction +cogl_material_get_depth_test_function (CoglHandle handle); + +/** + * cogl_material_set_depth_range: + * @handle: A CoglMaterial handle + * @near: The near component of the desired depth range which will be + * clamped to the range [0, 1] + * @far: The far component of the desired depth range which will be + * clamped to the range [0, 1] + * @error: location to store an error of type #CoglError + * + * Sets the range to map depth values in normalized device coordinates + * to before writing out to a depth buffer. + * + * After your geometry has be transformed, clipped and had perspective + * division applied placing it in normalized device + * coordinates all depth values between the near and far z clipping + * planes are in the range -1 to 1. Before writing any depth value to + * the depth buffer though the value is mapped into the range [0, 1]. + * + * With this function you can change the range which depth values are + * mapped too although the range must still lye within the range [0, + * 1]. + * + * If your driver does not support this feature (for example you are + * using GLES 1 drivers) then this will return %FALSE and set an error + * if @error isn't NULL. You can check ahead of time for the + * %COGL_FEATURE_DEPTH_RANGE feature with cogl_features_available() to + * know if this function will succeed. + * + * By default normalized device coordinate depth values are mapped to + * the full range of depth buffer values, [0, 1]. + * + * Returns: %TRUE if driver support is available else %FALSE. + * + * Since: 1.4 + */ +gboolean +cogl_material_set_depth_range (CoglHandle handle, + float near, + float far, + GError **error); + +/** + * cogl_material_get_depth_range_mapping: + * @handle: A CoglMaterial handle + * @near: A pointer to store the near component of the depth range + * @far: A pointer to store the far component of the depth range + * + * Gets the current range to which normalized depth values are mapped + * before writing to the depth buffer. This corresponds to the range + * set with cogl_material_set_depth_range(). + * + * Since: 1.4 + */ +void +cogl_material_get_depth_range (CoglHandle handle, + float *near, + float *far); + +#endif /* COGL_ENABLE_EXPERIMENTAL_API */ + G_END_DECLS #endif /* __COGL_MATERIAL_H__ */ diff --git a/cogl/cogl-types.h b/cogl/cogl-types.h index 68b6dca4f..54d6d5e2b 100644 --- a/cogl/cogl-types.h +++ b/cogl/cogl-types.h @@ -233,6 +233,7 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/ * @COGL_FEATURE_UNSIGNED_INT_INDICES: Set if * %COGL_INDICES_TYPE_UNSIGNED_INT is supported in * cogl_vertex_buffer_indices_new(). + * @COGL_FEATURE_DEPTH_RANGE: cogl_material_set_depth_range() support * * Flags for the supported features. * @@ -252,7 +253,8 @@ typedef enum COGL_FEATURE_STENCIL_BUFFER = (1 << 10), COGL_FEATURE_VBOS = (1 << 11), COGL_FEATURE_PBOS = (1 << 12), - COGL_FEATURE_UNSIGNED_INT_INDICES = (1 << 13) + COGL_FEATURE_UNSIGNED_INT_INDICES = (1 << 13), + COGL_FEATURE_DEPTH_RANGE = (1 << 14) } CoglFeatureFlags; /** @@ -403,6 +405,27 @@ typedef enum { /*< prefix=COGL_BLEND_STRING_ERROR >*/ GQuark cogl_blend_string_error_quark (void); +#define COGL_ERROR (_cogl_error_quark ()) + +/** + * CoglError: + * @COGL_ERROR_MISSING_FEATURE: You tried to use a feature not + * currently available; likely because of missing driver support. + * + * Error enumeration for Cogl + * + * Currently this is only used by Cogl API marked as experimental so + * this enum should also be considered experimental. + * + * Since: 1.4 + */ +typedef enum { /*< prefix=COGL_ERROR >*/ + COGL_ERROR_MISSING_FEATURE +} CoglError; + +GQuark +_cogl_error_quark (void); + G_END_DECLS #endif /* __COGL_TYPES_H__ */ diff --git a/cogl/cogl.c b/cogl/cogl.c index 81467b74b..46e17ac76 100644 --- a/cogl/cogl.c +++ b/cogl/cogl.c @@ -287,25 +287,28 @@ _cogl_get_enable (void) return ctx->enable_flags; } +/* XXX: This API has been deprecated */ void cogl_set_depth_test_enabled (gboolean setting) { - /* Currently the journal can't track changes to depth state... */ - _cogl_journal_flush (); + _COGL_GET_CONTEXT (ctx, NO_RETVAL); - if (setting) - { - glEnable (GL_DEPTH_TEST); - glDepthFunc (GL_LEQUAL); - } + if (ctx->legacy_depth_test_enabled == setting) + return; + + ctx->legacy_depth_test_enabled = setting; + if (ctx->legacy_depth_test_enabled) + ctx->legacy_state_set++; else - glDisable (GL_DEPTH_TEST); + ctx->legacy_state_set--; } +/* XXX: This API has been deprecated */ gboolean cogl_get_depth_test_enabled (void) { - return glIsEnabled (GL_DEPTH_TEST) == GL_TRUE ? TRUE : FALSE; + _COGL_GET_CONTEXT (ctx, FALSE); + return ctx->legacy_depth_test_enabled; } void @@ -1136,3 +1139,10 @@ _cogl_transform_point (const CoglMatrix *matrix_mv, #undef VIEWPORT_TRANSFORM_X #undef VIEWPORT_TRANSFORM_Y + +GQuark +_cogl_error_quark (void) +{ + return g_quark_from_static_string ("cogl-error-quark"); +} + diff --git a/cogl/cogl.h b/cogl/cogl.h index e639658da..791e1ad5f 100644 --- a/cogl/cogl.h +++ b/cogl/cogl.h @@ -483,6 +483,9 @@ cogl_get_viewport (float v[4]); * order specified using clutter_actor_raise() and * clutter_actor_lower(), otherwise it will also take into account the * actor's depth. Depth testing is disabled by default. + * + * Deprecated: 1.4: Use cogl_material_set_depth_test_enabled() + * instead. */ void cogl_set_depth_test_enabled (gboolean setting); @@ -493,6 +496,9 @@ cogl_set_depth_test_enabled (gboolean setting); * Queries if depth testing has been enabled via cogl_set_depth_test_enable() * * Return value: %TRUE if depth testing is enabled, and %FALSE otherwise + * + * Deprecated: 1.4: Use cogl_material_get_depth_test_enabled() + * instead. */ gboolean cogl_get_depth_test_enabled (void);