diff options
author | Hans Petter Jansson <hpj@cl.no> | 2013-10-10 18:10:52 +0200 |
---|---|---|
committer | Robert Bragg <robert@linux.intel.com> | 2013-10-28 15:59:18 +0000 |
commit | 71406438c5357eb4e0ef03e940c5456a536602a0 (patch) | |
tree | 549411a482035fabe1edbf087ac8b2873e60799d | |
parent | 9bd1ee544667cfe7ecae479ec7f778446dd8f326 (diff) | |
download | cogl-71406438c5357eb4e0ef03e940c5456a536602a0.tar.gz |
Add API to control per-framebuffer depth writing
Add framebuffer methods cogl_framebuffer_[gs]et_depth_write_enabled()
and backend bits to pass the state on to glDepthMask().
This allows us to enable or disable depth writing per-framebuffer, which
if disabled saves us some work in glClear(). When rendering, the flag
is combined with the pipeline's depth writing flag using a logical AND.
Depth writing is enabled by default.
https://bugzilla.gnome.org/show_bug.cgi?id=709827
Reviewed-by: Robert Bragg <robert@linux.intel.com>
-rw-r--r-- | cogl/cogl-framebuffer-private.h | 7 | ||||
-rw-r--r-- | cogl/cogl-framebuffer.c | 36 | ||||
-rw-r--r-- | cogl/cogl-framebuffer.h | 33 | ||||
-rw-r--r-- | cogl/driver/gl/cogl-framebuffer-gl.c | 10 | ||||
-rw-r--r-- | cogl/driver/gl/cogl-pipeline-opengl.c | 11 | ||||
-rw-r--r-- | tests/conform/test-depth-test.c | 20 |
6 files changed, 109 insertions, 8 deletions
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h index 75134123..94bc6d24 100644 --- a/cogl/cogl-framebuffer-private.h +++ b/cogl/cogl-framebuffer-private.h @@ -78,7 +78,8 @@ typedef enum _CoglFramebufferStateIndex COGL_FRAMEBUFFER_STATE_INDEX_PROJECTION = 5, COGL_FRAMEBUFFER_STATE_INDEX_COLOR_MASK = 6, COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING = 7, - COGL_FRAMEBUFFER_STATE_INDEX_MAX = 8 + COGL_FRAMEBUFFER_STATE_INDEX_DEPTH_WRITE = 8, + COGL_FRAMEBUFFER_STATE_INDEX_MAX = 9 } CoglFramebufferStateIndex; typedef enum _CoglFramebufferState @@ -90,7 +91,8 @@ typedef enum _CoglFramebufferState COGL_FRAMEBUFFER_STATE_MODELVIEW = 1<<4, COGL_FRAMEBUFFER_STATE_PROJECTION = 1<<5, COGL_FRAMEBUFFER_STATE_COLOR_MASK = 1<<6, - COGL_FRAMEBUFFER_STATE_FRONT_FACE_WINDING = 1<<7 + COGL_FRAMEBUFFER_STATE_FRONT_FACE_WINDING = 1<<7, + COGL_FRAMEBUFFER_STATE_DEPTH_WRITE = 1<<8 } CoglFramebufferState; #define COGL_FRAMEBUFFER_STATE_ALL ((1<<COGL_FRAMEBUFFER_STATE_INDEX_MAX) - 1) @@ -143,6 +145,7 @@ struct _CoglFramebuffer CoglClipState clip_state; CoglBool dither_enabled; + CoglBool depth_writing_enabled; CoglColorMask color_mask; /* We journal the textured rectangles we want to submit to OpenGL so diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c index b002f619..5c545098 100644 --- a/cogl/cogl-framebuffer.c +++ b/cogl/cogl-framebuffer.c @@ -106,6 +106,7 @@ _cogl_framebuffer_init (CoglFramebuffer *framebuffer, framebuffer->viewport_age = 0; framebuffer->viewport_age_for_scissor_workaround = -1; framebuffer->dither_enabled = TRUE; + framebuffer->depth_writing_enabled = TRUE; framebuffer->modelview_stack = cogl_matrix_stack_new (ctx); framebuffer->projection_stack = cogl_matrix_stack_new (ctx); @@ -801,6 +802,14 @@ _cogl_framebuffer_compare_front_face_winding_state (CoglFramebuffer *a, return 0; } +static unsigned long +_cogl_framebuffer_compare_depth_write_state (CoglFramebuffer *a, + CoglFramebuffer *b) +{ + return a->depth_writing_enabled != b->depth_writing_enabled ? + COGL_FRAMEBUFFER_STATE_DEPTH_WRITE : 0; +} + unsigned long _cogl_framebuffer_compare (CoglFramebuffer *a, CoglFramebuffer *b, @@ -849,6 +858,10 @@ _cogl_framebuffer_compare (CoglFramebuffer *a, differences |= _cogl_framebuffer_compare_front_face_winding_state (a, b); break; + case COGL_FRAMEBUFFER_STATE_INDEX_DEPTH_WRITE: + differences |= + _cogl_framebuffer_compare_depth_write_state (a, b); + break; default: g_warn_if_reached (); } @@ -960,6 +973,29 @@ cogl_framebuffer_set_color_mask (CoglFramebuffer *framebuffer, } CoglBool +cogl_framebuffer_get_depth_write_enabled (CoglFramebuffer *framebuffer) +{ + return framebuffer->depth_writing_enabled; +} + +void +cogl_framebuffer_set_depth_write_enabled (CoglFramebuffer *framebuffer, + CoglBool depth_write_enabled) +{ + if (framebuffer->depth_writing_enabled == depth_write_enabled) + return; + + /* XXX: Currently depth write changes don't go through the journal */ + _cogl_framebuffer_flush_journal (framebuffer); + + framebuffer->depth_writing_enabled = depth_write_enabled; + + if (framebuffer->context->current_draw_buffer == framebuffer) + framebuffer->context->current_draw_buffer_changes |= + COGL_FRAMEBUFFER_STATE_DEPTH_WRITE; +} + +CoglBool cogl_framebuffer_get_dither_enabled (CoglFramebuffer *framebuffer) { return framebuffer->dither_enabled; diff --git a/cogl/cogl-framebuffer.h b/cogl/cogl-framebuffer.h index 053646a3..650552b2 100644 --- a/cogl/cogl-framebuffer.h +++ b/cogl/cogl-framebuffer.h @@ -750,6 +750,39 @@ cogl_framebuffer_set_dither_enabled (CoglFramebuffer *framebuffer, CoglBool dither_enabled); /** + * cogl_framebuffer_get_depth_write_enabled: + * @framebuffer: a pointer to a #CoglFramebuffer + * + * Queries whether depth buffer writing is enabled for @framebuffer. This + * can be controlled via cogl_framebuffer_set_depth_write_enabled(). + * + * Return value: %TRUE if depth writing is enabled or %FALSE if not. + * Since: 1.18 + * Stability: unstable + */ +CoglBool +cogl_framebuffer_get_depth_write_enabled (CoglFramebuffer *framebuffer); + +/** + * cogl_framebuffer_set_depth_write_enabled: + * @framebuffer: a pointer to a #CoglFramebuffer + * @depth_write_enabled: %TRUE to enable depth writing or %FALSE to disable + * + * Enables or disables depth buffer writing when rendering to @framebuffer. + * If depth writing is enabled for both the framebuffer and the rendering + * pipeline, and the framebuffer has an associated depth buffer, depth + * information will be written to this buffer during rendering. + * + * Depth buffer writing is enabled by default. + * + * Since: 1.18 + * Stability: unstable + */ +void +cogl_framebuffer_set_depth_write_enabled (CoglFramebuffer *framebuffer, + CoglBool depth_write_enabled); + +/** * cogl_framebuffer_get_color_mask: * @framebuffer: a pointer to a #CoglFramebuffer * diff --git a/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/driver/gl/cogl-framebuffer-gl.c index 12c6bbd6..e34b58a5 100644 --- a/cogl/driver/gl/cogl-framebuffer-gl.c +++ b/cogl/driver/gl/cogl-framebuffer-gl.c @@ -368,6 +368,10 @@ _cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer, case COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING: _cogl_framebuffer_gl_flush_front_face_winding_state (draw_buffer); break; + case COGL_FRAMEBUFFER_STATE_INDEX_DEPTH_WRITE: + /* Nothing to do for depth write state change; the state will always + * be taken into account when flushing the pipeline's depth state. */ + break; default: g_warn_if_reached (); } @@ -916,11 +920,11 @@ _cogl_framebuffer_gl_clear (CoglFramebuffer *framebuffer, { gl_buffers |= GL_DEPTH_BUFFER_BIT; - if (ctx->depth_writing_enabled_cache != TRUE) + if (ctx->depth_writing_enabled_cache != framebuffer->depth_writing_enabled) { - GE( ctx, glDepthMask (TRUE)); + GE( ctx, glDepthMask (framebuffer->depth_writing_enabled)); - ctx->depth_writing_enabled_cache = TRUE; + ctx->depth_writing_enabled_cache = framebuffer->depth_writing_enabled; /* Make sure the DepthMask is updated when the next primitive is drawn */ ctx->current_pipeline_changes_since_flush |= diff --git a/cogl/driver/gl/cogl-pipeline-opengl.c b/cogl/driver/gl/cogl-pipeline-opengl.c index 4e3aedce..51db17a0 100644 --- a/cogl/driver/gl/cogl-pipeline-opengl.c +++ b/cogl/driver/gl/cogl-pipeline-opengl.c @@ -407,6 +407,11 @@ static void flush_depth_state (CoglContext *ctx, CoglDepthState *depth_state) { + CoglBool depth_writing_enabled = depth_state->write_enabled; + + if (ctx->current_draw_buffer) + depth_writing_enabled &= ctx->current_draw_buffer->depth_writing_enabled; + if (ctx->depth_test_enabled_cache != depth_state->test_enabled) { if (depth_state->test_enabled == TRUE) @@ -423,11 +428,11 @@ flush_depth_state (CoglContext *ctx, ctx->depth_test_function_cache = depth_state->test_function; } - if (ctx->depth_writing_enabled_cache != depth_state->write_enabled) + if (ctx->depth_writing_enabled_cache != depth_writing_enabled) { - GE (ctx, glDepthMask (depth_state->write_enabled ? + GE (ctx, glDepthMask (depth_writing_enabled ? GL_TRUE : GL_FALSE)); - ctx->depth_writing_enabled_cache = depth_state->write_enabled; + ctx->depth_writing_enabled_cache = depth_writing_enabled; } if (ctx->driver != COGL_DRIVER_GLES1 && diff --git a/tests/conform/test-depth-test.c b/tests/conform/test-depth-test.c index 7dca65fc..7b9cdf77 100644 --- a/tests/conform/test-depth-test.c +++ b/tests/conform/test-depth-test.c @@ -28,6 +28,7 @@ typedef struct CoglBool test_enable; CoglDepthTestFunction test_function; CoglBool write_enable; + CoglBool fb_write_enable; float range_near; float range_far; } TestDepthState; @@ -62,6 +63,7 @@ draw_rectangle (TestState *state, cogl_pipeline_set_color4ub (pipeline, Cr, Cg, Cb, Ca); + cogl_framebuffer_set_depth_write_enabled (test_fb, rect_state->fb_write_enable); cogl_framebuffer_push_matrix (test_fb); cogl_framebuffer_translate (test_fb, 0, 0, rect_state->depth); cogl_framebuffer_draw_rectangle (test_fb, @@ -120,6 +122,7 @@ paint (TestState *state) FALSE, /* depth test enable */ COGL_DEPTH_TEST_FUNCTION_ALWAYS, TRUE, /* depth write enable */ + TRUE, /* FB depth write enable */ 0, 1 /* depth range */ }; /* Furthest */ @@ -129,6 +132,7 @@ paint (TestState *state) TRUE, /* depth test enable */ COGL_DEPTH_TEST_FUNCTION_ALWAYS, TRUE, /* depth write enable */ + TRUE, /* FB depth write enable */ 0, 1 /* depth range */ }; /* In the middle */ @@ -138,6 +142,7 @@ paint (TestState *state) TRUE, /* depth test enable */ COGL_DEPTH_TEST_FUNCTION_NEVER, TRUE, /* depth write enable */ + TRUE, /* FB depth write enable */ 0, 1 /* depth range */ }; @@ -165,6 +170,19 @@ paint (TestState *state) test_depth (state, 4, 0, /* position */ &rect0_state, &rect1_state, &rect2_state, 0x0000ffff); /* expected */ + + rect1_state.write_enable = TRUE; + rect1_state.fb_write_enable = FALSE; + test_depth (state, 4, 0, /* position */ + &rect0_state, &rect1_state, &rect2_state, + 0x0000ffff); /* expected */ + + /* Re-enable FB depth writing to verify state flush */ + rect1_state.write_enable = TRUE; + rect1_state.fb_write_enable = TRUE; + test_depth (state, 4, 0, /* position */ + &rect0_state, &rect1_state, &rect2_state, + 0x00ff00ff); /* expected */ } /* Check that the depth buffer values can be mapped into different @@ -178,6 +196,7 @@ paint (TestState *state) TRUE, /* depth test enable */ COGL_DEPTH_TEST_FUNCTION_ALWAYS, TRUE, /* depth write enable */ + TRUE, /* FB depth write enable */ 0.5, 1 /* depth range */ }; /* Furthest by depth, nearest by depth range */ @@ -187,6 +206,7 @@ paint (TestState *state) TRUE, /* depth test enable */ COGL_DEPTH_TEST_FUNCTION_GREATER, TRUE, /* depth write enable */ + TRUE, /* FB depth write enable */ 0, 0.5 /* depth range */ }; |