mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 04:22:05 +00:00
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.
This commit is contained in:
parent
ff4d3e048b
commit
c434f1fc48
@ -127,6 +127,14 @@ cogl_create_context (void)
|
|||||||
|
|
||||||
_context->gl_blend_enable_cache = FALSE;
|
_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 ();
|
_context->framebuffer_stack = _cogl_create_framebuffer_stack ();
|
||||||
|
|
||||||
window_buffer = _cogl_onscreen_new ();
|
window_buffer = _cogl_onscreen_new ();
|
||||||
|
@ -109,6 +109,14 @@ typedef struct
|
|||||||
|
|
||||||
gboolean gl_blend_enable_cache;
|
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 */
|
/* PBOs */
|
||||||
/* This can be used to check if a pbo is bound */
|
/* This can be used to check if a pbo is bound */
|
||||||
CoglBuffer *current_pbo;
|
CoglBuffer *current_pbo;
|
||||||
|
@ -311,8 +311,9 @@ typedef enum _CoglMaterialState
|
|||||||
COGL_MATERIAL_STATE_ALPHA_FUNC = 1L<<4,
|
COGL_MATERIAL_STATE_ALPHA_FUNC = 1L<<4,
|
||||||
COGL_MATERIAL_STATE_BLEND = 1L<<5,
|
COGL_MATERIAL_STATE_BLEND = 1L<<5,
|
||||||
COGL_MATERIAL_STATE_USER_SHADER = 1L<<6,
|
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_ALL_SPARSE =
|
||||||
COGL_MATERIAL_STATE_COLOR |
|
COGL_MATERIAL_STATE_COLOR |
|
||||||
@ -321,7 +322,8 @@ typedef enum _CoglMaterialState
|
|||||||
COGL_MATERIAL_STATE_LIGHTING |
|
COGL_MATERIAL_STATE_LIGHTING |
|
||||||
COGL_MATERIAL_STATE_ALPHA_FUNC |
|
COGL_MATERIAL_STATE_ALPHA_FUNC |
|
||||||
COGL_MATERIAL_STATE_BLEND |
|
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_AFFECTS_BLENDING =
|
||||||
COGL_MATERIAL_STATE_COLOR |
|
COGL_MATERIAL_STATE_COLOR |
|
||||||
@ -335,7 +337,8 @@ typedef enum _CoglMaterialState
|
|||||||
COGL_MATERIAL_STATE_LIGHTING |
|
COGL_MATERIAL_STATE_LIGHTING |
|
||||||
COGL_MATERIAL_STATE_ALPHA_FUNC |
|
COGL_MATERIAL_STATE_ALPHA_FUNC |
|
||||||
COGL_MATERIAL_STATE_BLEND |
|
COGL_MATERIAL_STATE_BLEND |
|
||||||
COGL_MATERIAL_STATE_USER_SHADER
|
COGL_MATERIAL_STATE_USER_SHADER |
|
||||||
|
COGL_MATERIAL_STATE_DEPTH
|
||||||
|
|
||||||
} CoglMaterialState;
|
} CoglMaterialState;
|
||||||
|
|
||||||
@ -388,12 +391,22 @@ typedef struct
|
|||||||
GLint blend_dst_factor_rgb;
|
GLint blend_dst_factor_rgb;
|
||||||
} CoglMaterialBlendState;
|
} 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
|
typedef struct
|
||||||
{
|
{
|
||||||
CoglMaterialLightingState lighting_state;
|
CoglMaterialLightingState lighting_state;
|
||||||
CoglMaterialAlphaFuncState alpha_state;
|
CoglMaterialAlphaFuncState alpha_state;
|
||||||
CoglMaterialBlendState blend_state;
|
CoglMaterialBlendState blend_state;
|
||||||
CoglHandle user_program;
|
CoglHandle user_program;
|
||||||
|
CoglMaterialDepthState depth_state;
|
||||||
} CoglMaterialBigState;
|
} CoglMaterialBigState;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -347,6 +347,7 @@ _cogl_material_init_default_material (void)
|
|||||||
CoglMaterialLightingState *lighting_state = &big_state->lighting_state;
|
CoglMaterialLightingState *lighting_state = &big_state->lighting_state;
|
||||||
CoglMaterialAlphaFuncState *alpha_state = &big_state->alpha_state;
|
CoglMaterialAlphaFuncState *alpha_state = &big_state->alpha_state;
|
||||||
CoglMaterialBlendState *blend_state = &big_state->blend_state;
|
CoglMaterialBlendState *blend_state = &big_state->blend_state;
|
||||||
|
CoglMaterialDepthState *depth_state = &big_state->depth_state;
|
||||||
|
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
@ -409,6 +410,13 @@ _cogl_material_init_default_material (void)
|
|||||||
|
|
||||||
big_state->user_program = COGL_INVALID_HANDLE;
|
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);
|
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;
|
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
|
/* XXX: we shouldn't bother doing this in most cases since
|
||||||
* _copy_differences is typically used to initialize material state
|
* _copy_differences is typically used to initialize material state
|
||||||
* by copying it from the current authority, so it's not actually
|
* 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;
|
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
|
static gboolean
|
||||||
_cogl_material_layers_equal (CoglMaterial *authority0,
|
_cogl_material_layers_equal (CoglMaterial *authority0,
|
||||||
CoglMaterial *authority1)
|
CoglMaterial *authority1)
|
||||||
@ -3103,6 +3127,19 @@ _cogl_material_equal (CoglHandle handle0,
|
|||||||
return FALSE;
|
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)
|
if (materials_difference & COGL_MATERIAL_STATE_LAYERS)
|
||||||
{
|
{
|
||||||
CoglMaterial *authority0 =
|
CoglMaterial *authority0 =
|
||||||
@ -3888,6 +3925,200 @@ _cogl_material_set_user_program (CoglHandle handle,
|
|||||||
handle_automatic_blend_enable (material, state);
|
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 *
|
static CoglMaterialLayer *
|
||||||
_cogl_material_layer_copy (CoglMaterialLayer *src)
|
_cogl_material_layer_copy (CoglMaterialLayer *src)
|
||||||
{
|
{
|
||||||
@ -5838,9 +6069,45 @@ blend_factor_uses_constant (GLenum blend_factor)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_material_flush_color_blend_alpha_state (CoglMaterial *material,
|
flush_depth_state (CoglMaterialDepthState *depth_state)
|
||||||
unsigned long materials_difference,
|
{
|
||||||
gboolean skip_gl_color)
|
_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);
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
@ -5948,12 +6215,36 @@ _cogl_material_flush_color_blend_alpha_state (CoglMaterial *material,
|
|||||||
alpha_state->alpha_func_reference));
|
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 != ctx->gl_blend_enable_cache)
|
||||||
{
|
{
|
||||||
if (material->real_blend_enable)
|
if (material->real_blend_enable)
|
||||||
GE (glEnable (GL_BLEND));
|
GE (glEnable (GL_BLEND));
|
||||||
else
|
else
|
||||||
GE (glDisable (GL_BLEND));
|
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;
|
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_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
|
|
||||||
_cogl_material_flush_color_blend_alpha_state (material,
|
_cogl_material_flush_color_blend_alpha_depth_state (material,
|
||||||
materials_difference,
|
materials_difference,
|
||||||
skip_gl_color);
|
skip_gl_color);
|
||||||
|
|
||||||
state.i = 0;
|
state.i = 0;
|
||||||
state.layer_differences = layer_differences;
|
state.layer_differences = layer_differences;
|
||||||
@ -6568,16 +6859,18 @@ _cogl_material_apply_legacy_state (CoglHandle handle)
|
|||||||
{
|
{
|
||||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
_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)
|
if (ctx->current_program)
|
||||||
{
|
_cogl_material_set_user_program (handle, 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.
|
if (ctx->legacy_depth_test_enabled)
|
||||||
* Until cogl_program_use is removed we will transparently set
|
cogl_material_set_depth_test_enabled (handle, TRUE);
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -944,6 +944,213 @@ cogl_material_layer_get_wrap_mode_s (CoglHandle layer);
|
|||||||
CoglMaterialWrapMode
|
CoglMaterialWrapMode
|
||||||
cogl_material_layer_get_wrap_mode_t (CoglHandle layer);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __COGL_MATERIAL_H__ */
|
#endif /* __COGL_MATERIAL_H__ */
|
||||||
|
@ -233,6 +233,7 @@ typedef enum { /*< prefix=COGL_PIXEL_FORMAT >*/
|
|||||||
* @COGL_FEATURE_UNSIGNED_INT_INDICES: Set if
|
* @COGL_FEATURE_UNSIGNED_INT_INDICES: Set if
|
||||||
* %COGL_INDICES_TYPE_UNSIGNED_INT is supported in
|
* %COGL_INDICES_TYPE_UNSIGNED_INT is supported in
|
||||||
* cogl_vertex_buffer_indices_new().
|
* cogl_vertex_buffer_indices_new().
|
||||||
|
* @COGL_FEATURE_DEPTH_RANGE: cogl_material_set_depth_range() support
|
||||||
*
|
*
|
||||||
* Flags for the supported features.
|
* Flags for the supported features.
|
||||||
*
|
*
|
||||||
@ -252,7 +253,8 @@ typedef enum
|
|||||||
COGL_FEATURE_STENCIL_BUFFER = (1 << 10),
|
COGL_FEATURE_STENCIL_BUFFER = (1 << 10),
|
||||||
COGL_FEATURE_VBOS = (1 << 11),
|
COGL_FEATURE_VBOS = (1 << 11),
|
||||||
COGL_FEATURE_PBOS = (1 << 12),
|
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;
|
} CoglFeatureFlags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -403,6 +405,27 @@ typedef enum { /*< prefix=COGL_BLEND_STRING_ERROR >*/
|
|||||||
GQuark
|
GQuark
|
||||||
cogl_blend_string_error_quark (void);
|
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
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __COGL_TYPES_H__ */
|
#endif /* __COGL_TYPES_H__ */
|
||||||
|
@ -287,25 +287,28 @@ _cogl_get_enable (void)
|
|||||||
return ctx->enable_flags;
|
return ctx->enable_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX: This API has been deprecated */
|
||||||
void
|
void
|
||||||
cogl_set_depth_test_enabled (gboolean setting)
|
cogl_set_depth_test_enabled (gboolean setting)
|
||||||
{
|
{
|
||||||
/* Currently the journal can't track changes to depth state... */
|
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||||
_cogl_journal_flush ();
|
|
||||||
|
|
||||||
if (setting)
|
if (ctx->legacy_depth_test_enabled == setting)
|
||||||
{
|
return;
|
||||||
glEnable (GL_DEPTH_TEST);
|
|
||||||
glDepthFunc (GL_LEQUAL);
|
ctx->legacy_depth_test_enabled = setting;
|
||||||
}
|
if (ctx->legacy_depth_test_enabled)
|
||||||
|
ctx->legacy_state_set++;
|
||||||
else
|
else
|
||||||
glDisable (GL_DEPTH_TEST);
|
ctx->legacy_state_set--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* XXX: This API has been deprecated */
|
||||||
gboolean
|
gboolean
|
||||||
cogl_get_depth_test_enabled (void)
|
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
|
void
|
||||||
@ -1136,3 +1139,10 @@ _cogl_transform_point (const CoglMatrix *matrix_mv,
|
|||||||
|
|
||||||
#undef VIEWPORT_TRANSFORM_X
|
#undef VIEWPORT_TRANSFORM_X
|
||||||
#undef VIEWPORT_TRANSFORM_Y
|
#undef VIEWPORT_TRANSFORM_Y
|
||||||
|
|
||||||
|
GQuark
|
||||||
|
_cogl_error_quark (void)
|
||||||
|
{
|
||||||
|
return g_quark_from_static_string ("cogl-error-quark");
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -483,6 +483,9 @@ cogl_get_viewport (float v[4]);
|
|||||||
* order specified using clutter_actor_raise() and
|
* order specified using clutter_actor_raise() and
|
||||||
* clutter_actor_lower(), otherwise it will also take into account the
|
* clutter_actor_lower(), otherwise it will also take into account the
|
||||||
* actor's depth. Depth testing is disabled by default.
|
* actor's depth. Depth testing is disabled by default.
|
||||||
|
*
|
||||||
|
* Deprecated: 1.4: Use cogl_material_set_depth_test_enabled()
|
||||||
|
* instead.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
cogl_set_depth_test_enabled (gboolean setting);
|
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()
|
* Queries if depth testing has been enabled via cogl_set_depth_test_enable()
|
||||||
*
|
*
|
||||||
* Return value: %TRUE if depth testing is enabled, and %FALSE otherwise
|
* Return value: %TRUE if depth testing is enabled, and %FALSE otherwise
|
||||||
|
*
|
||||||
|
* Deprecated: 1.4: Use cogl_material_get_depth_test_enabled()
|
||||||
|
* instead.
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
cogl_get_depth_test_enabled (void);
|
cogl_get_depth_test_enabled (void);
|
||||||
|
@ -31,6 +31,7 @@ test_conformance_SOURCES = \
|
|||||||
test-cogl-pixel-buffer.c \
|
test-cogl-pixel-buffer.c \
|
||||||
test-cogl-path.c \
|
test-cogl-path.c \
|
||||||
test-cogl-object.c \
|
test-cogl-object.c \
|
||||||
|
test-cogl-depth-test.c \
|
||||||
test-path.c \
|
test-path.c \
|
||||||
test-pick.c \
|
test-pick.c \
|
||||||
test-clutter-rectangle.c \
|
test-clutter-rectangle.c \
|
||||||
|
354
tests/conform/test-cogl-depth-test.c
Normal file
354
tests/conform/test-cogl-depth-test.c
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
|
||||||
|
#include <clutter/clutter.h>
|
||||||
|
|
||||||
|
#ifndef COGL_ENABLE_EXPERIMENTAL_API
|
||||||
|
#define COGL_ENABLE_EXPERIMENTAL_API
|
||||||
|
#endif
|
||||||
|
#include <cogl/cogl.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "test-conform-common.h"
|
||||||
|
|
||||||
|
static const ClutterColor stage_color = { 0x0, 0x0, 0x0, 0xff };
|
||||||
|
|
||||||
|
#define QUAD_WIDTH 20
|
||||||
|
|
||||||
|
#define RED 0
|
||||||
|
#define GREEN 1
|
||||||
|
#define BLUE 2
|
||||||
|
#define ALPHA 3
|
||||||
|
|
||||||
|
#define MASK_RED(COLOR) ((COLOR & 0xff000000) >> 24);
|
||||||
|
#define MASK_GREEN(COLOR) ((COLOR & 0xff0000) >> 16);
|
||||||
|
#define MASK_BLUE(COLOR) ((COLOR & 0xff00) >> 8);
|
||||||
|
#define MASK_ALPHA(COLOR) (COLOR & 0xff);
|
||||||
|
|
||||||
|
typedef struct _TestState
|
||||||
|
{
|
||||||
|
guint frame;
|
||||||
|
ClutterGeometry stage_geom;
|
||||||
|
} TestState;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
guint32 color;
|
||||||
|
float depth;
|
||||||
|
gboolean test_enable;
|
||||||
|
CoglDepthTestFunction test_function;
|
||||||
|
gboolean write_enable;
|
||||||
|
float range_near;
|
||||||
|
float range_far;
|
||||||
|
} TestDepthState;
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_pixel (GLubyte *pixel, guint32 color)
|
||||||
|
{
|
||||||
|
guint8 r = MASK_RED (color);
|
||||||
|
guint8 g = MASK_GREEN (color);
|
||||||
|
guint8 b = MASK_BLUE (color);
|
||||||
|
guint8 a = MASK_ALPHA (color);
|
||||||
|
|
||||||
|
if (g_test_verbose ())
|
||||||
|
g_print (" expected = %x, %x, %x, %x\n",
|
||||||
|
r, g, b, a);
|
||||||
|
/* FIXME - allow for hardware in-precision */
|
||||||
|
g_assert_cmpint (pixel[RED], ==, r);
|
||||||
|
g_assert_cmpint (pixel[GREEN], ==, g);
|
||||||
|
g_assert_cmpint (pixel[BLUE], ==, b);
|
||||||
|
|
||||||
|
/* FIXME
|
||||||
|
* We ignore the alpha, since we don't know if our render target is
|
||||||
|
* RGB or RGBA */
|
||||||
|
/* g_assert (pixel[ALPHA] == a); */
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
draw_rectangle (TestState *state,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
TestDepthState *rect_state)
|
||||||
|
{
|
||||||
|
guint8 Cr = MASK_RED (rect_state->color);
|
||||||
|
guint8 Cg = MASK_GREEN (rect_state->color);
|
||||||
|
guint8 Cb = MASK_BLUE (rect_state->color);
|
||||||
|
guint8 Ca = MASK_ALPHA (rect_state->color);
|
||||||
|
CoglHandle material;
|
||||||
|
|
||||||
|
material = cogl_material_new ();
|
||||||
|
cogl_material_set_depth_test_enabled (material, rect_state->test_enable);
|
||||||
|
cogl_material_set_depth_test_function (material, rect_state->test_function);
|
||||||
|
cogl_material_set_depth_writing_enabled (material, rect_state->write_enable);
|
||||||
|
if (!cogl_material_set_depth_range (material,
|
||||||
|
rect_state->range_near,
|
||||||
|
rect_state->range_far,
|
||||||
|
NULL))
|
||||||
|
{
|
||||||
|
cogl_handle_unref (material);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cogl_material_set_color4ub (material, Cr, Cg, Cb, Ca);
|
||||||
|
|
||||||
|
cogl_set_source (material);
|
||||||
|
|
||||||
|
cogl_push_matrix ();
|
||||||
|
cogl_translate (0, 0, rect_state->depth);
|
||||||
|
cogl_rectangle (x * QUAD_WIDTH,
|
||||||
|
y * QUAD_WIDTH,
|
||||||
|
x * QUAD_WIDTH + QUAD_WIDTH,
|
||||||
|
y * QUAD_WIDTH + QUAD_WIDTH);
|
||||||
|
cogl_pop_matrix ();
|
||||||
|
|
||||||
|
cogl_handle_unref (material);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_depth (TestState *state,
|
||||||
|
int x,
|
||||||
|
int y,
|
||||||
|
TestDepthState *rect0_state,
|
||||||
|
TestDepthState *rect1_state,
|
||||||
|
TestDepthState *rect2_state,
|
||||||
|
guint32 expected_result)
|
||||||
|
{
|
||||||
|
GLubyte pixel[4];
|
||||||
|
GLint y_off;
|
||||||
|
GLint x_off;
|
||||||
|
gboolean missing_feature = FALSE;
|
||||||
|
|
||||||
|
if (rect0_state)
|
||||||
|
missing_feature |= !draw_rectangle (state, x, y, rect0_state);
|
||||||
|
if (rect1_state)
|
||||||
|
missing_feature |= !draw_rectangle (state, x, y, rect1_state);
|
||||||
|
if (rect2_state)
|
||||||
|
missing_feature |= !draw_rectangle (state, x, y, rect2_state);
|
||||||
|
|
||||||
|
/* We don't consider it an error that we can't test something
|
||||||
|
* the driver doesn't support. */
|
||||||
|
if (missing_feature)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* See what we got... */
|
||||||
|
|
||||||
|
y_off = y * QUAD_WIDTH + (QUAD_WIDTH / 2);
|
||||||
|
x_off = x * QUAD_WIDTH + (QUAD_WIDTH / 2);
|
||||||
|
|
||||||
|
/* XXX:
|
||||||
|
* We haven't always had good luck with GL drivers implementing glReadPixels
|
||||||
|
* reliably and skipping the first two frames improves our chances... */
|
||||||
|
if (state->frame <= 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cogl_read_pixels (x_off, y_off, 1, 1,
|
||||||
|
COGL_READ_PIXELS_COLOR_BUFFER,
|
||||||
|
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
|
||||||
|
pixel);
|
||||||
|
|
||||||
|
check_pixel (pixel, expected_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_paint (ClutterActor *actor, TestState *state)
|
||||||
|
{
|
||||||
|
int frame_num;
|
||||||
|
CoglMatrix projection_save;
|
||||||
|
CoglMatrix identity;
|
||||||
|
|
||||||
|
/* We don't want the effects of perspective division to interfere
|
||||||
|
* with the positions of our test rectangles on the x and y axis
|
||||||
|
* so we use an orthographic projection...
|
||||||
|
*/
|
||||||
|
|
||||||
|
cogl_get_projection_matrix (&projection_save);
|
||||||
|
|
||||||
|
cogl_ortho (0, state->stage_geom.width, /* left, right */
|
||||||
|
state->stage_geom.height, 0, /* bottom, top */
|
||||||
|
-1, 100 /* z near, far */);
|
||||||
|
|
||||||
|
cogl_push_matrix ();
|
||||||
|
cogl_matrix_init_identity (&identity);
|
||||||
|
cogl_set_modelview_matrix (&identity);
|
||||||
|
|
||||||
|
/* Sanity check a few of the different depth test functions
|
||||||
|
* and that depth writing can be disabled... */
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Closest */
|
||||||
|
TestDepthState rect0_state = {
|
||||||
|
0xff0000ff, /* rgba color */
|
||||||
|
-10, /* depth */
|
||||||
|
FALSE, /* depth test enable */
|
||||||
|
COGL_DEPTH_TEST_FUNCTION_ALWAYS,
|
||||||
|
TRUE, /* depth write enable */
|
||||||
|
0, 1 /* depth range */
|
||||||
|
};
|
||||||
|
/* Furthest */
|
||||||
|
TestDepthState rect1_state = {
|
||||||
|
0x00ff00ff, /* rgba color */
|
||||||
|
-70, /* depth */
|
||||||
|
TRUE, /* depth test enable */
|
||||||
|
COGL_DEPTH_TEST_FUNCTION_ALWAYS,
|
||||||
|
TRUE, /* depth write enable */
|
||||||
|
0, 1 /* depth range */
|
||||||
|
};
|
||||||
|
/* In the middle */
|
||||||
|
TestDepthState rect2_state = {
|
||||||
|
0x0000ffff, /* rgba color */
|
||||||
|
-20, /* depth */
|
||||||
|
TRUE, /* depth test enable */
|
||||||
|
COGL_DEPTH_TEST_FUNCTION_NEVER,
|
||||||
|
TRUE, /* depth write enable */
|
||||||
|
0, 1 /* depth range */
|
||||||
|
};
|
||||||
|
|
||||||
|
test_depth (state, 0, 0, /* position */
|
||||||
|
&rect0_state, &rect1_state, &rect2_state,
|
||||||
|
0x00ff00ff); /* expected */
|
||||||
|
|
||||||
|
rect2_state.test_function = COGL_DEPTH_TEST_FUNCTION_ALWAYS;
|
||||||
|
test_depth (state, 1, 0, /* position */
|
||||||
|
&rect0_state, &rect1_state, &rect2_state,
|
||||||
|
0x0000ffff); /* expected */
|
||||||
|
|
||||||
|
rect2_state.test_function = COGL_DEPTH_TEST_FUNCTION_LESS;
|
||||||
|
test_depth (state, 2, 0, /* position */
|
||||||
|
&rect0_state, &rect1_state, &rect2_state,
|
||||||
|
0x0000ffff); /* expected */
|
||||||
|
|
||||||
|
rect2_state.test_function = COGL_DEPTH_TEST_FUNCTION_GREATER;
|
||||||
|
test_depth (state, 3, 0, /* position */
|
||||||
|
&rect0_state, &rect1_state, &rect2_state,
|
||||||
|
0x00ff00ff); /* expected */
|
||||||
|
|
||||||
|
rect0_state.test_enable = TRUE;
|
||||||
|
rect1_state.write_enable = FALSE;
|
||||||
|
test_depth (state, 4, 0, /* position */
|
||||||
|
&rect0_state, &rect1_state, &rect2_state,
|
||||||
|
0x0000ffff); /* expected */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check that the depth buffer values can be mapped into different
|
||||||
|
* ranges... */
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Closest by depth, furthest by depth range */
|
||||||
|
TestDepthState rect0_state = {
|
||||||
|
0xff0000ff, /* rgba color */
|
||||||
|
-10, /* depth */
|
||||||
|
TRUE, /* depth test enable */
|
||||||
|
COGL_DEPTH_TEST_FUNCTION_ALWAYS,
|
||||||
|
TRUE, /* depth write enable */
|
||||||
|
0.5, 1 /* depth range */
|
||||||
|
};
|
||||||
|
/* Furthest by depth, nearest by depth range */
|
||||||
|
TestDepthState rect1_state = {
|
||||||
|
0x00ff00ff, /* rgba color */
|
||||||
|
-70, /* depth */
|
||||||
|
TRUE, /* depth test enable */
|
||||||
|
COGL_DEPTH_TEST_FUNCTION_GREATER,
|
||||||
|
TRUE, /* depth write enable */
|
||||||
|
0, 0.5 /* depth range */
|
||||||
|
};
|
||||||
|
|
||||||
|
test_depth (state, 0, 1, /* position */
|
||||||
|
&rect0_state, &rect1_state, NULL,
|
||||||
|
0xff0000ff); /* expected */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test that the legacy cogl_set_depth_test_enabled() API still
|
||||||
|
* works... */
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Nearest */
|
||||||
|
TestDepthState rect0_state = {
|
||||||
|
0xff0000ff, /* rgba color */
|
||||||
|
-10, /* depth */
|
||||||
|
FALSE, /* depth test enable */
|
||||||
|
COGL_DEPTH_TEST_FUNCTION_LESS,
|
||||||
|
TRUE, /* depth write enable */
|
||||||
|
0, 1 /* depth range */
|
||||||
|
};
|
||||||
|
/* Furthest */
|
||||||
|
TestDepthState rect1_state = {
|
||||||
|
0x00ff00ff, /* rgba color */
|
||||||
|
-70, /* depth */
|
||||||
|
FALSE, /* depth test enable */
|
||||||
|
COGL_DEPTH_TEST_FUNCTION_LESS,
|
||||||
|
TRUE, /* depth write enable */
|
||||||
|
0, 1 /* depth range */
|
||||||
|
};
|
||||||
|
|
||||||
|
cogl_set_depth_test_enabled (TRUE);
|
||||||
|
test_depth (state, 0, 2, /* position */
|
||||||
|
&rect0_state, &rect1_state, NULL,
|
||||||
|
0xff0000ff); /* expected */
|
||||||
|
cogl_set_depth_test_enabled (FALSE);
|
||||||
|
test_depth (state, 1, 2, /* position */
|
||||||
|
&rect0_state, &rect1_state, NULL,
|
||||||
|
0x00ff00ff); /* expected */
|
||||||
|
}
|
||||||
|
|
||||||
|
cogl_pop_matrix ();
|
||||||
|
cogl_set_projection_matrix (&projection_save);
|
||||||
|
|
||||||
|
/* XXX: Experiments have shown that for some buggy drivers, when using
|
||||||
|
* glReadPixels there is some kind of race, so we delay our test for a
|
||||||
|
* few frames and a few seconds: */
|
||||||
|
frame_num = state->frame++;
|
||||||
|
if (frame_num < 2)
|
||||||
|
g_usleep (G_USEC_PER_SEC);
|
||||||
|
|
||||||
|
/* Comment this out if you want visual feedback for what this test paints */
|
||||||
|
#if 1
|
||||||
|
if (frame_num == 3)
|
||||||
|
clutter_main_quit ();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
queue_redraw (gpointer stage)
|
||||||
|
{
|
||||||
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test_cogl_depth_test (TestConformSimpleFixture *fixture,
|
||||||
|
gconstpointer data)
|
||||||
|
{
|
||||||
|
TestState state;
|
||||||
|
ClutterActor *stage;
|
||||||
|
ClutterActor *group;
|
||||||
|
guint idle_source;
|
||||||
|
|
||||||
|
state.frame = 0;
|
||||||
|
|
||||||
|
stage = clutter_stage_get_default ();
|
||||||
|
|
||||||
|
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||||
|
clutter_actor_get_geometry (stage, &state.stage_geom);
|
||||||
|
|
||||||
|
group = clutter_group_new ();
|
||||||
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
|
||||||
|
|
||||||
|
/* We force continuous redrawing of the stage, since we need to skip
|
||||||
|
* the first few frames, and we wont be doing anything else that
|
||||||
|
* will trigger redrawing. */
|
||||||
|
idle_source = g_idle_add (queue_redraw, stage);
|
||||||
|
|
||||||
|
g_signal_connect (group, "paint", G_CALLBACK (on_paint), &state);
|
||||||
|
|
||||||
|
clutter_actor_show_all (stage);
|
||||||
|
|
||||||
|
clutter_main ();
|
||||||
|
|
||||||
|
g_source_remove (idle_source);
|
||||||
|
|
||||||
|
if (g_test_verbose ())
|
||||||
|
g_print ("OK\n");
|
||||||
|
}
|
||||||
|
|
@ -198,6 +198,7 @@ main (int argc, char **argv)
|
|||||||
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_premult);
|
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_premult);
|
||||||
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_readpixels);
|
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_readpixels);
|
||||||
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_path);
|
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_path);
|
||||||
|
TEST_CONFORM_SIMPLE ("/cogl", test_cogl_depth_test);
|
||||||
|
|
||||||
TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_npot_texture);
|
TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_npot_texture);
|
||||||
TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_multitexture);
|
TEST_CONFORM_SIMPLE ("/cogl/texture", test_cogl_multitexture);
|
||||||
|
Loading…
Reference in New Issue
Block a user