From 12af2751392ea53959fa41dd7cb19e07358655f2 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Wed, 21 Oct 2009 23:24:49 +0100 Subject: [PATCH] [cogl] Make sure Cogl always knows the current window geometry Because Cogl defines the origin of viewport and window coordinates to be top-left it always needs to know the size of the current window so that Cogl window/viewport coordinates can be transformed into OpenGL coordinates. This also fixes cogl_read_pixels to use the current draw buffer height instead of the viewport height to determine the OpenGL y coordinate to use for glReadPixels. --- clutter/clutter-backend.c | 19 ++++++++++++++- clutter/clutter-stage.c | 8 +++++++ clutter/cogl/cogl/cogl-context.c | 2 +- clutter/cogl/cogl/cogl-context.h | 2 +- clutter/cogl/cogl/cogl-draw-buffer.c | 36 ++++++++++++++++++++++++---- clutter/cogl/cogl/cogl.h.in | 3 +++ 6 files changed, 62 insertions(+), 8 deletions(-) diff --git a/clutter/clutter-backend.c b/clutter/clutter-backend.c index b0a7c279e..ca4fd3c26 100644 --- a/clutter/clutter-backend.c +++ b/clutter/clutter-backend.c @@ -47,6 +47,8 @@ #include "clutter-marshal.h" #include "clutter-private.h" +#include + G_DEFINE_ABSTRACT_TYPE (ClutterBackend, clutter_backend, G_TYPE_OBJECT); #define DEFAULT_FONT_NAME "Sans 10" @@ -355,7 +357,22 @@ _clutter_backend_ensure_context (ClutterBackend *backend, klass = CLUTTER_BACKEND_GET_CLASS (backend); if (G_LIKELY (klass->ensure_context)) klass->ensure_context (backend, new_stage); - + + /* XXX: Until Cogl becomes fully responsible for backend windows + * Clutter need to manually keep it informed of the current window size + * + * NB: This must be done after we ensure_context above because Cogl + * always assumes there is a current GL context. + */ + if (new_stage) + { + float width, height; + + clutter_actor_get_size (CLUTTER_ACTOR (stage), &width, &height); + + _cogl_onscreen_clutter_backend_set_size (width, height); + } + /* FIXME: With a NULL stage and thus no active context it may make more * sense to clean the context but then re call with the default stage * so at least there is some kind of context in place (as to avoid diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c index 9fe5cd347..be2941217 100644 --- a/clutter/clutter-stage.c +++ b/clutter/clutter-stage.c @@ -192,6 +192,10 @@ clutter_stage_allocate (ClutterActor *self, { ClutterActorClass *klass; + /* XXX: Until Cogl becomes fully responsible for backend windows Clutter + * need to manually keep it informed of the current window size */ + _cogl_onscreen_clutter_backend_set_size (width, height); + CLUTTER_NOTE (LAYOUT, "Following allocation to %dx%d (origin %s)", width, height, @@ -210,6 +214,10 @@ clutter_stage_allocate (ClutterActor *self, _clutter_stage_window_get_geometry (priv->impl, &geom); + /* XXX: Until Cogl becomes fully responsible for backend windows Clutter + * need to manually keep it informed of the current window size */ + _cogl_onscreen_clutter_backend_set_size (geom.width, geom.height); + override.x1 = 0; override.y1 = 0; override.x2 = geom.width; diff --git a/clutter/cogl/cogl/cogl-context.c b/clutter/cogl/cogl/cogl-context.c index ccd71c7d0..d50ec6cf9 100644 --- a/clutter/cogl/cogl/cogl-context.c +++ b/clutter/cogl/cogl/cogl-context.c @@ -102,7 +102,7 @@ cogl_create_context (void) _context->window_buffer = window_buffer; cogl_set_draw_buffer (COGL_WINDOW_BUFFER, 0/* ignored */); _context->dirty_bound_framebuffer = TRUE; - _context->dirty_viewport = TRUE; + _context->dirty_gl_viewport = TRUE; _context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode)); _context->last_path = 0; diff --git a/clutter/cogl/cogl/cogl-context.h b/clutter/cogl/cogl/cogl-context.h index 1d3f9ecf3..aa2045456 100644 --- a/clutter/cogl/cogl/cogl-context.h +++ b/clutter/cogl/cogl/cogl-context.h @@ -90,7 +90,7 @@ typedef struct GSList *draw_buffer_stack; CoglHandle window_buffer; gboolean dirty_bound_framebuffer; - gboolean dirty_viewport; + gboolean dirty_gl_viewport; /* Primitives */ floatVec2 path_start; diff --git a/clutter/cogl/cogl/cogl-draw-buffer.c b/clutter/cogl/cogl/cogl-draw-buffer.c index 41f0a5f91..76077627a 100644 --- a/clutter/cogl/cogl/cogl-draw-buffer.c +++ b/clutter/cogl/cogl/cogl-draw-buffer.c @@ -163,7 +163,7 @@ _cogl_draw_buffer_set_viewport (CoglHandle handle, draw_buffer->viewport_height = height; if (_cogl_get_draw_buffer () == draw_buffer) - ctx->dirty_viewport = TRUE; + ctx->dirty_gl_viewport = TRUE; } int @@ -377,6 +377,26 @@ _cogl_onscreen_free (CoglOnscreen *onscreen) g_free (onscreen); } +void +_cogl_onscreen_clutter_backend_set_size (int width, int height) +{ + CoglDrawBuffer *draw_buffer; + + _COGL_GET_CONTEXT (ctx, NO_RETVAL); + + draw_buffer = COGL_DRAW_BUFFER (ctx->window_buffer); + + if (draw_buffer->width == width && draw_buffer->height == height) + return; + + draw_buffer->width = width; + draw_buffer->height = height; + + /* We'll need to recalculate the GL viewport state derived + * from the Cogl viewport */ + ctx->dirty_gl_viewport = 1; +} + GSList * _cogl_create_draw_buffer_stack (void) { @@ -434,7 +454,7 @@ cogl_set_draw_buffer (CoglBufferTarget target, CoglHandle handle) entry->target = target; ctx->dirty_bound_framebuffer = 1; - ctx->dirty_viewport = 1; + ctx->dirty_gl_viewport = 1; if (draw_buffer != COGL_INVALID_HANDLE) cogl_handle_ref (draw_buffer); @@ -531,13 +551,19 @@ _cogl_draw_buffer_flush_state (CoglHandle handle, ctx->dirty_bound_framebuffer = FALSE; } - if (ctx->dirty_viewport) + if (ctx->dirty_gl_viewport) { + /* Convert the Cogl viewport y offset to an OpenGL viewport y offset + * (NB: OpenGL defines its window and viewport origins to be bottom + * left, while Cogl defines them to be top left.) */ + int gl_viewport_y = draw_buffer->height - + (draw_buffer->viewport_y + draw_buffer->viewport_height); + GE (glViewport (draw_buffer->viewport_x, - draw_buffer->viewport_y, + gl_viewport_y, draw_buffer->viewport_width, draw_buffer->viewport_height)); - ctx->dirty_viewport = FALSE; + ctx->dirty_gl_viewport = FALSE; } /* XXX: Flushing clip state may trash the modelview and projection diff --git a/clutter/cogl/cogl/cogl.h.in b/clutter/cogl/cogl/cogl.h.in index 23e417a29..9ce95ba35 100644 --- a/clutter/cogl/cogl/cogl.h.in +++ b/clutter/cogl/cogl/cogl.h.in @@ -869,6 +869,9 @@ void cogl_flush_gl_state (int flags); void _cogl_set_indirect_context (gboolean indirect); void _cogl_set_viewport (int x, int y, int width, int height); +void +_cogl_onscreen_clutter_backend_set_size (int width, int height); + G_END_DECLS #undef __COGL_H_INSIDE__