diff options
-rw-r--r-- | cogl/cogl-clip-stack.c | 2 | ||||
-rw-r--r-- | cogl/cogl-context-private.h | 5 | ||||
-rw-r--r-- | cogl/cogl-context.c | 2 | ||||
-rw-r--r-- | cogl/cogl-framebuffer-private.h | 3 | ||||
-rw-r--r-- | cogl/cogl-framebuffer.c | 19 | ||||
-rw-r--r-- | cogl/cogl-matrix-stack.c | 3 | ||||
-rw-r--r-- | cogl/cogl-pipeline-opengl.c | 2 | ||||
-rw-r--r-- | cogl/cogl-pipeline-progend-glsl.c | 13 | ||||
-rw-r--r-- | cogl/cogl-pipeline-vertend-glsl.c | 20 | ||||
-rw-r--r-- | cogl/cogl-renderer-private.h | 3 | ||||
-rw-r--r-- | cogl/cogl-renderer.c | 12 | ||||
-rw-r--r-- | cogl/cogl.c | 6 | ||||
-rw-r--r-- | cogl/winsys/cogl-winsys-egl.c | 11 | ||||
-rw-r--r-- | cogl/winsys/cogl-winsys-glx.c | 11 | ||||
-rw-r--r-- | cogl/winsys/cogl-winsys-private.h | 15 |
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); |