summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);