From bf7e6ae587adaf3321ed56ec407ed2d432805f57 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 17 Mar 2010 17:28:20 +0000 Subject: [PATCH] Add error reporting for create_context() failures MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We kind of assume that stuff will break well before during the ClutterBackend::create_context() implementation if we fail to create a GL context. We do, however, have error reporting in place inside the Backend API to catch those cases. Unfortunately, since we switched to lazy initialization of the Stage, there can be a case of GL context creation failure that still leads to a successful initialization - and a segmentation fault later on. This is clearly Not Good™. Let's try to catch a failure in all the places calling create_context() and report back to the user the error in a meaningful way, before crashing and burning. --- clutter/clutter-backend.c | 20 +++++++++++++++++++- clutter/clutter-feature.c | 11 +++++++---- clutter/clutter-main.c | 3 ++- clutter/clutter-private.h | 2 +- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/clutter/clutter-backend.c b/clutter/clutter-backend.c index 7c8233777..21b93f1b3 100644 --- a/clutter/clutter-backend.c +++ b/clutter/clutter-backend.c @@ -424,6 +424,7 @@ ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend) { ClutterBackendClass *klass; + GError *error; g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), 0); @@ -433,8 +434,25 @@ _clutter_backend_get_features (ClutterBackend *backend) * GL context first and the ask for features. if the * context already exists this should be a no-op */ + error = NULL; if (klass->create_context) - klass->create_context (backend, NULL); + { + gboolean res; + + res = klass->create_context (backend, &error); + if (!res) + { + if (error) + { + g_critical ("Unable to create a context: %s", error->message); + g_error_free (error); + } + else + g_critical ("Unable to create a context: unknown error"); + + return 0; + } + } if (klass->get_features) return klass->get_features (backend); diff --git a/clutter/clutter-feature.c b/clutter/clutter-feature.c index 4db690e55..74bf87ba0 100644 --- a/clutter/clutter-feature.c +++ b/clutter/clutter-feature.c @@ -83,8 +83,8 @@ _clutter_features_from_cogl (guint cogl_flags) return clutter_flags; } -void -_clutter_feature_init (void) +gboolean +_clutter_feature_init (GError **error) { ClutterMainContext *context; @@ -98,12 +98,13 @@ _clutter_feature_init (void) } if (__features->features_set) - return; + return TRUE; context = _clutter_context_get_default (); /* makes sure we have a GL context; if we have, this is a no-op */ - _clutter_backend_create_context (context->backend, NULL); + if (!_clutter_backend_create_context (context->backend, error)) + return FALSE; __features->flags = (_clutter_features_from_cogl (cogl_get_features ()) | _clutter_backend_get_features (context->backend)); @@ -111,6 +112,8 @@ _clutter_feature_init (void) __features->features_set = TRUE; CLUTTER_NOTE (MISC, "features checked"); + + return TRUE; } /** diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 053b6fc56..fcfa33b90 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -1534,7 +1534,8 @@ clutter_init_real (GError **error) /* this will take care of initializing Cogl's state and * query the GL machinery for features */ - _clutter_feature_init (); + if (!_clutter_feature_init (error)) + return CLUTTER_INIT_ERROR_BACKEND; #ifdef CLUTTER_ENABLE_PROFILE { diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h index b26771a20..bf06563fd 100644 --- a/clutter/clutter-private.h +++ b/clutter/clutter-private.h @@ -270,7 +270,7 @@ ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend); gfloat _clutter_backend_get_units_per_em (ClutterBackend *backend, PangoFontDescription *font_desc); -void _clutter_feature_init (void); +gboolean _clutter_feature_init (GError **error); /* Reinjecting queued events for processing */ void _clutter_process_event (ClutterEvent *event);