summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen W. Taylor <otaylor@fishsoup.net>2014-04-28 12:37:32 -0400
committerOwen W. Taylor <otaylor@fishsoup.net>2014-07-17 19:13:33 -0400
commitb5b8ab91c035e096bcd41284e7b84cbe56b4a29f (patch)
tree8210ddf89e55b0567ab4c77977a521e977b65598
parent728362c77b0ff804c196790dd93da84da2555b75 (diff)
downloadcogl-b5b8ab91c035e096bcd41284e7b84cbe56b4a29f.tar.gz
Add support for setting up stereo CoglOnscreens
If we want to show quad-buffer stereo with Cogl, we need to pick an appropriate fbconfig for creating the CoglOnscreen objects. Add cogl_onscreen_template_set_stereo_enabled() to indicate whether stereo support is needed. Add cogl_framebuffer_get_stereo_mode() to see if a framebuffer was created with stereo support. Add cogl_framebuffer_get_stereo_mode() to pick whether to draw to the left, right, or both buffers. Reviewed-by: Robert Bragg <robert.bragg@intel.com>
-rw-r--r--cogl/cogl-context-private.h1
-rw-r--r--cogl/cogl-framebuffer-private.h8
-rw-r--r--cogl/cogl-framebuffer.c41
-rw-r--r--cogl/cogl-framebuffer.h52
-rw-r--r--cogl/cogl-onscreen-template.c8
-rw-r--r--cogl/cogl-onscreen-template.h19
-rw-r--r--cogl/cogl-types.h15
-rw-r--r--cogl/driver/gl/cogl-framebuffer-gl.c36
-rw-r--r--cogl/winsys/cogl-winsys-glx-feature-functions.h1
-rw-r--r--cogl/winsys/cogl-winsys-glx.c8
10 files changed, 186 insertions, 3 deletions
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index 32f2aa29..58db878b 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -237,6 +237,7 @@ struct _CoglContext
CoglBool current_gl_dither_enabled;
CoglColorMask current_gl_color_mask;
+ GLenum current_gl_draw_buffer;
/* Clipping */
/* TRUE if we have a valid clipping stack flushed. In that case
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index ca1fbea1..f37492af 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -61,6 +61,7 @@ typedef struct
int samples_per_pixel;
CoglBool swap_throttled;
CoglBool depth_texture_enabled;
+ CoglBool stereo_enabled;
} CoglFramebufferConfig;
/* Flags to pass to _cogl_offscreen_new_with_texture_full */
@@ -86,7 +87,8 @@ typedef enum _CoglFramebufferStateIndex
COGL_FRAMEBUFFER_STATE_INDEX_COLOR_MASK = 6,
COGL_FRAMEBUFFER_STATE_INDEX_FRONT_FACE_WINDING = 7,
COGL_FRAMEBUFFER_STATE_INDEX_DEPTH_WRITE = 8,
- COGL_FRAMEBUFFER_STATE_INDEX_MAX = 9
+ COGL_FRAMEBUFFER_STATE_INDEX_STEREO_MODE = 9,
+ COGL_FRAMEBUFFER_STATE_INDEX_MAX = 10
} CoglFramebufferStateIndex;
typedef enum _CoglFramebufferState
@@ -99,7 +101,8 @@ typedef enum _CoglFramebufferState
COGL_FRAMEBUFFER_STATE_PROJECTION = 1<<5,
COGL_FRAMEBUFFER_STATE_COLOR_MASK = 1<<6,
COGL_FRAMEBUFFER_STATE_FRONT_FACE_WINDING = 1<<7,
- COGL_FRAMEBUFFER_STATE_DEPTH_WRITE = 1<<8
+ COGL_FRAMEBUFFER_STATE_DEPTH_WRITE = 1<<8,
+ COGL_FRAMEBUFFER_STATE_STEREO_MODE = 1<<9
} CoglFramebufferState;
#define COGL_FRAMEBUFFER_STATE_ALL ((1<<COGL_FRAMEBUFFER_STATE_INDEX_MAX) - 1)
@@ -154,6 +157,7 @@ struct _CoglFramebuffer
CoglBool dither_enabled;
CoglBool depth_writing_enabled;
CoglColorMask color_mask;
+ CoglStereoMode stereo_mode;
/* 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 90aaecdc..4cb397ae 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -854,6 +854,14 @@ _cogl_framebuffer_compare_depth_write_state (CoglFramebuffer *a,
COGL_FRAMEBUFFER_STATE_DEPTH_WRITE : 0;
}
+static unsigned long
+_cogl_framebuffer_compare_stereo_mode (CoglFramebuffer *a,
+ CoglFramebuffer *b)
+{
+ return a->stereo_mode != b->stereo_mode ?
+ COGL_FRAMEBUFFER_STATE_STEREO_MODE : 0;
+}
+
unsigned long
_cogl_framebuffer_compare (CoglFramebuffer *a,
CoglFramebuffer *b,
@@ -906,6 +914,10 @@ _cogl_framebuffer_compare (CoglFramebuffer *a,
differences |=
_cogl_framebuffer_compare_depth_write_state (a, b);
break;
+ case COGL_FRAMEBUFFER_STATE_INDEX_STEREO_MODE:
+ differences |=
+ _cogl_framebuffer_compare_stereo_mode (a, b);
+ break;
default:
g_warn_if_reached ();
}
@@ -993,6 +1005,12 @@ _cogl_framebuffer_get_stencil_bits (CoglFramebuffer *framebuffer)
return bits.stencil;
}
+gboolean
+cogl_framebuffer_get_is_stereo (CoglFramebuffer *framebuffer)
+{
+ return framebuffer->config.stereo_enabled;
+}
+
CoglColorMask
cogl_framebuffer_get_color_mask (CoglFramebuffer *framebuffer)
{
@@ -1016,6 +1034,29 @@ cogl_framebuffer_set_color_mask (CoglFramebuffer *framebuffer,
COGL_FRAMEBUFFER_STATE_COLOR_MASK;
}
+CoglStereoMode
+cogl_framebuffer_get_stereo_mode (CoglFramebuffer *framebuffer)
+{
+ return framebuffer->stereo_mode;
+}
+
+void
+cogl_framebuffer_set_stereo_mode (CoglFramebuffer *framebuffer,
+ CoglStereoMode stereo_mode)
+{
+ if (framebuffer->stereo_mode == stereo_mode)
+ return;
+
+ /* Stereo mode changes don't go through the journal */
+ _cogl_framebuffer_flush_journal (framebuffer);
+
+ framebuffer->stereo_mode = stereo_mode;
+
+ if (framebuffer->context->current_draw_buffer == framebuffer)
+ framebuffer->context->current_draw_buffer_changes |=
+ COGL_FRAMEBUFFER_STATE_STEREO_MODE;
+}
+
CoglBool
cogl_framebuffer_get_depth_write_enabled (CoglFramebuffer *framebuffer)
{
diff --git a/cogl/cogl-framebuffer.h b/cogl/cogl-framebuffer.h
index c9f17ecf..df2412df 100644
--- a/cogl/cogl-framebuffer.h
+++ b/cogl/cogl-framebuffer.h
@@ -717,6 +717,23 @@ cogl_framebuffer_get_alpha_bits (CoglFramebuffer *framebuffer);
int
cogl_framebuffer_get_depth_bits (CoglFramebuffer *framebuffer);
+/*
+ * cogl_framebuffer_get_is_stereo:
+ * @framebuffer: a pointer to a #CoglFramebuffer
+ *
+ * Retrieves whether @framebuffer has separate left and right
+ * buffers for use with stereo drawing. See
+ * cogl_framebuffer_set_stereo_mode().
+ *
+ * Return value: %TRUE if @framebuffer has separate left and
+ * right buffers.
+ *
+ * Since: 1.20
+ * Stability: unstable
+ */
+CoglBool
+cogl_framebuffer_get_is_stereo (CoglFramebuffer *framebuffer);
+
/**
* cogl_framebuffer_get_dither_enabled:
* @framebuffer: a pointer to a #CoglFramebuffer
@@ -842,6 +859,41 @@ CoglPixelFormat
cogl_framebuffer_get_color_format (CoglFramebuffer *framebuffer);
/**
+ * cogl_framebuffer_get_stereo_mode:
+ * @framebuffer: a pointer to a #CoglFramebuffer
+ *
+ * Gets the current #CoglStereoMode, which defines which stereo buffers
+ * should be drawn to. See cogl_framebuffer_set_stereo_mode().
+ *
+ * Returns: A #CoglStereoMode
+ * Since: 1.20
+ * Stability: unstable
+ */
+CoglStereoMode
+cogl_framebuffer_get_stereo_mode (CoglFramebuffer *framebuffer);
+
+/**
+ * cogl_framebuffer_set_stereo_mode:
+ * @framebuffer: a pointer to a #CoglFramebuffer
+ * @stereo_mode: A #CoglStereoMode specifying which stereo buffers
+ * should be drawn tow.
+ *
+ * Sets which stereo buffers should be drawn to. The default
+ * is %COGL_STEREO_BOTH, which means that both the left and
+ * right buffers will be affected by drawing. For this to have
+ * an effect, the display system must support stereo drawables,
+ * and the framebuffer must have been created with stereo
+ * enabled. (See cogl_onscreen_template_set_stereo_enabled(),
+ * cogl_framebuffer_get_is_stereo().)
+ *
+ * Since: 1.20
+ * Stability: unstable
+ */
+void
+cogl_framebuffer_set_stereo_mode (CoglFramebuffer *framebuffer,
+ CoglStereoMode stereo_mode);
+
+/**
* cogl_framebuffer_set_depth_texture_enabled:
* @framebuffer: A #CoglFramebuffer
* @enabled: TRUE or FALSE
diff --git a/cogl/cogl-onscreen-template.c b/cogl/cogl-onscreen-template.c
index 4f350e13..0083a2a0 100644
--- a/cogl/cogl-onscreen-template.c
+++ b/cogl/cogl-onscreen-template.c
@@ -94,3 +94,11 @@ cogl_onscreen_template_set_has_alpha (CoglOnscreenTemplate *onscreen_template,
{
onscreen_template->config.has_alpha = has_alpha;
}
+
+void
+cogl_onscreen_template_set_stereo_enabled (
+ CoglOnscreenTemplate *onscreen_template,
+ CoglBool enabled)
+{
+ onscreen_template->config.stereo_enabled = enabled;
+}
diff --git a/cogl/cogl-onscreen-template.h b/cogl/cogl-onscreen-template.h
index c10d3849..9aa66760 100644
--- a/cogl/cogl-onscreen-template.h
+++ b/cogl/cogl-onscreen-template.h
@@ -112,6 +112,25 @@ cogl_onscreen_template_set_has_alpha (CoglOnscreenTemplate *onscreen_template,
CoglBool has_alpha);
/**
+ * cogl_onscreen_template_set_stereo_enabled:
+ * @onscreen_template: A #CoglOnscreenTemplate template framebuffer
+ * @enabled: Whether framebuffers are created with stereo buffers
+ *
+ * Sets whether future #CoglOnscreen framebuffers derived from this
+ * template are attempted to be created with both left and right
+ * buffers, for use with stereo display. If the display system
+ * does not support stereo, then creation of the framebuffer will
+ * fail.
+ *
+ * Since: 1.20
+ * Stability: unstable
+ */
+void
+cogl_onscreen_template_set_stereo_enabled (
+ CoglOnscreenTemplate *onscreen_template,
+ CoglBool enabled);
+
+/**
* cogl_is_onscreen_template:
* @object: A #CoglObject pointer
*
diff --git a/cogl/cogl-types.h b/cogl/cogl-types.h
index 2126bdd8..f34339a9 100644
--- a/cogl/cogl-types.h
+++ b/cogl/cogl-types.h
@@ -715,6 +715,21 @@ typedef enum { /*< prefix=COGL_READ_PIXELS >*/
COGL_READ_PIXELS_COLOR_BUFFER = 1L << 0
} CoglReadPixelsFlags;
+/**
+ * CoglStereoMode:
+ * @COGL_STEREO_BOTH: draw to both stereo buffers
+ * @COGL_STEREO_LEFT: draw only to the left stereo buffer
+ * @COGL_STEREO_RIGHT: draw only to the left stereo buffer
+ *
+ * Represents how draw should affect the two buffers
+ * of a stereo framebuffer. See cogl_framebuffer_set_stereo_mode().
+ */
+typedef enum {
+ COGL_STEREO_BOTH,
+ COGL_STEREO_LEFT,
+ COGL_STEREO_RIGHT
+} CoglStereoMode;
+
COGL_END_DECLS
#endif /* __COGL_TYPES_H__ */
diff --git a/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/driver/gl/cogl-framebuffer-gl.c
index 5ef84867..b487a4ce 100644
--- a/cogl/driver/gl/cogl-framebuffer-gl.c
+++ b/cogl/driver/gl/cogl-framebuffer-gl.c
@@ -236,6 +236,39 @@ _cogl_framebuffer_gl_flush_front_face_winding_state (CoglFramebuffer *framebuffe
context->current_pipeline_age--;
}
+static void
+_cogl_framebuffer_gl_flush_stereo_mode_state (CoglFramebuffer *framebuffer)
+{
+ CoglContext *ctx = framebuffer->context;
+ GLenum draw_buffer = GL_BACK;
+
+ if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
+ return;
+
+ /* The one-shot default draw buffer setting in _cogl_framebuffer_gl_bind
+ * must have already happened. If not it would override what we set here. */
+ g_assert (ctx->was_bound_to_onscreen);
+
+ switch (framebuffer->stereo_mode)
+ {
+ case COGL_STEREO_BOTH:
+ draw_buffer = GL_BACK;
+ break;
+ case COGL_STEREO_LEFT:
+ draw_buffer = GL_BACK_LEFT;
+ break;
+ case COGL_STEREO_RIGHT:
+ draw_buffer = GL_BACK_RIGHT;
+ break;
+ }
+
+ if (ctx->current_gl_draw_buffer != draw_buffer)
+ {
+ GE (ctx, glDrawBuffer (draw_buffer));
+ ctx->current_gl_draw_buffer = draw_buffer;
+ }
+}
+
void
_cogl_framebuffer_gl_bind (CoglFramebuffer *framebuffer, GLenum target)
{
@@ -406,6 +439,9 @@ _cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer,
/* Nothing to do for depth write state change; the state will always
* be taken into account when flushing the pipeline's depth state. */
break;
+ case COGL_FRAMEBUFFER_STATE_INDEX_STEREO_MODE:
+ _cogl_framebuffer_gl_flush_stereo_mode_state (draw_buffer);
+ break;
default:
g_warn_if_reached ();
}
diff --git a/cogl/winsys/cogl-winsys-glx-feature-functions.h b/cogl/winsys/cogl-winsys-glx-feature-functions.h
index 37a06738..36ff02f5 100644
--- a/cogl/winsys/cogl-winsys-glx-feature-functions.h
+++ b/cogl/winsys/cogl-winsys-glx-feature-functions.h
@@ -176,6 +176,7 @@ COGL_WINSYS_FEATURE_BEGIN (255, 255,
"INTEL\0",
"swap_event\0",
COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT)
+
COGL_WINSYS_FEATURE_END ()
COGL_WINSYS_FEATURE_BEGIN (255, 255,
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index d59f3dc2..829e0f91 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -889,6 +889,11 @@ glx_attributes_from_framebuffer_config (CoglDisplay *display,
attributes[i++] = 1;
attributes[i++] = GLX_STENCIL_SIZE;
attributes[i++] = config->need_stencil ? 1: GLX_DONT_CARE;
+ if (config->stereo_enabled)
+ {
+ attributes[i++] = GLX_STEREO;
+ attributes[i++] = TRUE;
+ }
if (glx_renderer->glx_major == 1 && glx_renderer->glx_minor >= 4 &&
config->samples_per_pixel)
@@ -928,6 +933,7 @@ find_fbconfig (CoglDisplay *display,
xscreen_num,
attributes,
&n_configs);
+
if (!configs || n_configs == 0)
{
_cogl_set_error (error, COGL_WINSYS_ERROR,
@@ -1836,7 +1842,7 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
rect[0], rect[1], x2, y2,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
- context->glDrawBuffer (GL_BACK);
+ context->glDrawBuffer (context->current_gl_draw_buffer);
}
/* NB: unlike glXSwapBuffers, glXCopySubBuffer and