From 88c830b9ab6052ea069ba77fd707d2aefd05ff9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 13 Oct 2020 15:39:07 +0200 Subject: [PATCH] cogl/framebuffer: Move allocation and y-flip-ness to non-abstract types Now that CoglFramebuffer is a GObject, we can start moving things to the proper places. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1496 --- cogl/cogl/cogl-framebuffer.c | 110 +++++++++++++++++++---------------- cogl/cogl/cogl-framebuffer.h | 4 ++ cogl/cogl/cogl-onscreen.c | 31 ++++++++++ 3 files changed, 95 insertions(+), 50 deletions(-) diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c index 12e5e122a..ba33bfcbc 100644 --- a/cogl/cogl/cogl-framebuffer.c +++ b/cogl/cogl/cogl-framebuffer.c @@ -939,6 +939,52 @@ cogl_offscreen_get_texture (CoglOffscreen *offscreen) return offscreen->texture; } +static gboolean +cogl_offscreen_allocate (CoglFramebuffer *framebuffer, + GError **error) +{ + CoglOffscreen *offscreen = COGL_OFFSCREEN (framebuffer); + CoglContext *ctx = cogl_framebuffer_get_context (framebuffer); + CoglFramebufferPrivate *priv = + cogl_framebuffer_get_instance_private (framebuffer); + + if (!cogl_texture_allocate (offscreen->texture, error)) + return FALSE; + + /* NB: it's only after allocating the texture that we will + * determine whether a texture needs slicing... */ + if (cogl_texture_is_sliced (offscreen->texture)) + { + g_set_error (error, COGL_SYSTEM_ERROR, COGL_SYSTEM_ERROR_UNSUPPORTED, + "Can't create offscreen framebuffer from " + "sliced texture"); + return FALSE; + } + + /* Now that the texture has been allocated we can determine a + * size for the framebuffer... */ + priv->width = cogl_texture_get_width (offscreen->texture); + priv->height = cogl_texture_get_height (offscreen->texture); + priv->viewport_width = priv->width; + priv->viewport_height = priv->height; + + /* Forward the texture format as the internal format of the + * framebuffer */ + priv->internal_format = + _cogl_texture_get_format (offscreen->texture); + + if (!ctx->driver_vtable->offscreen_allocate (offscreen, error)) + return FALSE; + + return TRUE; +} + +static gboolean +cogl_offscreen_is_y_flipped (CoglFramebuffer *framebuffer) +{ + return TRUE; +} + static void cogl_offscreen_dispose (GObject *object) { @@ -966,8 +1012,12 @@ static void cogl_offscreen_class_init (CoglOffscreenClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + CoglFramebufferClass *framebuffer_class = COGL_FRAMEBUFFER_CLASS (klass); object_class->dispose = cogl_offscreen_dispose; + + framebuffer_class->allocate = cogl_offscreen_allocate; + framebuffer_class->is_y_flipped = cogl_offscreen_is_y_flipped; } gboolean @@ -985,58 +1035,12 @@ cogl_framebuffer_allocate (CoglFramebuffer *framebuffer, { CoglFramebufferPrivate *priv = cogl_framebuffer_get_instance_private (framebuffer); - const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer); - CoglContext *ctx = priv->context; if (priv->allocated) return TRUE; - if (COGL_IS_ONSCREEN (framebuffer)) - { - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - - if (!winsys->onscreen_init (onscreen, error)) - return FALSE; - - /* If the winsys doesn't support dirty events then we'll report - * one on allocation so that if the application only paints in - * response to dirty events then it will at least paint once to - * start */ - if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_DIRTY_EVENTS)) - _cogl_onscreen_queue_full_dirty (onscreen); - } - else - { - CoglOffscreen *offscreen = COGL_OFFSCREEN (framebuffer); - - if (!cogl_texture_allocate (offscreen->texture, error)) - return FALSE; - - /* NB: it's only after allocating the texture that we will - * determine whether a texture needs slicing... */ - if (cogl_texture_is_sliced (offscreen->texture)) - { - g_set_error (error, COGL_SYSTEM_ERROR, COGL_SYSTEM_ERROR_UNSUPPORTED, - "Can't create offscreen framebuffer from " - "sliced texture"); - return FALSE; - } - - /* Now that the texture has been allocated we can determine a - * size for the framebuffer... */ - priv->width = cogl_texture_get_width (offscreen->texture); - priv->height = cogl_texture_get_height (offscreen->texture); - priv->viewport_width = priv->width; - priv->viewport_height = priv->height; - - /* Forward the texture format as the internal format of the - * framebuffer */ - priv->internal_format = - _cogl_texture_get_format (offscreen->texture); - - if (!ctx->driver_vtable->offscreen_allocate (offscreen, error)) - return FALSE; - } + if (!COGL_FRAMEBUFFER_GET_CLASS (framebuffer)->allocate (framebuffer, error)) + return FALSE; priv->allocated = TRUE; @@ -1669,6 +1673,12 @@ cogl_framebuffer_read_pixels (CoglFramebuffer *framebuffer, return ret; } +static gboolean +cogl_framebuffer_is_y_flipped (CoglFramebuffer *framebuffer) +{ + return COGL_FRAMEBUFFER_GET_CLASS (framebuffer)->is_y_flipped (framebuffer); +} + gboolean cogl_blit_framebuffer (CoglFramebuffer *framebuffer, CoglFramebuffer *dst, @@ -1733,7 +1743,7 @@ cogl_blit_framebuffer (CoglFramebuffer *framebuffer, /* Offscreens we do the normal way, onscreens need an y-flip. Even if * we consider offscreens to be rendered upside-down, the offscreen * orientation is in this function's API. */ - if (COGL_IS_OFFSCREEN (framebuffer)) + if (cogl_framebuffer_is_y_flipped (framebuffer)) { src_x1 = src_x; src_y1 = src_y; @@ -1748,7 +1758,7 @@ cogl_blit_framebuffer (CoglFramebuffer *framebuffer, src_y2 = src_y1 - height; } - if (COGL_IS_OFFSCREEN (dst)) + if (cogl_framebuffer_is_y_flipped (dst)) { dst_x1 = dst_x; dst_y1 = dst_y; diff --git a/cogl/cogl/cogl-framebuffer.h b/cogl/cogl/cogl-framebuffer.h index 3dc05bba2..688c35f76 100644 --- a/cogl/cogl/cogl-framebuffer.h +++ b/cogl/cogl/cogl-framebuffer.h @@ -94,6 +94,10 @@ struct _CoglFramebufferClass { /*< private >*/ GObjectClass parent_class; + + gboolean (* allocate) (CoglFramebuffer *framebuffer, + GError **error); + gboolean (* is_y_flipped) (CoglFramebuffer *framebuffer); }; /** diff --git a/cogl/cogl/cogl-onscreen.c b/cogl/cogl/cogl-onscreen.c index c81bc80db..d3585ba46 100644 --- a/cogl/cogl/cogl-onscreen.c +++ b/cogl/cogl/cogl-onscreen.c @@ -107,6 +107,33 @@ cogl_onscreen_new (CoglContext *ctx, int width, int height) return onscreen; } +static gboolean +cogl_onscreen_allocate (CoglFramebuffer *framebuffer, + GError **error) +{ + CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); + const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer); + CoglContext *ctx = cogl_framebuffer_get_context (framebuffer); + + if (!winsys->onscreen_init (onscreen, error)) + return FALSE; + + /* If the winsys doesn't support dirty events then we'll report + * one on allocation so that if the application only paints in + * response to dirty events then it will at least paint once to + * start */ + if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_DIRTY_EVENTS)) + _cogl_onscreen_queue_full_dirty (onscreen); + + return TRUE; +} + +static gboolean +cogl_onscreen_is_y_flipped (CoglFramebuffer *framebuffer) +{ + return FALSE; +} + static void cogl_onscreen_dispose (GObject *object) { @@ -139,8 +166,12 @@ static void cogl_onscreen_class_init (CoglOnscreenClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); + CoglFramebufferClass *framebuffer_class = COGL_FRAMEBUFFER_CLASS (klass); object_class->dispose = cogl_onscreen_dispose; + + framebuffer_class->allocate = cogl_onscreen_allocate; + framebuffer_class->is_y_flipped = cogl_onscreen_is_y_flipped; } static void