[cogl/wip/neil/snippets] Allow the winsys backend to force rendering onscreen buffers flipped
- From: Neil Roberts <nroberts src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/neil/snippets] Allow the winsys backend to force rendering onscreen buffers flipped
- Date: Tue, 6 Dec 2011 12:48:08 +0000 (UTC)
commit 617f65639af18da6b4d28bd68f4703b2c6e68280
Author: Neil Roberts <neil linux intel com>
Date: Tue Dec 6 12:37:13 2011 +0000
Allow the winsys backend to force rendering onscreen buffers flipped
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.
cogl/cogl-clip-stack.c | 2 +-
cogl/cogl-context-private.h | 5 +++++
cogl/cogl-context.c | 2 ++
cogl/cogl-framebuffer-private.h | 3 +++
cogl/cogl-framebuffer.c | 19 ++++++++++++++++++-
cogl/cogl-matrix-stack.c | 3 ++-
cogl/cogl-pipeline-opengl.c | 2 +-
cogl/cogl-pipeline-progend-glsl.c | 11 +++++++----
cogl/cogl-pipeline-vertend-glsl.c | 20 ++++++++++++++++----
cogl/cogl-renderer-private.h | 3 +++
cogl/cogl-renderer.c | 12 ++++++++++++
cogl/cogl.c | 6 +++---
cogl/winsys/cogl-winsys-egl.c | 11 ++++++-----
cogl/winsys/cogl-winsys-glx.c | 11 ++++++-----
cogl/winsys/cogl-winsys-private.h | 15 +++++++++++++++
15 files changed, 100 insertions(+), 25 deletions(-)
---
diff --git a/cogl/cogl-clip-stack.c b/cogl/cogl-clip-stack.c
index 5bcd29d..9c44407 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 53a7cef..8336639 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 8183982..37901cd 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 fce41e6..bdf9e45 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 f70657c..ddd2936 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 15bd45c..160b42d 100644
--- a/cogl/cogl-matrix-stack.c
+++ b/cogl/cogl-matrix-stack.c
@@ -450,7 +450,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 aaf5ea8..4e5950f 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 17da03c..9397e80 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;
@@ -984,7 +987,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)
@@ -999,7 +1002,7 @@ _cogl_pipeline_progend_glsl_pre_paint (CoglPipeline *pipeline)
check_and_update_matrix_cache (projection_stack,
&program_state->projection_cache,
needs_flip &&
- program_state->flip_uniform == -1);
+ !program_state->has_vertex_snippets);
modelview_changed =
check_and_update_matrix_cache (modelview_stack,
@@ -1022,7 +1025,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);
@@ -1082,7 +1085,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 602cf02..c116728 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 45222ef..1a354d8 100644
--- a/cogl/cogl-renderer-private.h
+++ b/cogl/cogl-renderer-private.h
@@ -83,4 +83,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 a691bda..8557846 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 cba3de7..f1d2456 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 15d0d7a..676c3c6 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -1532,11 +1532,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];
+ }
if (egl_renderer->pf_eglSwapBuffersRegion (egl_renderer->edpy,
egl_onscreen->egl_surface,
diff --git a/cogl/winsys/cogl-winsys-glx.c b/cogl/winsys/cogl-winsys-glx.c
index 58640af..4ed7742 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 16317b7..4fb1cba 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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]