[mutter] Make all CoglOnscreen sub types inherit CoglOnscreen



commit 0b568b68c6eaf3052b35c68ece8613f620735f2e
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Sun Oct 18 01:39:21 2020 +0200

    Make all CoglOnscreen sub types inherit CoglOnscreen
    
    Thins means that e.g. MetaOnscreenNative now inherits CoglOnscreenEgl,
    which inherits CoglOnscreen which inherits CoglFramebuffer, all being
    the same GObject instance.
    
    This makes it necessary to the one creating the onscreen to know what it
    wants to create. For the X11 backend, the type of renderer (Xlib EGL or
    GLX) determines the type, and for the native backend, it's currently
    always MetaOnscreenNative.
    
    The "winsys" vfunc entries related to onscreens hasn't been moved yet,
    that will come later.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1514>

 cogl/cogl/cogl-mutter.h                    |   6 +
 cogl/cogl/cogl-onscreen.c                  | 104 ++++-----
 cogl/cogl/cogl-onscreen.h                  |  29 +--
 cogl/cogl/winsys/cogl-onscreen-egl.c       |  62 ++----
 cogl/cogl/winsys/cogl-onscreen-egl.h       |  18 +-
 cogl/cogl/winsys/cogl-onscreen-glx.c       |  76 ++++---
 cogl/cogl/winsys/cogl-onscreen-glx.h       |  10 +
 cogl/cogl/winsys/cogl-onscreen-xlib.c      |  69 +++---
 cogl/cogl/winsys/cogl-onscreen-xlib.h      |  11 +
 cogl/cogl/winsys/cogl-winsys-glx.c         |   5 +-
 cogl/test-fixtures/test-utils.c            |  37 +++-
 src/backends/native/meta-onscreen-native.c | 343 +++++++++++------------------
 src/backends/native/meta-onscreen-native.h |  23 +-
 src/backends/native/meta-renderer-native.c |  38 ++--
 src/backends/x11/meta-stage-x11.c          |  35 ++-
 15 files changed, 411 insertions(+), 455 deletions(-)
---
diff --git a/cogl/cogl/cogl-mutter.h b/cogl/cogl/cogl-mutter.h
index 9251d916b5..1f94d0d991 100644
--- a/cogl/cogl/cogl-mutter.h
+++ b/cogl/cogl/cogl-mutter.h
@@ -42,6 +42,12 @@
 #include <cogl/winsys/cogl-onscreen-egl.h>
 #include <cogl/winsys/cogl-winsys-egl-private.h>
 #endif
+#if defined (COGL_HAS_GLX_SUPPORT)
+#include <cogl/winsys/cogl-onscreen-glx.h>
+#endif
+#if defined (COGL_HAS_XLIB_SUPPORT)
+#include <cogl/winsys/cogl-onscreen-xlib.h>
+#endif
 #include <cogl/winsys/cogl-winsys-private.h>
 
 COGL_EXPORT
diff --git a/cogl/cogl/cogl-onscreen.c b/cogl/cogl/cogl-onscreen.c
index 1eb5b93bb2..7ea6db8f29 100644
--- a/cogl/cogl/cogl-onscreen.c
+++ b/cogl/cogl/cogl-onscreen.c
@@ -42,11 +42,6 @@
 #include "cogl-poll-private.h"
 #include "cogl-gtype-private.h"
 
-struct _CoglOnscreen
-{
-  CoglFramebuffer parent;
-};
-
 typedef struct _CoglOnscreenPrivate
 {
   CoglList frame_closures;
@@ -62,7 +57,7 @@ typedef struct _CoglOnscreenPrivate
                                * cogl_onscreen_swap_buffers() */
   GQueue pending_frame_infos;
 
-  void *winsys;
+  gboolean needs_deinit;
 } CoglOnscreenPrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (CoglOnscreen, cogl_onscreen, COGL_TYPE_FRAMEBUFFER)
@@ -92,58 +87,20 @@ COGL_GTYPE_DEFINE_BOXED (OnscreenDirtyClosure,
 
 G_DEFINE_QUARK (cogl-scanout-error-quark, cogl_scanout_error)
 
-static void
-_cogl_onscreen_init_from_template (CoglOnscreen *onscreen,
-                                   CoglOnscreenTemplate *onscreen_template)
-{
-  CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen);
-  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
-
-  _cogl_list_init (&priv->frame_closures);
-  _cogl_list_init (&priv->resize_closures);
-  _cogl_list_init (&priv->dirty_closures);
-
-  cogl_framebuffer_init_config (framebuffer, &onscreen_template->config);
-}
-
-CoglOnscreen *
-cogl_onscreen_new (CoglContext *ctx, int width, int height)
-{
-  CoglOnscreen *onscreen;
-
-  /* FIXME: We are assuming onscreen buffers will always be
-     premultiplied so we'll set the premult flag on the bitmap
-     format. This will usually be correct because the result of the
-     default blending operations for Cogl ends up with premultiplied
-     data in the framebuffer. However it is possible for the
-     framebuffer to be in whatever format depending on what
-     CoglPipeline is used to render to it. Eventually we may want to
-     add a way for an application to inform Cogl that the framebuffer
-     is not premultiplied in case it is being used for some special
-     purpose. */
-
-  onscreen = g_object_new (COGL_TYPE_ONSCREEN,
-                           "context", ctx,
-                           "width", width,
-                           "height", height,
-                           NULL);
-
-  _cogl_onscreen_init_from_template (onscreen, ctx->display->onscreen_template);
-
-  return onscreen;
-}
-
 static gboolean
 cogl_onscreen_allocate (CoglFramebuffer  *framebuffer,
                         GError          **error)
 {
   CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
+  CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen);
   const CoglWinsysVtable *winsys = _cogl_framebuffer_get_winsys (framebuffer);
   CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
 
   if (!winsys->onscreen_init (onscreen, error))
     return FALSE;
 
+  priv->needs_deinit = TRUE;
+
   /* 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
@@ -160,6 +117,34 @@ cogl_onscreen_is_y_flipped (CoglFramebuffer *framebuffer)
   return FALSE;
 }
 
+static void
+cogl_onscreen_init_from_template (CoglOnscreen *onscreen,
+                                   CoglOnscreenTemplate *onscreen_template)
+{
+  CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen);
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+
+  _cogl_list_init (&priv->frame_closures);
+  _cogl_list_init (&priv->resize_closures);
+  _cogl_list_init (&priv->dirty_closures);
+
+  cogl_framebuffer_init_config (framebuffer, &onscreen_template->config);
+}
+
+static void
+cogl_onscreen_constructed (GObject *object)
+{
+  CoglOnscreen *onscreen = COGL_ONSCREEN (object);
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+  CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
+  CoglOnscreenTemplate *onscreen_template;
+
+  onscreen_template = ctx->display->onscreen_template;
+  cogl_onscreen_init_from_template (onscreen, onscreen_template);
+
+  G_OBJECT_CLASS (cogl_onscreen_parent_class)->constructed (object);
+}
+
 static void
 cogl_onscreen_dispose (GObject *object)
 {
@@ -177,9 +162,11 @@ cogl_onscreen_dispose (GObject *object)
     cogl_object_unref (frame_info);
   g_queue_clear (&priv->pending_frame_infos);
 
-  if (priv->winsys)
-    winsys->onscreen_deinit (onscreen);
-  g_return_if_fail (priv->winsys == NULL);
+  if (priv->needs_deinit)
+    {
+      winsys->onscreen_deinit (onscreen);
+      priv->needs_deinit = FALSE;
+    }
 
   G_OBJECT_CLASS (cogl_onscreen_parent_class)->dispose (object);
 }
@@ -195,6 +182,7 @@ cogl_onscreen_class_init (CoglOnscreenClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   CoglFramebufferClass *framebuffer_class = COGL_FRAMEBUFFER_CLASS (klass);
 
+  object_class->constructed = cogl_onscreen_constructed;
   object_class->dispose = cogl_onscreen_dispose;
 
   framebuffer_class->allocate = cogl_onscreen_allocate;
@@ -714,19 +702,3 @@ cogl_onscreen_get_frame_counter (CoglOnscreen *onscreen)
   return priv->frame_counter;
 }
 
-void
-cogl_onscreen_set_winsys (CoglOnscreen *onscreen,
-                          gpointer      winsys)
-{
-  CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen);
-
-  priv->winsys = winsys;
-}
-
-gpointer
-cogl_onscreen_get_winsys (CoglOnscreen *onscreen)
-{
-  CoglOnscreenPrivate *priv = cogl_onscreen_get_instance_private (onscreen);
-
-  return priv->winsys;
-}
diff --git a/cogl/cogl/cogl-onscreen.h b/cogl/cogl/cogl-onscreen.h
index 308513a307..a815d7cb40 100644
--- a/cogl/cogl/cogl-onscreen.h
+++ b/cogl/cogl/cogl-onscreen.h
@@ -49,9 +49,15 @@ G_BEGIN_DECLS
 
 #define COGL_TYPE_ONSCREEN (cogl_onscreen_get_type ())
 COGL_EXPORT
-G_DECLARE_FINAL_TYPE (CoglOnscreen, cogl_onscreen,
-                      COGL, ONSCREEN,
-                      CoglFramebuffer)
+G_DECLARE_DERIVABLE_TYPE (CoglOnscreen, cogl_onscreen,
+                          COGL, ONSCREEN,
+                          CoglFramebuffer)
+
+struct _CoglOnscreenClass
+{
+  /*< private >*/
+  CoglFramebufferClass parent_class;
+};
 
 #define COGL_SCANOUT_ERROR (cogl_scanout_error_quark ())
 COGL_EXPORT GQuark
@@ -64,23 +70,6 @@ typedef enum _CoglScanoutError
 
 typedef struct _CoglScanout CoglScanout;
 
-/**
- * cogl_onscreen_new: (constructor) (skip)
- * @context: A #CoglContext
- * @width: The desired framebuffer width
- * @height: The desired framebuffer height
- *
- * Instantiates an "unallocated" #CoglOnscreen framebuffer that may be
- * configured before later being allocated, either implicitly when
- * it is first used or explicitly via cogl_framebuffer_allocate().
- *
- * Return value: (transfer full): A newly instantiated #CoglOnscreen framebuffer
- * Since: 1.8
- * Stability: unstable
- */
-COGL_EXPORT CoglOnscreen *
-cogl_onscreen_new (CoglContext *context, int width, int height);
-
 #ifdef COGL_HAS_X11
 /**
  * cogl_x11_onscreen_get_window_xid:
diff --git a/cogl/cogl/winsys/cogl-onscreen-egl.c b/cogl/cogl/winsys/cogl-onscreen-egl.c
index 925adc63d5..a5710b9b1c 100644
--- a/cogl/cogl/winsys/cogl-onscreen-egl.c
+++ b/cogl/cogl/winsys/cogl-onscreen-egl.c
@@ -40,34 +40,8 @@ typedef struct _CoglOnscreenEglPrivate
   void *platform;
 } CoglOnscreenEglPrivate;
 
-typedef struct _CoglOnscreenEgl
-{
-  CoglOnscreenEglPrivate *priv;
-} CoglOnscreenEgl;
-
-CoglOnscreenEgl *
-cogl_onscreen_egl_new (void)
-{
-  CoglOnscreenEgl *onscreen_egl;
-
-  onscreen_egl = g_slice_new0 (CoglOnscreenEgl);
-  onscreen_egl->priv = g_new0 (CoglOnscreenEglPrivate, 1);
-
-  return onscreen_egl;
-}
-
-void
-cogl_onscreen_egl_free (CoglOnscreenEgl *onscreen_egl)
-{
-  g_free (onscreen_egl->priv);
-  g_slice_free (CoglOnscreenEgl, onscreen_egl);
-}
-
-static CoglOnscreenEglPrivate *
-cogl_onscreen_egl_get_instance_private (CoglOnscreenEgl *onscreen_egl)
-{
-  return onscreen_egl->priv;
-}
+G_DEFINE_TYPE_WITH_PRIVATE (CoglOnscreenEgl, cogl_onscreen_egl,
+                            COGL_TYPE_ONSCREEN)
 
 gboolean
 _cogl_winsys_onscreen_egl_init (CoglOnscreen  *onscreen,
@@ -84,7 +58,6 @@ _cogl_winsys_onscreen_egl_init (CoglOnscreen  *onscreen,
   EGLConfig egl_config;
   EGLint config_count = 0;
   EGLBoolean status;
-  CoglOnscreenEgl *winsys;
 
   g_return_val_if_fail (egl_display->egl_context, FALSE);
 
@@ -115,17 +88,11 @@ _cogl_winsys_onscreen_egl_init (CoglOnscreen  *onscreen,
       cogl_framebuffer_update_samples_per_pixel (framebuffer, samples);
     }
 
-  winsys = cogl_onscreen_egl_new ();
-  cogl_onscreen_set_winsys (onscreen, winsys);
-
   if (egl_renderer->platform_vtable->onscreen_init &&
       !egl_renderer->platform_vtable->onscreen_init (onscreen,
                                                      egl_config,
                                                      error))
-    {
-      g_slice_free (CoglOnscreenEgl, winsys);
-      return FALSE;
-    }
+    return FALSE;
 
   return TRUE;
 }
@@ -133,7 +100,7 @@ _cogl_winsys_onscreen_egl_init (CoglOnscreen  *onscreen,
 void
 _cogl_winsys_onscreen_egl_deinit (CoglOnscreen *onscreen)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenEgl *onscreen_egl = COGL_ONSCREEN_EGL (onscreen);
   CoglOnscreenEglPrivate *priv =
     cogl_onscreen_egl_get_instance_private (onscreen_egl);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@@ -171,16 +138,13 @@ _cogl_winsys_onscreen_egl_deinit (CoglOnscreen *onscreen)
 
   if (egl_renderer->platform_vtable->onscreen_deinit)
     egl_renderer->platform_vtable->onscreen_deinit (onscreen);
-
-  g_slice_free (CoglOnscreenEgl, cogl_onscreen_get_winsys (onscreen));
-  cogl_onscreen_set_winsys (onscreen, NULL);
 }
 
 static gboolean
 bind_onscreen_with_context (CoglOnscreen *onscreen,
                             EGLContext egl_context)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenEgl *onscreen_egl = COGL_ONSCREEN_EGL (onscreen);
   CoglOnscreenEglPrivate *priv =
     cogl_onscreen_egl_get_instance_private (onscreen_egl);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@@ -224,7 +188,7 @@ _cogl_winsys_onscreen_egl_bind (CoglOnscreen *onscreen)
 int
 _cogl_winsys_onscreen_egl_get_buffer_age (CoglOnscreen *onscreen)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenEgl *onscreen_egl = COGL_ONSCREEN_EGL (onscreen);
   CoglOnscreenEglPrivate *priv =
     cogl_onscreen_egl_get_instance_private (onscreen_egl);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@@ -265,7 +229,7 @@ _cogl_winsys_onscreen_egl_swap_region (CoglOnscreen  *onscreen,
                                        CoglFrameInfo *info,
                                        gpointer       user_data)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenEgl *onscreen_egl = COGL_ONSCREEN_EGL (onscreen);
   CoglOnscreenEglPrivate *priv =
     cogl_onscreen_egl_get_instance_private (onscreen_egl);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@@ -308,7 +272,7 @@ _cogl_winsys_onscreen_egl_swap_buffers_with_damage (CoglOnscreen  *onscreen,
                                                     CoglFrameInfo *info,
                                                     gpointer       user_data)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenEgl *onscreen_egl = COGL_ONSCREEN_EGL (onscreen);
   CoglOnscreenEglPrivate *priv =
     cogl_onscreen_egl_get_instance_private (onscreen_egl);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@@ -392,3 +356,13 @@ cogl_onscreen_egl_get_egl_surface (CoglOnscreenEgl *onscreen_egl)
 
   return priv->egl_surface;
 }
+
+static void
+cogl_onscreen_egl_init (CoglOnscreenEgl *onscreen_egl)
+{
+}
+
+static void
+cogl_onscreen_egl_class_init (CoglOnscreenEglClass *klass)
+{
+}
diff --git a/cogl/cogl/winsys/cogl-onscreen-egl.h b/cogl/cogl/winsys/cogl-onscreen-egl.h
index 200e1fe0d6..4f2ae458dc 100644
--- a/cogl/cogl/winsys/cogl-onscreen-egl.h
+++ b/cogl/cogl/winsys/cogl-onscreen-egl.h
@@ -29,13 +29,17 @@
 #include "cogl-onscreen.h"
 #include "winsys/cogl-winsys-egl-private.h"
 
-typedef struct _CoglOnscreenEgl CoglOnscreenEgl;
-
-COGL_EXPORT CoglOnscreenEgl *
-cogl_onscreen_egl_new (void);
-
-COGL_EXPORT void
-cogl_onscreen_egl_free (CoglOnscreenEgl *onscreen_egl);
+#define COGL_TYPE_ONSCREEN_EGL (cogl_onscreen_egl_get_type ())
+COGL_EXPORT
+G_DECLARE_DERIVABLE_TYPE (CoglOnscreenEgl, cogl_onscreen_egl,
+                          COGL, ONSCREEN_EGL,
+                          CoglOnscreen)
+
+struct _CoglOnscreenEglClass
+{
+  /*< private >*/
+  CoglOnscreenClass parent_class;
+};
 
 gboolean
 _cogl_winsys_onscreen_egl_init (CoglOnscreen  *onscreen,
diff --git a/cogl/cogl/winsys/cogl-onscreen-glx.c b/cogl/cogl/winsys/cogl-onscreen-glx.c
index 4493bef6bb..5331e828e4 100644
--- a/cogl/cogl/winsys/cogl-onscreen-glx.c
+++ b/cogl/cogl/winsys/cogl-onscreen-glx.c
@@ -38,8 +38,10 @@
 #include "winsys/cogl-glx-renderer-private.h"
 #include "winsys/cogl-winsys-glx-private.h"
 
-typedef struct _CoglOnscreenGlx
+struct _CoglOnscreenGlx
 {
+  CoglOnscreen parent;
+
   Window xwin;
   int x, y;
   CoglOutput *output;
@@ -49,7 +51,10 @@ typedef struct _CoglOnscreenGlx
   uint32_t pending_sync_notify;
   uint32_t pending_complete_notify;
   uint32_t pending_resize_notify;
-} CoglOnscreenGlx;
+};
+
+G_DEFINE_TYPE (CoglOnscreenGlx, cogl_onscreen_glx,
+               COGL_TYPE_ONSCREEN)
 
 #define COGL_ONSCREEN_X11_EVENT_MASK (StructureNotifyMask | ExposureMask)
 
@@ -57,6 +62,7 @@ gboolean
 _cogl_winsys_onscreen_glx_init (CoglOnscreen  *onscreen,
                                 GError       **error)
 {
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglDisplay *display = context->display;
@@ -65,11 +71,9 @@ _cogl_winsys_onscreen_glx_init (CoglOnscreen  *onscreen,
     _cogl_xlib_renderer_get_data (display->renderer);
   CoglGLXRenderer *glx_renderer = display->renderer->winsys;
   Window xwin;
-  CoglOnscreenGlx *onscreen_glx;
   const CoglFramebufferConfig *config;
   GLXFBConfig fbconfig;
   GError *fbconfig_error = NULL;
-  CoglOnscreenGlx *winsys;
 
   g_return_val_if_fail (glx_display->glx_context, FALSE);
 
@@ -168,10 +172,6 @@ _cogl_winsys_onscreen_glx_init (CoglOnscreen  *onscreen,
         }
     }
 
-  winsys = g_slice_new0 (CoglOnscreenGlx);
-  cogl_onscreen_set_winsys (onscreen, winsys);
-  onscreen_glx = cogl_onscreen_get_winsys (onscreen);
-
   onscreen_glx->xwin = xwin;
 
   /* Try and create a GLXWindow to use with extensions dependent on
@@ -208,6 +208,7 @@ _cogl_winsys_onscreen_glx_init (CoglOnscreen  *onscreen,
 void
 _cogl_winsys_onscreen_glx_deinit (CoglOnscreen *onscreen)
 {
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglGLXDisplay *glx_display = context->display->winsys;
@@ -215,7 +216,6 @@ _cogl_winsys_onscreen_glx_deinit (CoglOnscreen *onscreen)
     _cogl_xlib_renderer_get_data (context->display->renderer);
   CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
   CoglXlibTrapState old_state;
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
   GLXDrawable drawable;
 
   /* If we never successfully allocated then there's nothing to do */
@@ -268,21 +268,18 @@ _cogl_winsys_onscreen_glx_deinit (CoglOnscreen *onscreen)
   XSync (xlib_renderer->xdpy, False);
 
   _cogl_xlib_renderer_untrap_errors (context->display->renderer, &old_state);
-
-  g_slice_free (CoglOnscreenGlx, cogl_onscreen_get_winsys (onscreen));
-  cogl_onscreen_set_winsys (onscreen, NULL);
 }
 
 void
 _cogl_winsys_onscreen_glx_bind (CoglOnscreen *onscreen)
 {
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglGLXDisplay *glx_display = context->display->winsys;
   CoglXlibRenderer *xlib_renderer =
     _cogl_xlib_renderer_get_data (context->display->renderer);
   CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
   CoglXlibTrapState old_state;
   GLXDrawable drawable;
 
@@ -469,7 +466,7 @@ _cogl_winsys_wait_for_vblank (CoglOnscreen *onscreen)
 
       if (glx_renderer->glXWaitForMsc)
         {
-          CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
+          CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
           Drawable drawable = onscreen_glx->glxwin;
           int64_t ust;
           int64_t msc;
@@ -516,11 +513,11 @@ _cogl_winsys_get_vsync_counter (CoglContext *ctx)
 int
 _cogl_winsys_onscreen_glx_get_buffer_age (CoglOnscreen *onscreen)
 {
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglXlibRenderer *xlib_renderer = _cogl_xlib_renderer_get_data (context->display->renderer);
   CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
   GLXDrawable drawable;
   unsigned int age;
 
@@ -550,7 +547,7 @@ set_frame_info_output (CoglOnscreen *onscreen,
 static void
 cogl_onscreen_glx_flush_notification (CoglOnscreen *onscreen)
 {
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
 
   while (onscreen_glx->pending_sync_notify > 0 ||
          onscreen_glx->pending_complete_notify > 0 ||
@@ -617,7 +614,7 @@ flush_pending_notifications_idle (void *user_data)
 static void
 set_sync_pending (CoglOnscreen *onscreen)
 {
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglRenderer *renderer = context->display->renderer;
@@ -641,7 +638,7 @@ set_sync_pending (CoglOnscreen *onscreen)
 static void
 set_complete_pending (CoglOnscreen *onscreen)
 {
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglRenderer *renderer = context->display->renderer;
@@ -669,13 +666,13 @@ _cogl_winsys_onscreen_glx_swap_region (CoglOnscreen  *onscreen,
                                        CoglFrameInfo *info,
                                        gpointer       user_data)
 {
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglXlibRenderer *xlib_renderer =
     _cogl_xlib_renderer_get_data (context->display->renderer);
   CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
   CoglGLXDisplay *glx_display = context->display->winsys;
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
   uint32_t end_frame_vsync_counter = 0;
   gboolean have_counter;
   gboolean can_wait;
@@ -878,13 +875,13 @@ _cogl_winsys_onscreen_glx_swap_buffers_with_damage (CoglOnscreen  *onscreen,
                                                     CoglFrameInfo *info,
                                                     gpointer       user_data)
 {
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglXlibRenderer *xlib_renderer =
     _cogl_xlib_renderer_get_data (context->display->renderer);
   CoglGLXRenderer *glx_renderer = context->display->renderer->winsys;
   CoglGLXDisplay *glx_display = context->display->winsys;
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
   gboolean have_counter;
   GLXDrawable drawable;
 
@@ -952,7 +949,7 @@ _cogl_winsys_onscreen_glx_swap_buffers_with_damage (CoglOnscreen  *onscreen,
 uint32_t
 _cogl_winsys_onscreen_glx_get_window_xid (CoglOnscreen *onscreen)
 {
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
 
   return onscreen_glx->xwin;
 }
@@ -961,11 +958,11 @@ void
 _cogl_winsys_onscreen_glx_set_visibility (CoglOnscreen *onscreen,
                                           gboolean      visibility)
 {
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglXlibRenderer *xlib_renderer =
     _cogl_xlib_renderer_get_data (context->display->renderer);
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
 
   if (visibility)
     XMapWindow (xlib_renderer->xdpy, onscreen_glx->xwin);
@@ -977,11 +974,11 @@ void
 _cogl_winsys_onscreen_glx_set_resizable (CoglOnscreen *onscreen,
                                          gboolean      resizable)
 {
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglXlibRenderer *xlib_renderer =
     _cogl_xlib_renderer_get_data (context->display->renderer);
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
 
   XSizeHints *size_hints = XAllocSizeHints ();
 
@@ -1015,9 +1012,7 @@ void
 cogl_onscreen_glx_notify_swap_buffers (CoglOnscreen          *onscreen,
                                        GLXBufferSwapComplete *swap_event)
 {
-  CoglOnscreenGlx *onscreen_glx;
-
-  onscreen_glx = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
 
   /* We only want to notify that the swap is complete when the
      application calls cogl_context_dispatch so instead of immediately
@@ -1043,7 +1038,7 @@ cogl_onscreen_glx_notify_swap_buffers (CoglOnscreen          *onscreen,
 void
 cogl_onscreen_glx_update_output (CoglOnscreen *onscreen)
 {
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglDisplay *display = context->display;
@@ -1072,14 +1067,13 @@ void
 cogl_onscreen_glx_resize (CoglOnscreen    *onscreen,
                           XConfigureEvent *configure_event)
 {
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglRenderer *renderer = context->display->renderer;
   CoglGLXRenderer *glx_renderer = renderer->winsys;
-  CoglOnscreenGlx *onscreen_glx;
   int x, y;
 
-  onscreen_glx = cogl_onscreen_get_winsys (onscreen);
 
   _cogl_framebuffer_winsys_update_size (framebuffer,
                                         configure_event->width,
@@ -1123,7 +1117,29 @@ gboolean
 cogl_onscreen_glx_is_for_window (CoglOnscreen *onscreen,
                                  Window        window)
 {
-  CoglOnscreenGlx *onscreen_glx = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenGlx *onscreen_glx = COGL_ONSCREEN_GLX (onscreen);
 
   return onscreen_glx->xwin == window;
 }
+
+CoglOnscreenGlx *
+cogl_onscreen_glx_new (CoglContext *context,
+                       int          width,
+                       int          height)
+{
+  return g_object_new (COGL_TYPE_ONSCREEN_GLX,
+                       "context", context,
+                       "width", width,
+                       "height", height,
+                       NULL);
+}
+
+static void
+cogl_onscreen_glx_init (CoglOnscreenGlx *onscreen_glx)
+{
+}
+
+static void
+cogl_onscreen_glx_class_init (CoglOnscreenGlxClass *klass)
+{
+}
diff --git a/cogl/cogl/winsys/cogl-onscreen-glx.h b/cogl/cogl/winsys/cogl-onscreen-glx.h
index e218a6a964..75454ae926 100644
--- a/cogl/cogl/winsys/cogl-onscreen-glx.h
+++ b/cogl/cogl/winsys/cogl-onscreen-glx.h
@@ -31,6 +31,16 @@
 
 #include "cogl-onscreen.h"
 
+#define COGL_TYPE_ONSCREEN_GLX (cogl_onscreen_glx_get_type ())
+G_DECLARE_FINAL_TYPE (CoglOnscreenGlx, cogl_onscreen_glx,
+                      COGL, ONSCREEN_GLX,
+                      CoglOnscreen)
+
+COGL_EXPORT CoglOnscreenGlx *
+cogl_onscreen_glx_new (CoglContext *context,
+                       int          width,
+                       int          height);
+
 gboolean
 _cogl_winsys_onscreen_glx_init (CoglOnscreen  *onscreen,
                                 GError       **error);
diff --git a/cogl/cogl/winsys/cogl-onscreen-xlib.c b/cogl/cogl/winsys/cogl-onscreen-xlib.c
index cfa5206a49..b1d1aac6c6 100644
--- a/cogl/cogl/winsys/cogl-onscreen-xlib.c
+++ b/cogl/cogl/winsys/cogl-onscreen-xlib.c
@@ -34,12 +34,17 @@
 #include "winsys/cogl-onscreen-egl.h"
 #include "winsys/cogl-winsys-egl-x11-private.h"
 
-typedef struct _CoglOnscreenXlib
+struct _CoglOnscreenXlib
 {
+  CoglOnscreenEgl parent;
+
   Window xwin;
 
   gboolean pending_resize_notify;
-} CoglOnscreenXlib;
+};
+
+G_DEFINE_TYPE (CoglOnscreenXlib, cogl_onscreen_xlib,
+               COGL_TYPE_ONSCREEN_EGL)
 
 #define COGL_ONSCREEN_X11_EVENT_MASK (StructureNotifyMask | ExposureMask)
 
@@ -48,6 +53,7 @@ _cogl_winsys_egl_onscreen_xlib_init (CoglOnscreen  *onscreen,
                                      EGLConfig      egl_config,
                                      GError       **error)
 {
+  CoglOnscreenXlib *onscreen_xlib = COGL_ONSCREEN_XLIB (onscreen);;
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglDisplay *display = context->display;
@@ -55,8 +61,7 @@ _cogl_winsys_egl_onscreen_xlib_init (CoglOnscreen  *onscreen,
   CoglRendererEGL *egl_renderer = renderer->winsys;
   CoglXlibRenderer *xlib_renderer =
     _cogl_xlib_renderer_get_data (renderer);
-  CoglOnscreenXlib *onscreen_xlib;
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenEgl *onscreen_egl = COGL_ONSCREEN_EGL (onscreen);
   Window xwin;
   EGLSurface egl_surface;
 
@@ -132,9 +137,6 @@ _cogl_winsys_egl_onscreen_xlib_init (CoglOnscreen  *onscreen,
         }
     }
 
-  onscreen_xlib = g_slice_new (CoglOnscreenXlib);
-  cogl_onscreen_egl_set_platform (onscreen_egl, onscreen_xlib);
-
   onscreen_xlib->xwin = xwin;
 
   egl_surface =
@@ -151,15 +153,13 @@ _cogl_winsys_egl_onscreen_xlib_init (CoglOnscreen  *onscreen,
 void
 _cogl_winsys_egl_onscreen_xlib_deinit (CoglOnscreen *onscreen)
 {
+  CoglOnscreenXlib *onscreen_xlib = COGL_ONSCREEN_XLIB (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglRenderer *renderer = context->display->renderer;
   CoglXlibRenderer *xlib_renderer =
     _cogl_xlib_renderer_get_data (renderer);
   CoglXlibTrapState old_state;
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  CoglOnscreenXlib *onscreen_xlib =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
 
   _cogl_xlib_renderer_trap_errors (renderer, &old_state);
 
@@ -176,22 +176,18 @@ _cogl_winsys_egl_onscreen_xlib_deinit (CoglOnscreen *onscreen)
   if (_cogl_xlib_renderer_untrap_errors (renderer,
                                          &old_state) != Success)
     g_warning ("X Error while destroying X window");
-
-  g_slice_free (CoglOnscreenXlib, onscreen_xlib);
 }
 
 void
 _cogl_winsys_onscreen_xlib_set_visibility (CoglOnscreen *onscreen,
                                            gboolean      visibility)
 {
+  CoglOnscreenXlib *onscreen_xlib = COGL_ONSCREEN_XLIB (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglRenderer *renderer = context->display->renderer;
   CoglXlibRenderer *xlib_renderer =
     _cogl_xlib_renderer_get_data (renderer);
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  CoglOnscreenXlib *onscreen_xlib =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
 
   if (visibility)
     XMapWindow (xlib_renderer->xdpy, onscreen_xlib->xwin);
@@ -203,13 +199,11 @@ void
 _cogl_winsys_onscreen_xlib_set_resizable (CoglOnscreen *onscreen,
                                           gboolean      resizable)
 {
+  CoglOnscreenXlib *onscreen_xlib = COGL_ONSCREEN_XLIB (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglXlibRenderer *xlib_renderer =
     _cogl_xlib_renderer_get_data (context->display->renderer);
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  CoglOnscreenXlib *onscreen_xlib =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
 
   XSizeHints *size_hints = XAllocSizeHints ();
 
@@ -242,9 +236,7 @@ _cogl_winsys_onscreen_xlib_set_resizable (CoglOnscreen *onscreen,
 uint32_t
 _cogl_winsys_onscreen_xlib_get_window_xid (CoglOnscreen *onscreen)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  CoglOnscreenXlib *onscreen_xlib =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  CoglOnscreenXlib *onscreen_xlib = COGL_ONSCREEN_XLIB (onscreen);
 
   return onscreen_xlib->xwin;
 }
@@ -253,9 +245,7 @@ gboolean
 cogl_onscreen_xlib_is_for_window (CoglOnscreen *onscreen,
                                   Window        window)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  CoglOnscreenXlib *onscreen_xlib =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  CoglOnscreenXlib *onscreen_xlib = COGL_ONSCREEN_XLIB (onscreen);
 
   return onscreen_xlib->xwin == window;
 }
@@ -269,9 +259,7 @@ flush_pending_resize_notifications_cb (void *data,
   if (COGL_IS_ONSCREEN (framebuffer))
     {
       CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
-      CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-      CoglOnscreenXlib *onscreen_xlib =
-        cogl_onscreen_egl_get_platform (onscreen_egl);
+      CoglOnscreenXlib *onscreen_xlib = COGL_ONSCREEN_XLIB (onscreen);
 
       if (onscreen_xlib->pending_resize_notify)
         {
@@ -303,14 +291,12 @@ cogl_onscreen_xlib_resize (CoglOnscreen *onscreen,
                            int           width,
                            int           height)
 {
+  CoglOnscreenXlib *onscreen_xlib = COGL_ONSCREEN_XLIB (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *context = cogl_framebuffer_get_context (framebuffer);
   CoglRenderer *renderer = context->display->renderer;
   CoglRendererEGL *egl_renderer = renderer->winsys;
-  CoglOnscreenEgl *onscreen_egl;
-  CoglOnscreenXlib *onscreen_xlib;
 
-  onscreen_egl = cogl_onscreen_get_winsys (onscreen);
 
   _cogl_framebuffer_winsys_update_size (framebuffer, width, height);
 
@@ -326,6 +312,27 @@ cogl_onscreen_xlib_resize (CoglOnscreen *onscreen,
                                       NULL);
     }
 
-  onscreen_xlib = cogl_onscreen_egl_get_platform (onscreen_egl);
   onscreen_xlib->pending_resize_notify = TRUE;
 }
+
+CoglOnscreenXlib *
+cogl_onscreen_xlib_new (CoglContext *context,
+                        int          width,
+                        int          height)
+{
+  return g_object_new (COGL_TYPE_ONSCREEN_XLIB,
+                       "context", context,
+                       "width", width,
+                       "height", height,
+                       NULL);
+}
+
+static void
+cogl_onscreen_xlib_init (CoglOnscreenXlib *onscreen_xlib)
+{
+}
+
+static void
+cogl_onscreen_xlib_class_init (CoglOnscreenXlibClass *klass)
+{
+}
diff --git a/cogl/cogl/winsys/cogl-onscreen-xlib.h b/cogl/cogl/winsys/cogl-onscreen-xlib.h
index 41b234b950..a04ade6696 100644
--- a/cogl/cogl/winsys/cogl-onscreen-xlib.h
+++ b/cogl/cogl/winsys/cogl-onscreen-xlib.h
@@ -28,13 +28,24 @@
 #define COGL_ONSCREEN_XLIB_H
 
 #include "cogl-onscreen.h"
+#include "winsys/cogl-onscreen-egl.h"
 #include "winsys/cogl-winsys-egl-private.h"
 
+#define COGL_TYPE_ONSCREEN_XLIB (cogl_onscreen_xlib_get_type ())
+G_DECLARE_FINAL_TYPE (CoglOnscreenXlib, cogl_onscreen_xlib,
+                      COGL, ONSCREEN_XLIB,
+                      CoglOnscreenEgl)
+
 gboolean
 _cogl_winsys_egl_onscreen_xlib_init (CoglOnscreen  *onscreen,
                                      EGLConfig      egl_config,
                                      GError       **error);
 
+COGL_EXPORT CoglOnscreenXlib *
+cogl_onscreen_xlib_new (CoglContext *context,
+                        int          width,
+                        int          height);
+
 void
 _cogl_winsys_egl_onscreen_xlib_deinit (CoglOnscreen *onscreen);
 
diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c
index 19fa450c79..160cf71e52 100644
--- a/cogl/cogl/winsys/cogl-winsys-glx.c
+++ b/cogl/cogl/winsys/cogl-winsys-glx.c
@@ -162,15 +162,12 @@ find_onscreen_for_xid (CoglContext *context, uint32_t xid)
     {
       CoglFramebuffer *framebuffer = l->data;
       CoglOnscreen *onscreen;
-      CoglOnscreenGlx *onscreen_glx;
 
       if (!COGL_IS_ONSCREEN (framebuffer))
         continue;
 
       onscreen = COGL_ONSCREEN (framebuffer);
-      onscreen_glx = cogl_onscreen_get_winsys (onscreen);
-      if (onscreen_glx &&
-          cogl_onscreen_glx_is_for_window (onscreen, (Window) xid))
+      if (cogl_onscreen_glx_is_for_window (onscreen, (Window) xid))
         return onscreen;
     }
 
diff --git a/cogl/test-fixtures/test-utils.c b/cogl/test-fixtures/test-utils.c
index 597519d8f1..3e5552a9c9 100644
--- a/cogl/test-fixtures/test-utils.c
+++ b/cogl/test-fixtures/test-utils.c
@@ -5,6 +5,9 @@
 #include "test-unit.h"
 #include "test-utils.h"
 
+#include "cogl/winsys/cogl-onscreen-glx.h"
+#include "cogl/winsys/cogl-onscreen-xlib.h"
+
 #define FB_WIDTH 512
 #define FB_HEIGHT 512
 
@@ -77,6 +80,38 @@ is_boolean_env_set (const char *variable)
   return ret;
 }
 
+static CoglOnscreen *
+create_onscreen (CoglContext *cogl_context,
+                 int          width,
+                 int          height)
+{
+  CoglDisplay *display = cogl_context_get_display (test_ctx);
+  CoglRenderer *renderer = cogl_display_get_renderer (display);
+
+  switch (cogl_renderer_get_winsys_id (renderer))
+    {
+    case COGL_WINSYS_ID_GLX:
+#ifdef COGL_HAS_GLX_SUPPORT
+      return COGL_ONSCREEN (cogl_onscreen_glx_new (cogl_context,
+                                                   width, height));
+#else
+      g_assert_not_reached ();
+      break;
+#endif
+    case COGL_WINSYS_ID_EGL_XLIB:
+#ifdef COGL_HAS_EGL_SUPPORT
+      return COGL_ONSCREEN (cogl_onscreen_xlib_new (cogl_context,
+                                                    width, height));
+#else
+      g_assert_not_reached ();
+      break;
+#endif
+    default:
+      g_assert_not_reached ();
+      return NULL;
+    }
+}
+
 gboolean
 test_utils_init (TestFlags requirement_flags,
                  TestFlags known_failure_flags)
@@ -128,7 +163,7 @@ test_utils_init (TestFlags requirement_flags,
 
   if (is_boolean_env_set ("COGL_TEST_ONSCREEN"))
     {
-      onscreen = cogl_onscreen_new (test_ctx, 640, 480);
+      onscreen = create_onscreen (test_ctx, 640, 480);
       test_fb = COGL_FRAMEBUFFER (onscreen);
     }
   else
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
index d89dd0c08d..8f7b11d7c4 100644
--- a/src/backends/native/meta-onscreen-native.c
+++ b/src/backends/native/meta-onscreen-native.c
@@ -77,8 +77,10 @@ typedef struct _MetaOnscreenNativeSecondaryGpuState
   MetaSharedFramebufferImportStatus import_status;
 } MetaOnscreenNativeSecondaryGpuState;
 
-typedef struct _MetaOnscreenNative
+struct _MetaOnscreenNative
 {
+  CoglOnscreenEgl parent;
+
   MetaRendererNative *renderer_native;
   MetaGpuKms *render_gpu;
   MetaOutput *output;
@@ -101,14 +103,20 @@ typedef struct _MetaOnscreenNative
 #endif
 
   MetaRendererView *view;
-} MetaOnscreenNative;
+};
+
+G_DEFINE_TYPE (MetaOnscreenNative, meta_onscreen_native,
+               COGL_TYPE_ONSCREEN_EGL)
+
+static gboolean
+init_secondary_gpu_state (MetaRendererNative  *renderer_native,
+                          CoglOnscreen        *onscreen,
+                          GError             **error);
 
 static void
 swap_secondary_drm_fb (CoglOnscreen *onscreen)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
 
   secondary_gpu_state = onscreen_native->secondary_gpu_state;
@@ -123,9 +131,7 @@ swap_secondary_drm_fb (CoglOnscreen *onscreen)
 static void
 free_current_secondary_bo (CoglOnscreen *onscreen)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
 
   secondary_gpu_state = onscreen_native->secondary_gpu_state;
@@ -138,9 +144,7 @@ free_current_secondary_bo (CoglOnscreen *onscreen)
 static void
 free_current_bo (CoglOnscreen *onscreen)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
 
   g_clear_object (&onscreen_native->gbm.current_fb);
   free_current_secondary_bo (onscreen);
@@ -149,9 +153,7 @@ free_current_bo (CoglOnscreen *onscreen)
 static void
 meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
 
   if (!onscreen_native->gbm.next_fb)
     return;
@@ -211,9 +213,7 @@ notify_view_crtc_presented (MetaRendererView *view,
   CoglFramebuffer *framebuffer =
     clutter_stage_view_get_onscreen (stage_view);
   CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer);
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaRendererNative *renderer_native = onscreen_native->renderer_native;
   CoglFrameInfo *frame_info;
   MetaCrtc *crtc;
@@ -354,7 +354,8 @@ static int
 custom_egl_stream_page_flip (gpointer custom_page_flip_data,
                              gpointer user_data)
 {
-  MetaOnscreenNative *onscreen_native = custom_page_flip_data;
+  CoglOnscreen *onscreen = custom_page_flip_data;
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaRendererView *view = user_data;
   MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
   MetaRendererNativeGpuData *renderer_gpu_data;
@@ -407,9 +408,7 @@ meta_onscreen_native_flip_crtc (CoglOnscreen                *onscreen,
                                 MetaCrtc                    *crtc,
                                 MetaKmsPageFlipListenerFlag  flags)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaRendererNative *renderer_native = onscreen_native->renderer_native;
   MetaGpuKms *render_gpu = onscreen_native->render_gpu;
   MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc);
@@ -471,9 +470,7 @@ static void
 meta_onscreen_native_set_crtc_mode (CoglOnscreen              *onscreen,
                                     MetaRendererNativeGpuData *renderer_gpu_data)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc);
   MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
   MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);
@@ -545,9 +542,7 @@ static gboolean
 import_shared_framebuffer (CoglOnscreen                        *onscreen,
                            MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaGpuKms *gpu_kms;
   MetaKmsDevice *kms_device;
   struct gbm_device *gbm_device;
@@ -622,9 +617,7 @@ copy_shared_framebuffer_gpu (CoglOnscreen                        *onscreen,
                              MetaRendererNativeGpuData           *renderer_gpu_data,
                              gboolean                            *egl_context_changed)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
   MetaEgl *egl = meta_renderer_native_get_egl (renderer_native);
   MetaGles3 *gles3 = meta_renderer_native_get_gles3 (renderer_native);
@@ -715,9 +708,7 @@ copy_shared_framebuffer_primary_gpu (CoglOnscreen                        *onscre
                                      MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaRendererNative *renderer_native = onscreen_native->renderer_native;
   MetaGpuKms *primary_gpu;
   MetaRendererNativeGpuData *primary_gpu_data;
@@ -858,9 +849,7 @@ copy_shared_framebuffer_cpu (CoglOnscreen                        *onscreen,
 static void
 update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
 
   COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeGpuStatePreSwapBuffers,
@@ -914,9 +903,7 @@ static void
 update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen,
                                               gboolean     *egl_context_changed)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaRendererNative *renderer_native = onscreen_native->renderer_native;
   MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
 
@@ -955,9 +942,7 @@ retry:
 static void
 ensure_crtc_modes (CoglOnscreen *onscreen)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
   CoglRenderer *cogl_renderer = cogl_context->display->renderer;
@@ -990,9 +975,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen  *onscreen,
   MetaMonitorManager *monitor_manager =
     meta_backend_get_monitor_manager (backend);
   MetaKms *kms = meta_backend_native_get_kms (backend_native);
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaGpuKms *render_gpu = onscreen_native->render_gpu;
   MetaKmsDevice *render_kms_device = meta_gpu_kms_get_kms_device (render_gpu);
   ClutterFrame *frame = user_data;
@@ -1157,9 +1140,7 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen,
                                                    uint64_t      drm_modifier,
                                                    uint32_t      stride)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   const MetaCrtcConfig *crtc_config;
   MetaDrmBuffer *fb;
   struct gbm_bo *gbm_bo;
@@ -1203,9 +1184,7 @@ meta_onscreen_native_direct_scanout (CoglOnscreen   *onscreen,
                                      gpointer        user_data,
                                      GError        **error)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaGpuKms *render_gpu = onscreen_native->render_gpu;
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
@@ -1310,9 +1289,7 @@ void
 meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
                                    ClutterFrame *frame)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaCrtc *crtc = onscreen_native->crtc;
   MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
   MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);;
@@ -1364,9 +1341,7 @@ meta_onscreen_native_finish_frame (CoglOnscreen *onscreen,
 static gboolean
 should_surface_be_sharable (CoglOnscreen *onscreen)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
 
   if (META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)) ==
       onscreen_native->render_gpu)
@@ -1435,9 +1410,7 @@ get_supported_egl_modifiers (CoglOnscreen *onscreen,
                              MetaCrtcKms  *crtc_kms,
                              uint32_t      format)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaRendererNative *renderer_native = onscreen_native->renderer_native;
   MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
   MetaGpu *gpu;
@@ -1484,9 +1457,7 @@ static GArray *
 get_supported_modifiers (CoglOnscreen *onscreen,
                          uint32_t      format)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc);
   MetaGpu *gpu;
   g_autoptr (GArray) modifiers = NULL;
@@ -1503,9 +1474,7 @@ get_supported_modifiers (CoglOnscreen *onscreen,
 static GArray *
 get_supported_kms_formats (CoglOnscreen *onscreen)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc);
 
   return meta_crtc_kms_copy_drm_format_list (crtc_kms);
@@ -1519,9 +1488,7 @@ create_surfaces_gbm (CoglOnscreen        *onscreen,
                      EGLSurface          *egl_surface,
                      GError             **error)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaRendererNative *renderer_native = onscreen_native->renderer_native;
   MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@@ -1611,9 +1578,7 @@ create_surfaces_egl_device (CoglOnscreen  *onscreen,
                             GError       **error)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
   CoglDisplay *cogl_display = cogl_context->display;
   CoglDisplayEGL *cogl_display_egl = cogl_display->winsys;
@@ -1698,12 +1663,7 @@ void
 meta_onscreen_native_set_view (CoglOnscreen     *onscreen,
                                MetaRendererView *view)
 {
-  CoglOnscreenEgl *onscreen_egl;
-  MetaOnscreenNative *onscreen_native;
-
-  onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   onscreen_native->view = view;
 }
 
@@ -1711,30 +1671,70 @@ gboolean
 meta_renderer_native_init_onscreen (CoglOnscreen *onscreen,
                                     GError      **error)
 {
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
+  CoglOnscreenEgl *onscreen_egl = COGL_ONSCREEN_EGL (onscreen);
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
-  CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
-  CoglDisplay *cogl_display = cogl_context->display;
-  CoglDisplayEGL *cogl_display_egl = cogl_display->winsys;
-  CoglOnscreenEgl *onscreen_egl;
-  MetaOnscreenNative *onscreen_native;
+  MetaRendererNativeGpuData *renderer_gpu_data;
+  struct gbm_surface *gbm_surface;
+  EGLSurface egl_surface;
+  int width;
+  int height;
+#ifdef HAVE_EGL_DEVICE
+  MetaKmsDevice *render_kms_device;
+  EGLStreamKHR egl_stream;
+#endif
 
-  g_return_val_if_fail (cogl_display_egl->egl_context, FALSE);
+  if (META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)) !=
+      onscreen_native->render_gpu)
+    {
+      if (!init_secondary_gpu_state (onscreen_native->renderer_native,
+                                     onscreen, error))
+        return FALSE;
+    }
 
-  onscreen_egl = cogl_onscreen_egl_new ();
-  cogl_onscreen_set_winsys (onscreen, onscreen_egl);
+  width = cogl_framebuffer_get_width (framebuffer);
+  height = cogl_framebuffer_get_height (framebuffer);
 
-  onscreen_native = g_slice_new0 (MetaOnscreenNative);
-  cogl_onscreen_egl_set_platform (onscreen_egl, onscreen_native);
+  renderer_gpu_data =
+    meta_renderer_native_get_gpu_data (onscreen_native->renderer_native,
+                                       onscreen_native->render_gpu);
+  switch (renderer_gpu_data->mode)
+    {
+    case META_RENDERER_NATIVE_MODE_GBM:
+      if (!create_surfaces_gbm (onscreen,
+                                width, height,
+                                &gbm_surface,
+                                &egl_surface,
+                                error))
+        return FALSE;
 
-  /*
-   * Don't actually initialize anything here, since we may not have the
-   * information available yet, and there is no way to pass it at this stage.
-   * To properly allocate a MetaOnscreenNative, the caller must call
-   * meta_onscreen_native_allocate() after cogl_framebuffer_allocate().
-   *
-   * TODO: Turn CoglFramebuffer/CoglOnscreen into GObjects, so it's possible
-   * to add backend specific properties.
-   */
+      onscreen_native->gbm.surface = gbm_surface;
+      cogl_onscreen_egl_set_egl_surface (onscreen_egl, egl_surface);
+      break;
+#ifdef HAVE_EGL_DEVICE
+    case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
+      render_kms_device =
+        meta_gpu_kms_get_kms_device (onscreen_native->render_gpu);
+      onscreen_native->egl.dumb_fb =
+        meta_drm_buffer_dumb_new (render_kms_device,
+                                  width, height,
+                                  DRM_FORMAT_XRGB8888,
+                                  error);
+      if (!onscreen_native->egl.dumb_fb)
+        return FALSE;
+
+      if (!create_surfaces_egl_device (onscreen,
+                                       width, height,
+                                       &egl_stream,
+                                       &egl_surface,
+                                       error))
+        return FALSE;
+
+      onscreen_native->egl.stream = egl_stream;
+      cogl_onscreen_egl_set_egl_surface (onscreen_egl, egl_surface);
+      break;
+#endif /* HAVE_EGL_DEVICE */
+    }
 
   return TRUE;
 }
@@ -1746,9 +1746,7 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative         *renderer_nat
                                         GError                    **error)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
   int width, height;
   EGLNativeWindowType egl_native_window;
@@ -1870,9 +1868,7 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative         *renderer_nat
                                         GError                    **error)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
   MetaGpuKms *gpu_kms;
   MetaKmsDevice *kms_device;
@@ -1936,9 +1932,7 @@ init_secondary_gpu_state (MetaRendererNative  *renderer_native,
                           CoglOnscreen        *onscreen,
                           GError             **error)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
   MetaGpu *gpu = meta_crtc_get_gpu (onscreen_native->crtc);
   MetaRendererNativeGpuData *renderer_gpu_data;
 
@@ -1973,117 +1967,35 @@ init_secondary_gpu_state (MetaRendererNative  *renderer_native,
   return TRUE;
 }
 
-CoglOnscreen *
-meta_onscreen_native_new (MetaRendererNative   *renderer_native,
-                          MetaGpuKms           *render_gpu,
-                          MetaOutput           *output,
-                          MetaCrtc             *crtc,
-                          CoglContext          *context,
-                          int                   width,
-                          int                   height,
-                          GError              **error)
+MetaOnscreenNative *
+meta_onscreen_native_new (MetaRendererNative *renderer_native,
+                          MetaGpuKms         *render_gpu,
+                          MetaOutput         *output,
+                          MetaCrtc           *crtc,
+                          CoglContext        *cogl_context,
+                          int                 width,
+                          int                 height)
 {
-  CoglOnscreen *onscreen;
-  CoglOnscreenEgl *onscreen_egl;
   MetaOnscreenNative *onscreen_native;
 
-  onscreen = cogl_onscreen_new (context, width, height);
+  onscreen_native = g_object_new (META_TYPE_ONSCREEN_NATIVE,
+                                  "context", cogl_context,
+                                  "width", width,
+                                  "height", height,
+                                  NULL);
 
-  if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen), error))
-    {
-      g_object_unref (onscreen);
-      return NULL;
-    }
-
-  onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
   onscreen_native->renderer_native = renderer_native;
   onscreen_native->render_gpu = render_gpu;
   onscreen_native->output = output;
   onscreen_native->crtc = crtc;
 
-  if (META_GPU_KMS (meta_crtc_get_gpu (crtc)) != render_gpu)
-    {
-      if (!init_secondary_gpu_state (renderer_native, onscreen, error))
-        {
-          g_object_unref (onscreen);
-          return NULL;
-        }
-    }
-
-  return onscreen;
-}
-
-gboolean
-meta_onscreen_native_allocate (CoglOnscreen *onscreen,
-                               GError      **error)
-{
-  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
-  MetaRendererNativeGpuData *renderer_gpu_data;
-  struct gbm_surface *gbm_surface;
-  EGLSurface egl_surface;
-  int width;
-  int height;
-#ifdef HAVE_EGL_DEVICE
-  MetaKmsDevice *render_kms_device;
-  EGLStreamKHR egl_stream;
-#endif
-
-  width = cogl_framebuffer_get_width (framebuffer);
-  height = cogl_framebuffer_get_height (framebuffer);
-
-  renderer_gpu_data =
-    meta_renderer_native_get_gpu_data (onscreen_native->renderer_native,
-                                       onscreen_native->render_gpu);
-  switch (renderer_gpu_data->mode)
-    {
-    case META_RENDERER_NATIVE_MODE_GBM:
-      if (!create_surfaces_gbm (onscreen,
-                                width, height,
-                                &gbm_surface,
-                                &egl_surface,
-                                error))
-        return FALSE;
-
-      onscreen_native->gbm.surface = gbm_surface;
-      cogl_onscreen_egl_set_egl_surface (onscreen_egl, egl_surface);
-      break;
-#ifdef HAVE_EGL_DEVICE
-    case META_RENDERER_NATIVE_MODE_EGL_DEVICE:
-      render_kms_device =
-        meta_gpu_kms_get_kms_device (onscreen_native->render_gpu);
-      onscreen_native->egl.dumb_fb =
-        meta_drm_buffer_dumb_new (render_kms_device,
-                                  width, height,
-                                  DRM_FORMAT_XRGB8888,
-                                  error);
-      if (!onscreen_native->egl.dumb_fb)
-        return FALSE;
-
-      if (!create_surfaces_egl_device (onscreen,
-                                       width, height,
-                                       &egl_stream,
-                                       &egl_surface,
-                                       error))
-        return FALSE;
-
-      onscreen_native->egl.stream = egl_stream;
-      cogl_onscreen_egl_set_egl_surface (onscreen_egl, egl_surface);
-      break;
-#endif /* HAVE_EGL_DEVICE */
-    }
-
-  return TRUE;
+  return onscreen_native;
 }
 
 static void
 destroy_egl_surface (CoglOnscreen *onscreen)
 {
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
+  CoglOnscreenEgl *onscreen_egl = COGL_ONSCREEN_EGL (onscreen);
   EGLSurface egl_surface;
 
   egl_surface = cogl_onscreen_egl_get_egl_surface (onscreen_egl);
@@ -2112,19 +2024,12 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
   CoglContext *cogl_context = cogl_framebuffer_get_context (framebuffer);
   CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
   CoglDisplayEGL *cogl_display_egl = cogl_display->winsys;
-  CoglOnscreenEgl *onscreen_egl = cogl_onscreen_get_winsys (onscreen);
-  MetaOnscreenNative *onscreen_native;
-  MetaRendererNative *renderer_native;
+  CoglOnscreenEgl *onscreen_egl = COGL_ONSCREEN_EGL (onscreen);
+  MetaOnscreenNative *onscreen_native = META_ONSCREEN_NATIVE (onscreen);
+  MetaRendererNative *renderer_native = onscreen_native->renderer_native;
   MetaRendererNativeGpuData *renderer_gpu_data;
   EGLSurface egl_surface;
 
-  /* If we never successfully allocated then there's nothing to do */
-  if (onscreen_egl == NULL)
-    return;
-
-  onscreen_native =
-    cogl_onscreen_egl_get_platform (onscreen_egl);
-  renderer_native = onscreen_native->renderer_native;
 
   egl_surface = cogl_onscreen_egl_get_egl_surface (onscreen_egl);
   if (egl_surface != EGL_NO_SURFACE &&
@@ -2182,8 +2087,14 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
 
   g_clear_pointer (&onscreen_native->secondary_gpu_state,
                    secondary_gpu_state_free);
+}
 
-  g_slice_free (MetaOnscreenNative, onscreen_native);
-  cogl_onscreen_egl_free (cogl_onscreen_get_winsys (onscreen));
-  cogl_onscreen_set_winsys (onscreen, NULL);
+static void
+meta_onscreen_native_init (MetaOnscreenNative *onscreen_native)
+{
+}
+
+static void
+meta_onscreen_native_class_init (MetaOnscreenNativeClass *klass)
+{
 }
diff --git a/src/backends/native/meta-onscreen-native.h b/src/backends/native/meta-onscreen-native.h
index 10a3a610f9..f47355431a 100644
--- a/src/backends/native/meta-onscreen-native.h
+++ b/src/backends/native/meta-onscreen-native.h
@@ -28,15 +28,17 @@
 #include "clutter/clutter.h"
 #include "cogl/cogl.h"
 
+#define META_TYPE_ONSCREEN_NATIVE (meta_onscreen_native_get_type ())
+G_DECLARE_FINAL_TYPE (MetaOnscreenNative, meta_onscreen_native,
+                      META, ONSCREEN_NATIVE,
+                      CoglOnscreenEgl)
+
 gboolean
 meta_renderer_native_init_onscreen (CoglOnscreen *onscreen,
                                     GError      **error);
 
 void meta_renderer_native_release_onscreen (CoglOnscreen *onscreen);
 
-gboolean meta_onscreen_native_allocate (CoglOnscreen *onscreen,
-                                        GError      **error);
-
 void meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen  *onscreen,
                                                     const int     *rectangles,
                                                     int            n_rectangles,
@@ -57,13 +59,12 @@ void meta_onscreen_native_dummy_power_save_page_flip (CoglOnscreen *onscreen);
 void meta_onscreen_native_set_view (CoglOnscreen     *onscreen,
                                     MetaRendererView *view);
 
-CoglOnscreen * meta_onscreen_native_new (MetaRendererNative  *renderer_native,
-                                         MetaGpuKms          *render_gpu,
-                                         MetaOutput          *output,
-                                         MetaCrtc            *crtc,
-                                         CoglContext         *cogl_context,
-                                         int                  width,
-                                         int                  height,
-                                         GError             **error);
+MetaOnscreenNative * meta_onscreen_native_new (MetaRendererNative *renderer_native,
+                                               MetaGpuKms         *render_gpu,
+                                               MetaOutput         *output,
+                                               MetaCrtc           *crtc,
+                                               CoglContext        *cogl_context,
+                                               int                 width,
+                                               int                 height);
 
 #endif /* META_ONSCREEN_NATIVE_H */
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index 555bd413d0..c67dd0de13 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -1052,7 +1052,7 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
   const MetaCrtcConfig *crtc_config;
   const MetaCrtcModeInfo *crtc_mode_info;
   MetaMonitorTransform view_transform;
-  CoglOnscreen *onscreen = NULL;
+  MetaOnscreenNative *onscreen_native;
   CoglOffscreen *offscreen = NULL;
   gboolean use_shadowfb;
   float scale;
@@ -1068,15 +1068,15 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
   onscreen_width = crtc_mode_info->width;
   onscreen_height = crtc_mode_info->height;
 
-  onscreen = meta_onscreen_native_new (renderer_native,
-                                       renderer_native->primary_gpu_kms,
-                                       output,
-                                       crtc,
-                                       cogl_context,
-                                       onscreen_width,
-                                       onscreen_height,
-                                       &error);
-  if (!onscreen)
+  onscreen_native = meta_onscreen_native_new (renderer_native,
+                                              renderer_native->primary_gpu_kms,
+                                              output,
+                                              crtc,
+                                              cogl_context,
+                                              onscreen_width,
+                                              onscreen_height);
+
+  if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (onscreen_native), &error))
     g_error ("Failed to allocate onscreen framebuffer: %s", error->message);
 
   view_transform = calculate_view_transform (monitor_manager,
@@ -1125,30 +1125,20 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
                        "layout", &view_layout,
                        "crtc", crtc,
                        "scale", scale,
-                       "framebuffer", onscreen,
+                       "framebuffer", onscreen_native,
                        "offscreen", offscreen,
                        "use-shadowfb", use_shadowfb,
                        "transform", view_transform,
                        "refresh-rate", crtc_mode_info->refresh_rate,
                        NULL);
   g_clear_object (&offscreen);
+  g_object_unref (onscreen_native);
 
-  meta_onscreen_native_set_view (onscreen, view);
-
-  if (!meta_onscreen_native_allocate (onscreen, &error))
-    {
-      g_warning ("Could not create onscreen: %s", error->message);
-      g_object_unref (onscreen);
-      g_object_unref (view);
-      g_error_free (error);
-      return NULL;
-    }
-
-  g_object_unref (onscreen);
+  meta_onscreen_native_set_view (COGL_ONSCREEN (onscreen_native), view);
 
   /* Ensure we don't point to stale surfaces when creating the offscreen */
-  onscreen_egl = cogl_onscreen_get_winsys (onscreen);
   cogl_display_egl = cogl_display->winsys;
+  onscreen_egl = COGL_ONSCREEN_EGL (onscreen_native);
   egl_surface = cogl_onscreen_egl_get_egl_surface (onscreen_egl);
   _cogl_winsys_egl_make_current (cogl_display,
                                  egl_surface,
diff --git a/src/backends/x11/meta-stage-x11.c b/src/backends/x11/meta-stage-x11.c
index eadcc4fbbf..bc7e537604 100644
--- a/src/backends/x11/meta-stage-x11.c
+++ b/src/backends/x11/meta-stage-x11.c
@@ -36,6 +36,7 @@
 #include "clutter/clutter-mutter.h"
 #include "clutter/x11/clutter-x11.h"
 #include "clutter/x11/clutter-backend-x11.h"
+#include "cogl/cogl-mutter.h"
 #include "cogl/cogl.h"
 #include "core/display-private.h"
 #include "meta/main.h"
@@ -255,6 +256,38 @@ meta_stage_x11_unrealize (ClutterStageWindow *stage_window)
   g_clear_object (&stage_x11->onscreen);
 }
 
+static CoglOnscreen *
+create_onscreen (CoglContext *cogl_context,
+                 int          width,
+                 int          height)
+{
+  CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
+  CoglRenderer *cogl_renderer = cogl_display_get_renderer (cogl_display);
+
+  switch (cogl_renderer_get_winsys_id (cogl_renderer))
+    {
+    case COGL_WINSYS_ID_GLX:
+#ifdef COGL_HAS_GLX_SUPPORT
+      return COGL_ONSCREEN (cogl_onscreen_glx_new (cogl_context,
+                                                   width, height));
+#else
+      g_assert_not_reached ();
+      break;
+#endif
+    case COGL_WINSYS_ID_EGL_XLIB:
+#ifdef COGL_HAS_EGL_SUPPORT
+      return COGL_ONSCREEN (cogl_onscreen_xlib_new (cogl_context,
+                                                    width, height));
+#else
+      g_assert_not_reached ();
+      break;
+#endif
+    default:
+      g_assert_not_reached ();
+      return NULL;
+    }
+}
+
 static gboolean
 meta_stage_x11_realize (ClutterStageWindow *stage_window)
 {
@@ -268,7 +301,7 @@ meta_stage_x11_realize (ClutterStageWindow *stage_window)
 
   clutter_actor_get_size (CLUTTER_ACTOR (stage_cogl->wrapper), &width, &height);
 
-  stage_x11->onscreen = cogl_onscreen_new (backend->cogl_context, width, height);
+  stage_x11->onscreen = create_onscreen (backend->cogl_context, width, height);
 
   if (META_IS_BACKEND_X11_CM (stage_x11->backend))
     {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]