MetaOnscreenNative: Allocate for real after cogl_framebuffer_allocate

There is no way to pass any backend specific parameters to a
CoglFramebuffer until after it has been allocated by
cogl_framebuffer_allocate() (since this is where the winsys/platform
fields are initialized). This can make it hard to actually allocate
anything, if the platform depends on some backend specific data.

A proper solution would be to refactor the onscreens and framebuffers to
use a GObject based type system instead of the home baked Cogl one, but
that'll be left for another day. For now, allocate in two steps, one to
allocate the backend specific parts (MetaOnscreenNative), and one to
allocate the actual onscreen framebuffer (via
meta_onscreen_native_allocate()).

So far there is nothing that forces this separation, but in the future
there will, for example EGLDevice's need to know about the CRTC in
order to create the EGLSurface.

https://bugzilla.gnome.org/show_bug.cgi?id=773629
This commit is contained in:
Jonas Ådahl 2016-09-29 22:46:34 +08:00
parent faa96444b5
commit b1597b4291

View File

@ -757,15 +757,8 @@ meta_renderer_native_init_onscreen (CoglOnscreen *onscreen,
CoglContext *cogl_context = framebuffer->context; CoglContext *cogl_context = framebuffer->context;
CoglDisplay *cogl_display = cogl_context->display; CoglDisplay *cogl_display = cogl_context->display;
CoglDisplayEGL *egl_display = cogl_display->winsys; CoglDisplayEGL *egl_display = cogl_display->winsys;
CoglRenderer *cogl_renderer = cogl_display->renderer;
CoglRendererEGL *egl_renderer = cogl_renderer->winsys;
MetaRendererNative *renderer_native = egl_renderer->platform;
CoglOnscreenEGL *egl_onscreen; CoglOnscreenEGL *egl_onscreen;
MetaOnscreenNative *onscreen_native; MetaOnscreenNative *onscreen_native;
struct gbm_surface *gbm_surface;
EGLSurface egl_surface;
int width;
int height;
_COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE); _COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE);
@ -775,6 +768,36 @@ meta_renderer_native_init_onscreen (CoglOnscreen *onscreen,
onscreen_native = g_slice_new0 (MetaOnscreenNative); onscreen_native = g_slice_new0 (MetaOnscreenNative);
egl_onscreen->platform = onscreen_native; egl_onscreen->platform = onscreen_native;
/*
* 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.
*/
return TRUE;
}
static gboolean
meta_onscreen_native_allocate (CoglOnscreen *onscreen,
GError **error)
{
CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
CoglContext *cogl_context = framebuffer->context;
CoglDisplay *cogl_display = cogl_context->display;
CoglRenderer *cogl_renderer = cogl_display->renderer;
CoglRendererEGL *egl_renderer = cogl_renderer->winsys;
MetaRendererNative *renderer_native = egl_renderer->platform;
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
MetaOnscreenNative *onscreen_native = egl_onscreen->platform;
struct gbm_surface *gbm_surface;
EGLSurface egl_surface;
int width;
int height;
onscreen_native->pending_set_crtc = TRUE; onscreen_native->pending_set_crtc = TRUE;
/* If a kms_fd is set then the display width and height /* If a kms_fd is set then the display width and height
@ -1129,6 +1152,7 @@ meta_renderer_native_create_legacy_view (MetaRendererNative *renderer_native)
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
cairo_rectangle_int_t view_layout = { 0 }; cairo_rectangle_int_t view_layout = { 0 };
MetaRendererView *view; MetaRendererView *view;
GError *error = NULL;
if (!monitor_manager) if (!monitor_manager)
return NULL; return NULL;
@ -1150,10 +1174,20 @@ meta_renderer_native_create_legacy_view (MetaRendererNative *renderer_native)
"layout", &view_layout, "layout", &view_layout,
"framebuffer", onscreen, "framebuffer", onscreen,
NULL); NULL);
cogl_object_unref (onscreen);
meta_onscreen_native_set_view (onscreen, view); meta_onscreen_native_set_view (onscreen, view);
if (!meta_onscreen_native_allocate (onscreen, &error))
{
g_warning ("Could not create onscreen: %s", error->message);
cogl_object_unref (onscreen);
g_object_unref (view);
g_error_free (error);
return NULL;
}
cogl_object_unref (onscreen);
return view; return view;
} }
@ -1171,6 +1205,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
CoglOnscreen *onscreen = NULL; CoglOnscreen *onscreen = NULL;
CoglOffscreen *offscreen = NULL; CoglOffscreen *offscreen = NULL;
MetaRendererView *view; MetaRendererView *view;
GError *error = NULL;
transform = meta_renderer_native_get_monitor_info_transform (renderer, transform = meta_renderer_native_get_monitor_info_transform (renderer,
monitor_info); monitor_info);
@ -1183,13 +1218,6 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
if (!onscreen) if (!onscreen)
meta_fatal ("Failed to allocate onscreen framebuffer\n"); meta_fatal ("Failed to allocate onscreen framebuffer\n");
/* Ensure we don't point to stale surfaces when creating the offscreen */
egl_onscreen = onscreen->winsys;
_cogl_winsys_egl_make_current (cogl_display,
egl_onscreen->egl_surface,
egl_onscreen->egl_surface,
egl_display->egl_context);
if (transform != META_MONITOR_TRANSFORM_NORMAL) if (transform != META_MONITOR_TRANSFORM_NORMAL)
{ {
offscreen = meta_renderer_native_create_offscreen (META_RENDERER_NATIVE (renderer), offscreen = meta_renderer_native_create_offscreen (META_RENDERER_NATIVE (renderer),
@ -1208,11 +1236,28 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
"monitor-info", monitor_info, "monitor-info", monitor_info,
"transform", transform, "transform", transform,
NULL); NULL);
cogl_object_unref (onscreen);
g_clear_pointer (&offscreen, cogl_object_unref); g_clear_pointer (&offscreen, cogl_object_unref);
meta_onscreen_native_set_view (onscreen, view); meta_onscreen_native_set_view (onscreen, view);
if (!meta_onscreen_native_allocate (onscreen, &error))
{
g_warning ("Could not create onscreen: %s", error->message);
cogl_object_unref (onscreen);
g_object_unref (view);
g_error_free (error);
return NULL;
}
cogl_object_unref (onscreen);
/* Ensure we don't point to stale surfaces when creating the offscreen */
egl_onscreen = onscreen->winsys;
_cogl_winsys_egl_make_current (cogl_display,
egl_onscreen->egl_surface,
egl_onscreen->egl_surface,
egl_display->egl_context);
return view; return view;
} }