summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cogl/cogl-context-private.h1
-rw-r--r--cogl/cogl-context.c1
-rw-r--r--cogl/cogl-framebuffer-private.h1
-rw-r--r--cogl/cogl-framebuffer.c38
-rw-r--r--cogl/cogl-framebuffer.h28
-rw-r--r--cogl/cogl-pipeline-opengl.c18
-rw-r--r--cogl/cogl-pipeline-private.h15
-rw-r--r--cogl/cogl-pipeline.c89
-rw-r--r--cogl/cogl-pipeline.h34
-rw-r--r--cogl/cogl-types.h26
10 files changed, 248 insertions, 3 deletions
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 4ce999b3..20123c6c 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -204,6 +204,7 @@ struct _CoglContext
GLuint current_gl_program;
gboolean current_gl_dither_enabled;
+ CoglColorMask current_gl_color_mask;
/* List of types that will be considered a subclass of CoglTexture in
cogl_is_texture */
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 2674b235..088bfae6 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -277,6 +277,7 @@ cogl_context_new (CoglDisplay *display,
context->current_gl_program = 0;
context->current_gl_dither_enabled = TRUE;
+ context->current_gl_color_mask = COGL_COLOR_MASK_ALL;
context->gl_blend_enable_cache = FALSE;
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index 1b0ee444..3e41077d 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -75,6 +75,7 @@ struct _CoglFramebuffer
int alpha_bits;
gboolean dither_enabled;
+ CoglColorMask color_mask;
/* We journal the textured rectangles we want to submit to OpenGL so
* we have an oppertunity to batch them together into less draw
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index af8cc9a2..37d8514e 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -155,6 +155,8 @@ _cogl_framebuffer_init (CoglFramebuffer *framebuffer,
framebuffer->dirty_bitmasks = TRUE;
+ framebuffer->color_mask = COGL_COLOR_MASK_ALL;
+
/* Initialise the clip stack */
_cogl_clip_state_init (&framebuffer->clip_state);
@@ -238,8 +240,24 @@ _cogl_clear4f (unsigned long buffers,
if (buffers & COGL_BUFFER_BIT_COLOR)
{
+ CoglFramebuffer *draw_framebuffer;
+
GE( ctx, glClearColor (red, green, blue, alpha) );
gl_buffers |= GL_COLOR_BUFFER_BIT;
+
+ draw_framebuffer = cogl_get_draw_framebuffer ();
+ if (ctx->current_gl_color_mask != draw_framebuffer->color_mask)
+ {
+ CoglColorMask color_mask = draw_framebuffer->color_mask;
+ GE( ctx, glColorMask (color_mask & COGL_COLOR_MASK_RED,
+ color_mask & COGL_COLOR_MASK_GREEN,
+ color_mask & COGL_COLOR_MASK_BLUE,
+ color_mask & COGL_COLOR_MASK_ALPHA));
+ ctx->current_gl_color_mask = color_mask;
+ /* Make sure the ColorMask is updated when the next primitive is drawn */
+ ctx->current_pipeline_changes_since_flush |=
+ COGL_PIPELINE_STATE_LOGIC_OPS;
+ }
}
if (buffers & COGL_BUFFER_BIT_DEPTH)
@@ -1492,6 +1510,26 @@ cogl_framebuffer_get_alpha_bits (CoglFramebuffer *framebuffer)
return framebuffer->alpha_bits;
}
+CoglColorMask
+cogl_framebuffer_get_color_mask (CoglFramebuffer *framebuffer)
+{
+ return framebuffer->color_mask;
+}
+
+void
+cogl_framebuffer_set_color_mask (CoglFramebuffer *framebuffer,
+ CoglColorMask color_mask)
+{
+ _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+ cogl_flush (); /* XXX: Currently color mask changes don't go through the journal */
+ framebuffer->color_mask = color_mask;
+
+ /* Make sure the ColorMask is updated when the next primitive is drawn */
+ ctx->current_pipeline_changes_since_flush |=
+ COGL_PIPELINE_STATE_LOGIC_OPS;
+}
+
gboolean
cogl_framebuffer_get_dither_enabled (CoglFramebuffer *framebuffer)
{
diff --git a/cogl/cogl-framebuffer.h b/cogl/cogl-framebuffer.h
index df8f8307..4462a601 100644
--- a/cogl/cogl-framebuffer.h
+++ b/cogl/cogl-framebuffer.h
@@ -227,6 +227,34 @@ void
cogl_framebuffer_set_dither_enabled (CoglFramebuffer *framebuffer,
gboolean dither_enabled);
+/**
+ * cogl_framebuffer_get_color_mask:
+ * @framebuffer: a pointer to a #CoglFramebuffer
+ *
+ * Gets the current #CoglColorMask of which channels would be written to the
+ * current framebuffer. Each bit set in the mask means that the
+ * corresponding color would be written.
+ *
+ * Returns: A #CoglColorMask
+ * Since: 1.8
+ * Stability: unstable
+ */
+CoglColorMask
+cogl_framebuffer_get_color_mask (CoglFramebuffer *framebuffer);
+
+/**
+ * cogl_framebuffer_set_color_mask:
+ * @framebuffer: a pointer to a #CoglFramebuffer
+ * @color_mask: A #CoglColorMask of which color channels to write to
+ * the current framebuffer.
+ *
+ * Defines a bit mask of which color channels should be written to the
+ * given @framebuffer. If a bit is set in @color_mask that means that
+ * color will be written.
+ */
+cogl_framebuffer_set_color_mask (CoglFramebuffer *framebuffer,
+ CoglColorMask color_mask);
+
#define cogl_framebuffer_swap_buffers cogl_framebuffer_swap_buffers_EXP
void
cogl_framebuffer_swap_buffers (CoglFramebuffer *framebuffer);
diff --git a/cogl/cogl-pipeline-opengl.c b/cogl/cogl-pipeline-opengl.c
index 1b15b557..80a7fdcf 100644
--- a/cogl/cogl-pipeline-opengl.c
+++ b/cogl/cogl-pipeline-opengl.c
@@ -607,6 +607,24 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state (
}
}
+ if (pipelines_difference & COGL_PIPELINE_STATE_LOGIC_OPS)
+ {
+ CoglPipeline *authority =
+ _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LOGIC_OPS);
+ CoglPipelineLogicOpsState *logic_ops_state = &authority->big_state->logic_ops_state;
+ CoglColorMask color_mask = logic_ops_state->color_mask;
+ CoglFramebuffer *draw_framebuffer = cogl_get_draw_framebuffer ();
+
+ if (draw_framebuffer)
+ color_mask &= draw_framebuffer->color_mask;
+
+ GE (ctx, glColorMask (color_mask & COGL_COLOR_MASK_RED,
+ color_mask & COGL_COLOR_MASK_GREEN,
+ color_mask & COGL_COLOR_MASK_BLUE,
+ color_mask & COGL_COLOR_MASK_ALPHA));
+ ctx->current_gl_color_mask = color_mask;
+ }
+
if (pipeline->real_blend_enable != ctx->gl_blend_enable_cache)
{
if (pipeline->real_blend_enable)
diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
index 35d05e7d..41f73ab8 100644
--- a/cogl/cogl-pipeline-private.h
+++ b/cogl/cogl-pipeline-private.h
@@ -428,6 +428,7 @@ typedef enum
COGL_PIPELINE_STATE_DEPTH_INDEX,
COGL_PIPELINE_STATE_FOG_INDEX,
COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
+ COGL_PIPELINE_STATE_LOGIC_OPS_INDEX,
/* non-sparse */
COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX,
@@ -471,6 +472,8 @@ typedef enum _CoglPipelineState
1L<<COGL_PIPELINE_STATE_FOG_INDEX,
COGL_PIPELINE_STATE_POINT_SIZE =
1L<<COGL_PIPELINE_STATE_POINT_SIZE_INDEX,
+ COGL_PIPELINE_STATE_LOGIC_OPS =
+ 1L<<COGL_PIPELINE_STATE_LOGIC_OPS_INDEX,
COGL_PIPELINE_STATE_REAL_BLEND_ENABLE =
1L<<COGL_PIPELINE_STATE_REAL_BLEND_ENABLE_INDEX,
@@ -504,14 +507,16 @@ typedef enum _CoglPipelineState
COGL_PIPELINE_STATE_USER_SHADER | \
COGL_PIPELINE_STATE_DEPTH | \
COGL_PIPELINE_STATE_FOG | \
- COGL_PIPELINE_STATE_POINT_SIZE)
+ COGL_PIPELINE_STATE_POINT_SIZE | \
+ COGL_PIPELINE_STATE_LOGIC_OPS)
#define COGL_PIPELINE_STATE_MULTI_PROPERTY \
(COGL_PIPELINE_STATE_LAYERS | \
COGL_PIPELINE_STATE_LIGHTING | \
COGL_PIPELINE_STATE_BLEND | \
COGL_PIPELINE_STATE_DEPTH | \
- COGL_PIPELINE_STATE_FOG)
+ COGL_PIPELINE_STATE_FOG | \
+ COGL_PIPELINE_STATE_LOGIC_OPS)
#define COGL_PIPELINE_STATE_AFFECTS_VERTEX_CODEGEN \
(COGL_PIPELINE_STATE_LAYERS | \
@@ -578,6 +583,11 @@ typedef struct
typedef struct
{
+ CoglColorMask color_mask;
+} CoglPipelineLogicOpsState;
+
+typedef struct
+{
CoglPipelineLightingState lighting_state;
CoglPipelineAlphaFuncState alpha_state;
CoglPipelineBlendState blend_state;
@@ -585,6 +595,7 @@ typedef struct
CoglDepthState depth_state;
CoglPipelineFogState fog_state;
float point_size;
+ CoglPipelineLogicOpsState logic_ops_state;
} CoglPipelineBigState;
typedef enum
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index 4d70a6f9..8b87a2ea 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -196,6 +196,7 @@ _cogl_pipeline_init_default_pipeline (void)
CoglPipelineAlphaFuncState *alpha_state = &big_state->alpha_state;
CoglPipelineBlendState *blend_state = &big_state->blend_state;
CoglDepthState *depth_state = &big_state->depth_state;
+ CoglPipelineLogicOpsState *logic_ops_state = &big_state->logic_ops_state;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
@@ -301,6 +302,8 @@ _cogl_pipeline_init_default_pipeline (void)
big_state->point_size = 1.0f;
+ logic_ops_state->color_mask = COGL_COLOR_MASK_ALL;
+
ctx->default_pipeline = _cogl_pipeline_object_new (pipeline);
}
@@ -1067,6 +1070,13 @@ _cogl_pipeline_copy_differences (CoglPipeline *dest,
if (differences & COGL_PIPELINE_STATE_POINT_SIZE)
big_state->point_size = src->big_state->point_size;
+ if (differences & COGL_PIPELINE_STATE_LOGIC_OPS)
+ {
+ memcpy (&big_state->logic_ops_state,
+ &src->big_state->logic_ops_state,
+ sizeof (CoglPipelineLogicOpsState));
+ }
+
/* XXX: we shouldn't bother doing this in most cases since
* _copy_differences is typically used to initialize pipeline state
* by copying it from the current authority, so it's not actually
@@ -1137,6 +1147,13 @@ _cogl_pipeline_init_multi_property_sparse_state (CoglPipeline *pipeline,
sizeof (CoglPipelineFogState));
break;
}
+ case COGL_PIPELINE_STATE_LOGIC_OPS:
+ {
+ memcpy (&pipeline->big_state->logic_ops_state,
+ &authority->big_state->logic_ops_state,
+ sizeof (CoglPipelineLogicOpsState));
+ break;
+ }
}
}
@@ -3481,6 +3498,16 @@ _cogl_pipeline_point_size_equal (CoglPipeline *authority0,
}
static gboolean
+_cogl_pipeline_logic_ops_state_equal (CoglPipeline *authority0,
+ CoglPipeline *authority1)
+{
+ CoglPipelineLogicOpsState *logic_ops_state0 = &authority0->big_state->logic_ops_state;
+ CoglPipelineLogicOpsState *logic_ops_state1 = &authority1->big_state->logic_ops_state;
+
+ return logic_ops_state0->color_mask == logic_ops_state1->color_mask;
+}
+
+static gboolean
_cogl_pipeline_user_shader_equal (CoglPipeline *authority0,
CoglPipeline *authority1)
{
@@ -3796,6 +3823,12 @@ _cogl_pipeline_equal (CoglPipeline *pipeline0,
if (!simple_property_equal (authorities0, authorities1,
pipelines_difference,
+ COGL_PIPELINE_STATE_LOGIC_OPS_INDEX,
+ _cogl_pipeline_logic_ops_state_equal))
+ goto done;
+
+ if (!simple_property_equal (authorities0, authorities1,
+ pipelines_difference,
COGL_PIPELINE_STATE_USER_SHADER_INDEX,
_cogl_pipeline_user_shader_equal))
goto done;
@@ -4745,6 +4778,49 @@ cogl_pipeline_get_depth_state (CoglPipeline *pipeline,
*state = authority->big_state->depth_state;
}
+CoglColorMask
+cogl_pipeline_get_color_mask (CoglPipeline *pipeline)
+{
+ CoglPipeline *authority;
+
+ g_return_val_if_fail (cogl_is_pipeline (pipeline), 0);
+
+ authority =
+ _cogl_pipeline_get_authority (pipeline, COGL_PIPELINE_STATE_LOGIC_OPS);
+
+ return authority->big_state->logic_ops_state.color_mask;
+}
+
+void
+cogl_pipeline_set_color_mask (CoglPipeline *pipeline,
+ CoglColorMask color_mask)
+{
+ CoglPipelineState state = COGL_PIPELINE_STATE_LOGIC_OPS;
+ CoglPipeline *authority;
+ CoglPipelineLogicOpsState *logic_ops_state;
+
+ g_return_if_fail (cogl_is_pipeline (pipeline));
+
+ authority = _cogl_pipeline_get_authority (pipeline, state);
+
+ logic_ops_state = &authority->big_state->logic_ops_state;
+ if (logic_ops_state->color_mask == color_mask)
+ return;
+
+ /* - Flush journal primitives referencing the current state.
+ * - Make sure the pipeline has no dependants so it may be modified.
+ * - If the pipeline isn't currently an authority for the state being
+ * changed, then initialize that state from the current authority.
+ */
+ _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
+
+ logic_ops_state = &pipeline->big_state->logic_ops_state;
+ logic_ops_state->color_mask = color_mask;
+
+ _cogl_pipeline_update_authority (pipeline, authority, state,
+ _cogl_pipeline_logic_ops_state_equal);
+}
+
static void
_cogl_pipeline_set_fog_state (CoglPipeline *pipeline,
const CoglPipelineFogState *fog_state)
@@ -6193,6 +6269,15 @@ _cogl_pipeline_hash_point_size_state (CoglPipeline *authority,
sizeof (point_size));
}
+static void
+_cogl_pipeline_hash_logic_ops_state (CoglPipeline *authority,
+ HashState *state)
+{
+ CoglPipelineLogicOpsState *logic_ops_state = &authority->big_state->logic_ops_state;
+ state->hash = _cogl_util_one_at_a_time_hash (state->hash, &logic_ops_state->color_mask,
+ sizeof (CoglColorMask));
+}
+
typedef void (*StateHashFunction) (CoglPipeline *authority, HashState *state);
static StateHashFunction
@@ -6226,9 +6311,11 @@ _cogl_pipeline_init_state_hash_functions (void)
_cogl_pipeline_hash_fog_state;
state_hash_functions[COGL_PIPELINE_STATE_POINT_SIZE_INDEX] =
_cogl_pipeline_hash_point_size_state;
+ state_hash_functions[COGL_PIPELINE_STATE_LOGIC_OPS_INDEX] =
+ _cogl_pipeline_hash_logic_ops_state;
/* So we get a big error if we forget to update this code! */
- g_assert (COGL_PIPELINE_STATE_SPARSE_COUNT == 11);
+ g_assert (COGL_PIPELINE_STATE_SPARSE_COUNT == 12);
}
unsigned int
diff --git a/cogl/cogl-pipeline.h b/cogl/cogl-pipeline.h
index 28d756a8..9e68e839 100644
--- a/cogl/cogl-pipeline.h
+++ b/cogl/cogl-pipeline.h
@@ -633,6 +633,40 @@ cogl_pipeline_set_point_size (CoglHandle pipeline,
float
cogl_pipeline_get_point_size (CoglHandle pipeline);
+#define cogl_pipeline_get_color_mask cogl_pipeline_get_color_mask_EXP
+/**
+ * cogl_pipeline_get_color_mask:
+ * @pipeline: a #CoglPipeline object.
+ *
+ * Gets the current #CoglColorMask of which channels would be written to the
+ * current framebuffer. Each bit set in the mask means that the
+ * corresponding color would be written.
+ *
+ * Returns: A #CoglColorMask
+ * Since: 1.8
+ * Stability: unstable
+ */
+CoglColorMask
+cogl_pipeline_get_color_mask (CoglPipeline *pipeline);
+
+#define cogl_pipeline_set_color_mask cogl_pipeline_set_color_mask_EXP
+/**
+ * cogl_pipeline_set_color_mask:
+ * @pipeline: a #CoglPipeline object.
+ * @color_mask: A #CoglColorMask of which color channels to write to
+ * the current framebuffer.
+ *
+ * Defines a bit mask of which color channels should be written to the
+ * current framebuffer. If a bit is set in @color_mask that means that
+ * color will be written.
+ *
+ * Since: 1.8
+ * Stability: unstable
+ */
+void
+cogl_pipeline_set_color_mask (CoglPipeline *pipeline,
+ CoglColorMask color_mask);
+
/**
* cogl_pipeline_get_user_program:
* @pipeline: a #CoglPipeline object.
diff --git a/cogl/cogl-types.h b/cogl/cogl-types.h
index 55f22969..0d17b932 100644
--- a/cogl/cogl-types.h
+++ b/cogl/cogl-types.h
@@ -671,6 +671,32 @@ typedef enum _CoglWinsysFeature
COGL_WINSYS_FEATURE_N_FEATURES
} CoglWinsysFeature;
+/**
+ * CoglColorMask:
+ * @COGL_COLOR_MASK_NONE: None of the color channels are masked
+ * @COGL_COLOR_MASK_RED: Masks the red color channel
+ * @COGL_COLOR_MASK_GREEN: Masks the green color channel
+ * @COGL_COLOR_MASK_BLUE: Masks the blue color channel
+ * @COGL_COLOR_MASK_ALPHA: Masks the alpha color channel
+ * @COGL_COLOR_MASK_ALL: All of the color channels are masked
+ *
+ * Defines a bit mask of color channels. This can be used with
+ * cogl_pipeline_set_color_mask() for example to define which color
+ * channels should be written to the current framebuffer when
+ * drawing something.
+ */
+typedef enum
+{
+ COGL_COLOR_MASK_NONE = 0,
+ COGL_COLOR_MASK_RED = 1L<<0,
+ COGL_COLOR_MASK_GREEN = 1L<<1,
+ COGL_COLOR_MASK_BLUE = 1L<<2,
+ COGL_COLOR_MASK_ALPHA = 1L<<3,
+ /* XXX: glib-mkenums is a perl script that can't cope if we split
+ * this onto multiple lines! *sigh* */
+ COGL_COLOR_MASK_ALL = (COGL_COLOR_MASK_RED | COGL_COLOR_MASK_GREEN | COGL_COLOR_MASK_BLUE | COGL_COLOR_MASK_ALPHA)
+} CoglColorMask;
+
G_END_DECLS
#endif /* __COGL_TYPES_H__ */