summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Roberts <neil@linux.intel.com>2011-12-06 12:37:13 +0000
committerNeil Roberts <neil@linux.intel.com>2011-12-07 18:59:11 +0000
commit0717f0f96c46da03bac9da024e89f2cd1d9237fc (patch)
tree6516b48b253297e8ec08bdfaeffdbc38d0451495
parent09520a7d61a86e59aec7ea901724b089d4777ae1 (diff)
downloadcogl-wip/onscreen-flip.tar.gz
Allow the winsys backend to force rendering onscreen buffers flippedwip/onscreen-flip
This adds the option for a winsys to report which kinds of buffers need a flipped rendering. This will be used by the KMS backend because that also needs flipped rendering for onscreen buffers. There is a virtual winsys function to report a bitmask of types of buffers that need to be flipped. The default implementation just reports offscreen buffers. None of the winsyss actually implement it yet. When the backend flips for both types of framebuffer or neither type of framebuffer the vertend now hardcodes the vector for the flip instead of adding the uniform.
-rw-r--r--cogl/cogl-clip-stack.c2
-rw-r--r--cogl/cogl-context-private.h5
-rw-r--r--cogl/cogl-context.c2
-rw-r--r--cogl/cogl-framebuffer-private.h3
-rw-r--r--cogl/cogl-framebuffer.c19
-rw-r--r--cogl/cogl-matrix-stack.c3
-rw-r--r--cogl/cogl-pipeline-opengl.c2
-rw-r--r--cogl/cogl-pipeline-progend-glsl.c13
-rw-r--r--cogl/cogl-pipeline-vertend-glsl.c20
-rw-r--r--cogl/cogl-renderer-private.h3
-rw-r--r--cogl/cogl-renderer.c12
-rw-r--r--cogl/cogl.c6
-rw-r--r--cogl/winsys/cogl-winsys-egl.c11
-rw-r--r--cogl/winsys/cogl-winsys-glx.c11
-rw-r--r--cogl/winsys/cogl-winsys-private.h15
15 files changed, 101 insertions, 26 deletions
diff --git a/cogl/cogl-clip-stack.c b/cogl/cogl-clip-stack.c
index 5cc49817..0aeb1adf 100644
--- a/cogl/cogl-clip-stack.c
+++ b/cogl/cogl-clip-stack.c
@@ -861,7 +861,7 @@ _cogl_clip_stack_flush (CoglClipStack *stack,
* down so in this case no conversion is needed.
*/
- if (cogl_is_offscreen (framebuffer))
+ if (_cogl_framebuffer_is_flipped (framebuffer))
scissor_y_start = scissor_y0;
else
{
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index b67c7e78..a72cc996 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -277,6 +277,11 @@ struct _CoglContext
GHashTable *uniform_name_hash;
int n_uniform_names;
+ /* Cache of the result of _cogl_renderer_get_framebuffer_orientation().
+ This will be used every time a matrix is flushed so it's probably
+ worthwhile caching it */
+ CoglRendererFramebufferOrientation framebuffer_orientation;
+
/* This defines a list of function pointers that Cogl uses from
either GL or GLES. All functions are accessed indirectly through
these pointers rather than linking to them directly */
diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 21c10b78..06ddce7e 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -375,6 +375,8 @@ cogl_context_new (CoglDisplay *display,
_context->current_projection_stack = NULL;
_cogl_matrix_stack_init_cache (&_context->builtin_flushed_projection);
_cogl_matrix_stack_init_cache (&_context->builtin_flushed_modelview);
+ _context->framebuffer_orientation =
+ _cogl_renderer_get_framebuffer_orientation (display->renderer);
/* Create default textures used for fall backs */
context->default_gl_texture_2d_tex =
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index fce41e67..bdf9e452 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -363,4 +363,7 @@ _cogl_framebuffer_save_clip_stack (CoglFramebuffer *framebuffer);
void
_cogl_framebuffer_restore_clip_stack (CoglFramebuffer *framebuffer);
+gboolean
+_cogl_framebuffer_is_flipped (CoglFramebuffer *framebuffer);
+
#endif /* __COGL_FRAMEBUFFER_PRIVATE_H */
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index 829b5c2a..7a5e432b 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -1489,7 +1489,7 @@ _cogl_framebuffer_flush_viewport_state (CoglFramebuffer *framebuffer)
* left, while Cogl defines them to be top left.
* NB: We render upside down to offscreen framebuffers so we don't
* need to convert the y offset in this case. */
- if (cogl_is_offscreen (framebuffer))
+ if (_cogl_framebuffer_is_flipped (framebuffer))
gl_viewport_y = framebuffer->viewport_y;
else
gl_viewport_y = framebuffer->height -
@@ -2407,3 +2407,20 @@ _cogl_framebuffer_restore_clip_stack (CoglFramebuffer *framebuffer)
framebuffer->context->current_draw_buffer_changes |=
COGL_FRAMEBUFFER_STATE_CLIP;
}
+
+gboolean
+_cogl_framebuffer_is_flipped (CoglFramebuffer *framebuffer)
+{
+ CoglRendererFramebufferOrientation orientation =
+ framebuffer->context->framebuffer_orientation;
+
+ switch (framebuffer->type)
+ {
+ case COGL_FRAMEBUFFER_TYPE_ONSCREEN:
+ return !!(orientation & COGL_RENDERER_FLIP_ONSCREEN);
+ case COGL_FRAMEBUFFER_TYPE_OFFSCREEN:
+ return !!(orientation & COGL_RENDERER_FLIP_OFFSCREEN);
+ }
+
+ g_assert_not_reached ();
+}
diff --git a/cogl/cogl-matrix-stack.c b/cogl/cogl-matrix-stack.c
index c97d3b90..35ae064b 100644
--- a/cogl/cogl-matrix-stack.c
+++ b/cogl/cogl-matrix-stack.c
@@ -430,7 +430,8 @@ _cogl_matrix_stack_flush_to_gl_builtins (CoglContext *ctx,
if (disable_flip)
needs_flip = FALSE;
else
- needs_flip = cogl_is_offscreen (cogl_get_draw_framebuffer ());
+ needs_flip =
+ _cogl_framebuffer_is_flipped (cogl_get_draw_framebuffer ());
cache = &ctx->builtin_flushed_projection;
}
diff --git a/cogl/cogl-pipeline-opengl.c b/cogl/cogl-pipeline-opengl.c
index aaf5ea8c..4e5950f3 100644
--- a/cogl/cogl-pipeline-opengl.c
+++ b/cogl/cogl-pipeline-opengl.c
@@ -643,7 +643,7 @@ _cogl_pipeline_flush_color_blend_alpha_depth_state (
/* If we are painting to an offscreen framebuffer then we
need to invert the winding of the front face because
everything is painted upside down */
- invert_winding = cogl_is_offscreen (draw_framebuffer);
+ invert_winding = _cogl_framebuffer_is_flipped (draw_framebuffer);
switch (cull_face_state->front_winding)
{
diff --git a/cogl/cogl-pipeline-progend-glsl.c b/cogl/cogl-pipeline-progend-glsl.c
index 561ea3ee..e3172ac2 100644
--- a/cogl/cogl-pipeline-progend-glsl.c
+++ b/cogl/cogl-pipeline-progend-glsl.c
@@ -142,6 +142,7 @@ typedef struct
the framebuffer requires it only when there are vertex
snippets. Otherwise this is acheived using the projection
matrix */
+ gboolean has_vertex_snippets;
GLint flip_uniform;
int flushed_flip_state;
@@ -797,6 +798,8 @@ _cogl_pipeline_progend_glsl_end (CoglPipeline *pipeline,
GE_RET (program_state->flip_uniform,
ctx, glGetUniformLocation (gl_program, "_cogl_flip_vector"));
program_state->flushed_flip_state = -1;
+ program_state->has_vertex_snippets =
+ _cogl_pipeline_has_vertex_snippets (pipeline);
}
state.unit = 0;
@@ -951,7 +954,7 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline)
if (modelview_stack == NULL || projection_stack == NULL)
return;
- needs_flip = cogl_is_offscreen (cogl_get_draw_framebuffer ());
+ needs_flip = _cogl_framebuffer_is_flipped (cogl_get_draw_framebuffer ());
#ifdef HAVE_COGL_GLES2
if (ctx->driver == COGL_DRIVER_GLES2)
@@ -967,8 +970,8 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline)
&program_state->
projection_cache,
needs_flip &&
- program_state->
- flip_uniform == -1);
+ !program_state->
+ has_vertex_snippets);
modelview_changed =
_cogl_matrix_stack_check_and_update_cache (modelview_stack,
@@ -993,7 +996,7 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline)
_cogl_matrix_stack_get (modelview_stack, &modelview);
if (need_projection)
{
- if (needs_flip && program_state->flip_uniform == -1)
+ if (needs_flip && !program_state->has_vertex_snippets)
{
CoglMatrix tmp_matrix;
_cogl_matrix_stack_get (projection_stack, &tmp_matrix);
@@ -1053,7 +1056,7 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline)
/* If there are vertex snippets, then we'll disable flipping the
geometry via the matrix and use the flip vertex instead */
- disable_flip = program_state->flip_uniform != -1;
+ disable_flip = program_state->has_vertex_snippets;
_cogl_matrix_stack_flush_to_gl_builtins (ctx,
projection_stack,
diff --git a/cogl/cogl-pipeline-vertend-glsl.c b/cogl/cogl-pipeline-vertend-glsl.c
index 602cf02c..c1167283 100644
--- a/cogl/cogl-pipeline-vertend-glsl.c
+++ b/cogl/cogl-pipeline-vertend-glsl.c
@@ -469,10 +469,22 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
uniform */
if (_cogl_pipeline_has_vertex_snippets (pipeline))
{
- g_string_append (shader_state->header,
- "uniform vec4 _cogl_flip_vector;\n");
- g_string_append (shader_state->source,
- " cogl_position_out *= _cogl_flip_vector;\n");
+ /* If the backend always needs flipping then we might as
+ well hardcode the flip instead of using a uniform */
+ if (ctx->framebuffer_orientation ==
+ (COGL_RENDERER_FLIP_ONSCREEN | COGL_RENDERER_FLIP_OFFSCREEN))
+ {
+ g_string_append (shader_state->source,
+ " cogl_position_out *= "
+ "vec4 (1.0, -1.0, 1.0, 1.0);\n");
+ }
+ else if (ctx->framebuffer_orientation != 0)
+ {
+ g_string_append (shader_state->header,
+ "uniform vec4 _cogl_flip_vector;\n");
+ g_string_append (shader_state->source,
+ " cogl_position_out *= _cogl_flip_vector;\n");
+ }
}
g_string_append (shader_state->source,
diff --git a/cogl/cogl-renderer-private.h b/cogl/cogl-renderer-private.h
index 2f7aaf10..83a93145 100644
--- a/cogl/cogl-renderer-private.h
+++ b/cogl/cogl-renderer-private.h
@@ -84,4 +84,7 @@ void *
_cogl_renderer_get_proc_address (CoglRenderer *renderer,
const char *name);
+CoglRendererFramebufferOrientation
+_cogl_renderer_get_framebuffer_orientation (CoglRenderer *renderer);
+
#endif /* __COGL_RENDERER_PRIVATE_H */
diff --git a/cogl/cogl-renderer.c b/cogl/cogl-renderer.c
index 2e272092..70af0c11 100644
--- a/cogl/cogl-renderer.c
+++ b/cogl/cogl-renderer.c
@@ -403,6 +403,18 @@ _cogl_renderer_get_proc_address (CoglRenderer *renderer,
return winsys->renderer_get_proc_address (renderer, name);
}
+CoglRendererFramebufferOrientation
+_cogl_renderer_get_framebuffer_orientation (CoglRenderer *renderer)
+{
+ const CoglWinsysVtable *winsys = _cogl_renderer_get_winsys (renderer);
+
+ if (winsys->renderer_get_framebuffer_orientation)
+ return winsys->renderer_get_framebuffer_orientation (renderer);
+ else
+ /* Most backends just need to flip the offscreen buffers */
+ return COGL_RENDERER_FLIP_OFFSCREEN;
+}
+
int
cogl_renderer_get_n_fragment_texture_units (CoglRenderer *renderer)
{
diff --git a/cogl/cogl.c b/cogl/cogl.c
index cba3de7a..f1d24565 100644
--- a/cogl/cogl.c
+++ b/cogl/cogl.c
@@ -431,7 +431,7 @@ _cogl_read_pixels_with_rowstride (int x,
* NB: all offscreen rendering is done upside down so no conversion
* is necissary in this case.
*/
- if (!cogl_is_offscreen (framebuffer))
+ if (!_cogl_framebuffer_is_flipped (framebuffer))
y = framebuffer_height - y - height;
/* Initialise the CoglBitmap */
@@ -462,7 +462,7 @@ _cogl_read_pixels_with_rowstride (int x,
/* NB: All offscreen rendering is done upside down so there is no need
* to flip in this case... */
if ((ctx->private_feature_flags & COGL_PRIVATE_FEATURE_MESA_PACK_INVERT) &&
- !cogl_is_offscreen (framebuffer))
+ !_cogl_framebuffer_is_flipped (framebuffer))
{
GE (ctx, glPixelStorei (GL_PACK_INVERT_MESA, TRUE));
pack_invert_set = TRUE;
@@ -541,7 +541,7 @@ _cogl_read_pixels_with_rowstride (int x,
/* NB: All offscreen rendering is done upside down so there is no need
* to flip in this case... */
- if (!cogl_is_offscreen (framebuffer) && !pack_invert_set)
+ if (!_cogl_framebuffer_is_flipped (framebuffer) && !pack_invert_set)
{
guint8 *temprow = g_alloca (rowstride * sizeof (guint8));
diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c
index 7d0435fa..b21375a4 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -1535,11 +1535,12 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
* but we are given rectangles relative to the top left so we need to flip
* them... */
memcpy (rectangles, user_rectangles, sizeof (int) * n_rectangles * 4);
- for (i = 0; i < n_rectangles; i++)
- {
- int *rect = &rectangles[4 * i];
- rect[1] = framebuffer_height - rect[1] - rect[3];
- }
+ if (!_cogl_framebuffer_is_flipped (framebuffer))
+ for (i = 0; i < n_rectangles; i++)
+ {
+ int *rect = &rectangles[4 * i];
+ rect[1] = framebuffer_height - rect[1] - rect[3];
+ }
/* At least for eglSwapBuffers the EGL spec says that the surface to
swap must be bound to the current context. It looks like Mesa
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index 58640afc..4ed77421 100644
--- a/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/winsys/cogl-winsys-glx.c
@@ -1211,11 +1211,12 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
* we are given rectangles relative to the top left so we need to flip
* them... */
memcpy (rectangles, user_rectangles, sizeof (int) * n_rectangles * 4);
- for (i = 0; i < n_rectangles; i++)
- {
- int *rect = &rectangles[4 * i];
- rect[1] = framebuffer_height - rect[1] - rect[3];
- }
+ if (!_cogl_framebuffer_is_flipped (framebuffer))
+ for (i = 0; i < n_rectangles; i++)
+ {
+ int *rect = &rectangles[4 * i];
+ rect[1] = framebuffer_height - rect[1] - rect[3];
+ }
_cogl_framebuffer_flush_state (framebuffer,
framebuffer,
diff --git a/cogl/winsys/cogl-winsys-private.h b/cogl/winsys/cogl-winsys-private.h
index 16317b7b..4fb1cbab 100644
--- a/cogl/winsys/cogl-winsys-private.h
+++ b/cogl/winsys/cogl-winsys-private.h
@@ -54,6 +54,18 @@ typedef enum
COGL_WINSYS_RECTANGLE_STATE_ENABLE
} CoglWinsysRectangleState;
+/* Flags to specify which types of buffers need to be rendered to
+ upside-down for this particularly renderer. Currently all offscreen
+ buffers need to be rendered upside down in Cogl because the texture
+ coordinate 0,0 is expected to be the topleft whereas in GL it is
+ the bottom-left. Additionally, some backends may require rendering
+ upside-down to onscreen buffers as well */
+typedef enum
+{
+ COGL_RENDERER_FLIP_ONSCREEN = (1 << 0),
+ COGL_RENDERER_FLIP_OFFSCREEN = (1 << 1),
+} CoglRendererFramebufferOrientation;
+
typedef struct _CoglWinsysVtable
{
CoglWinsysID id;
@@ -110,6 +122,9 @@ typedef struct _CoglWinsysVtable
const int *rectangles,
int n_rectangles);
+ CoglRendererFramebufferOrientation
+ (*renderer_get_framebuffer_orientation) (CoglRenderer *renderer);
+
#ifdef COGL_HAS_EGL_SUPPORT
EGLDisplay
(*context_egl_get_egl_display) (CoglContext *context);