mirror of
https://github.com/brl/mutter.git
synced 2024-12-22 11:02:05 +00:00
2006-12-04 Emmanuele Bassi <ebassi@openedhand.com>
Avoid clutter segfaulting when used without invoking clutter_init(). This is needed when using api documentation tools and every other tool relying on the GObject introspection API (esp. on a headless box). see the note in clutter/clutter-feature.c:clutter_feature_init for a full explanation. * clutter/clutter-feature.c: Call clutter_feature_init() when needed by one of the accessors of the features structure. * clutter/clutter-main.c: * clutter/clutter-private.h: Remove clutter_feature_init() public declaration: the features support check is done the first time a feature is needed. * clutter/clutter-main.c: Do not ever access the clutter main context pointer directly; instead, obtain a pointer to it via clutter_context_get_default(), which will always return something valid.
This commit is contained in:
parent
f83ffa3520
commit
6d87b1479c
23
ChangeLog
23
ChangeLog
@ -1,3 +1,26 @@
|
|||||||
|
2006-12-04 Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
|
||||||
|
Avoid clutter segfaulting when used without invoking
|
||||||
|
clutter_init(). This is needed when using api documentation
|
||||||
|
tools and every other tool relying on the GObject
|
||||||
|
introspection API (esp. on a headless box). see the
|
||||||
|
note in clutter/clutter-feature.c:clutter_feature_init
|
||||||
|
for a full explanation.
|
||||||
|
|
||||||
|
* clutter/clutter-feature.c: Call clutter_feature_init()
|
||||||
|
when needed by one of the accessors of the features
|
||||||
|
structure.
|
||||||
|
|
||||||
|
* clutter/clutter-main.c:
|
||||||
|
* clutter/clutter-private.h: Remove clutter_feature_init()
|
||||||
|
public declaration: the features support check is done the
|
||||||
|
first time a feature is needed.
|
||||||
|
|
||||||
|
* clutter/clutter-main.c: Do not ever access the clutter
|
||||||
|
main context pointer directly; instead, obtain a pointer
|
||||||
|
to it via clutter_context_get_default(), which will always
|
||||||
|
return something valid.
|
||||||
|
|
||||||
2006-12-04 Emmanuele Bassi <ebassi@openedhand.com>
|
2006-12-04 Emmanuele Bassi <ebassi@openedhand.com>
|
||||||
|
|
||||||
* clutter/clutter-private.h: Add our own READABLE,
|
* clutter/clutter-private.h: Add our own READABLE,
|
||||||
|
@ -76,9 +76,11 @@ typedef struct ClutterFeatures
|
|||||||
gint dri_fd;
|
gint dri_fd;
|
||||||
ClutterVBlankType vblank_type;
|
ClutterVBlankType vblank_type;
|
||||||
|
|
||||||
|
guint features_set : 1;
|
||||||
} ClutterFeatures;
|
} ClutterFeatures;
|
||||||
|
|
||||||
static ClutterFeatures* __features = NULL;
|
static ClutterFeatures* __features = NULL;
|
||||||
|
G_LOCK_DEFINE_STATIC (__features);
|
||||||
|
|
||||||
/* #ifdef linux */
|
/* #ifdef linux */
|
||||||
#define DRM_VBLANK_RELATIVE 0x1;
|
#define DRM_VBLANK_RELATIVE 0x1;
|
||||||
@ -125,10 +127,11 @@ static int drm_wait_vblank(int fd, drm_wait_vblank_t *vbl)
|
|||||||
|
|
||||||
/* Note must be called after context created */
|
/* Note must be called after context created */
|
||||||
static gboolean
|
static gboolean
|
||||||
check_gl_extension (const gchar *name, const gchar *ext)
|
check_gl_extension (const gchar *name,
|
||||||
|
const gchar *ext)
|
||||||
{
|
{
|
||||||
gchar *end;
|
gchar *end;
|
||||||
gint name_len, n;
|
gint name_len, n;
|
||||||
|
|
||||||
if (name == NULL || ext == NULL)
|
if (name == NULL || ext == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -162,22 +165,27 @@ get_proc_address (const gchar *name)
|
|||||||
if (dlhand)
|
if (dlhand)
|
||||||
{
|
{
|
||||||
dlerror ();
|
dlerror ();
|
||||||
get_proc_func
|
|
||||||
= (GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress");
|
get_proc_func =
|
||||||
|
(GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress");
|
||||||
|
|
||||||
if (dlerror () != NULL)
|
if (dlerror () != NULL)
|
||||||
get_proc_func
|
{
|
||||||
= (GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddressARB");
|
get_proc_func =
|
||||||
|
(GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddressARB");
|
||||||
|
}
|
||||||
|
|
||||||
if (dlerror () != NULL)
|
if (dlerror () != NULL)
|
||||||
{
|
{
|
||||||
get_proc_func = NULL;
|
get_proc_func = NULL;
|
||||||
g_warning
|
g_warning ("failed to bind GLXGetProcAddress "
|
||||||
("failed to bind GLXGetProcAddress or GLXGetProcAddressARB");
|
"or GLXGetProcAddressARB");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_proc_func)
|
if (get_proc_func)
|
||||||
return get_proc_func ((unsigned char*)name);
|
return get_proc_func ((unsigned char*) name);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -196,25 +204,54 @@ check_vblank_env (const char *name)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/* clutter_feature_init:
|
||||||
|
* must be called with the static lock on __features held, to keep it
|
||||||
|
* mt-safe.
|
||||||
|
*
|
||||||
|
* XXX - here we need a bit of weird machinery in place. the features
|
||||||
|
* are checked at run time, each time we try to access them - unless
|
||||||
|
* we already checked them once. unfortunately, we need an open
|
||||||
|
* X display if we want to check them, so ideally we'd need to call
|
||||||
|
* clutter_init() before checking for any feature. the generator for
|
||||||
|
* the api documentation, and more in general every tool relying on the
|
||||||
|
* introspection API provided by GObject, may well not be able to call
|
||||||
|
* clutter_init() (and neither they should be, as we might be running
|
||||||
|
* them on a headless build box). so, we need a way to get the features
|
||||||
|
* without explicitely calling clutter_feature_init() inside clutter_init()
|
||||||
|
* and we also need to have an open X display when we test for the features.
|
||||||
|
* __features is dynamically allocated, and applications tend to badly
|
||||||
|
* crash when trying to access __features; so when can't use a NULL check
|
||||||
|
* to know whether we already invoked clutter_feature_init() once; hence,
|
||||||
|
* we must allocate it anyway, and have a flag to let us know when the
|
||||||
|
* features have been set - that is when clutter_feature_init() has been
|
||||||
|
* successfully completed with an open X display.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
clutter_feature_init (void)
|
clutter_feature_init (void)
|
||||||
{
|
{
|
||||||
const gchar *gl_extensions, *glx_extensions;
|
const gchar *gl_extensions, *glx_extensions;
|
||||||
|
|
||||||
|
CLUTTER_NOTE (MISC, "checking features");
|
||||||
|
|
||||||
if (__features != NULL)
|
if (!__features)
|
||||||
{
|
{
|
||||||
g_warning ("You should never call clutter_feature_init() "
|
CLUTTER_NOTE (MISC, "allocating features data");
|
||||||
"more than once.");
|
|
||||||
return;
|
__features = g_new0 (ClutterFeatures, 1);
|
||||||
|
memset(&__features->funcs, 0, sizeof(ClutterFeatureFuncs));
|
||||||
|
__features->features_set = FALSE; /* don't rely on zero-ing */
|
||||||
}
|
}
|
||||||
|
|
||||||
__features = g_new0 (ClutterFeatures, 1);
|
if (!clutter_xdisplay ())
|
||||||
memset(&__features->funcs, 0, sizeof(ClutterFeatureFuncs));
|
return;
|
||||||
|
|
||||||
gl_extensions = (const gchar*)glGetString(GL_EXTENSIONS);
|
if (__features->features_set)
|
||||||
glx_extensions = glXQueryExtensionsString (clutter_xdisplay(),
|
return;
|
||||||
clutter_xscreen());
|
|
||||||
|
|
||||||
|
gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS);
|
||||||
|
glx_extensions = glXQueryExtensionsString (clutter_xdisplay (),
|
||||||
|
clutter_xscreen ());
|
||||||
|
|
||||||
if (check_gl_extension ("GL_ARB_texture_rectangle", gl_extensions))
|
if (check_gl_extension ("GL_ARB_texture_rectangle", gl_extensions))
|
||||||
__features->flags |= CLUTTER_FEATURE_TEXTURE_RECTANGLE;
|
__features->flags |= CLUTTER_FEATURE_TEXTURE_RECTANGLE;
|
||||||
|
|
||||||
@ -228,8 +265,8 @@ clutter_feature_init (void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!check_vblank_env("dri")
|
if (!check_vblank_env("dri") &&
|
||||||
&& check_gl_extension ("GLX_SGI_video_sync", glx_extensions))
|
check_gl_extension ("GLX_SGI_video_sync", glx_extensions))
|
||||||
{
|
{
|
||||||
__features->funcs.get_video_sync =
|
__features->funcs.get_video_sync =
|
||||||
(GLXGetVideoSyncProc) get_proc_address ("glXGetVideoSyncSGI");
|
(GLXGetVideoSyncProc) get_proc_address ("glXGetVideoSyncSGI");
|
||||||
@ -237,8 +274,8 @@ clutter_feature_init (void)
|
|||||||
__features->funcs.wait_video_sync =
|
__features->funcs.wait_video_sync =
|
||||||
(GLXWaitVideoSyncProc) get_proc_address ("glXWaitVideoSyncSGI");
|
(GLXWaitVideoSyncProc) get_proc_address ("glXWaitVideoSyncSGI");
|
||||||
|
|
||||||
if (__features->funcs.get_video_sync != NULL
|
if ((__features->funcs.get_video_sync != NULL) &&
|
||||||
&& __features->funcs.wait_video_sync != NULL)
|
(__features->funcs.wait_video_sync != NULL))
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (MISC, "vblank sync: using glx");
|
CLUTTER_NOTE (MISC, "vblank sync: using glx");
|
||||||
|
|
||||||
@ -265,6 +302,18 @@ clutter_feature_init (void)
|
|||||||
"vblank sync: no use-able mechanism found");
|
"vblank sync: no use-able mechanism found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLUTTER_NOTE (MISC, "features checked");
|
||||||
|
|
||||||
|
__features->features_set = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_feature_do_init (void)
|
||||||
|
{
|
||||||
|
G_LOCK (__features);
|
||||||
|
clutter_feature_init ();
|
||||||
|
G_UNLOCK (__features);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -281,13 +330,15 @@ clutter_feature_init (void)
|
|||||||
gboolean
|
gboolean
|
||||||
clutter_feature_available (ClutterFeatureFlags feature)
|
clutter_feature_available (ClutterFeatureFlags feature)
|
||||||
{
|
{
|
||||||
|
clutter_feature_do_init ();
|
||||||
|
|
||||||
return (__features->flags & feature);
|
return (__features->flags & feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_feature_get_all:
|
* clutter_feature_get_all:
|
||||||
*
|
*
|
||||||
* Returns all the suppoerted features.
|
* Returns all the supported features.
|
||||||
*
|
*
|
||||||
* Return value: a logical OR of all the supported features.
|
* Return value: a logical OR of all the supported features.
|
||||||
*
|
*
|
||||||
@ -296,6 +347,8 @@ clutter_feature_available (ClutterFeatureFlags feature)
|
|||||||
ClutterFeatureFlags
|
ClutterFeatureFlags
|
||||||
clutter_feature_get_all (void)
|
clutter_feature_get_all (void)
|
||||||
{
|
{
|
||||||
|
clutter_feature_do_init ();
|
||||||
|
|
||||||
return __features->flags;
|
return __features->flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,14 +362,17 @@ clutter_feature_get_all (void)
|
|||||||
void
|
void
|
||||||
clutter_feature_wait_for_vblank (void)
|
clutter_feature_wait_for_vblank (void)
|
||||||
{
|
{
|
||||||
|
clutter_feature_do_init ();
|
||||||
|
|
||||||
switch (__features->vblank_type)
|
switch (__features->vblank_type)
|
||||||
{
|
{
|
||||||
case CLUTTER_VBLANK_GLX:
|
case CLUTTER_VBLANK_GLX:
|
||||||
{
|
{
|
||||||
unsigned int retraceCount;
|
unsigned int retraceCount;
|
||||||
__features->funcs.get_video_sync(&retraceCount);
|
__features->funcs.get_video_sync (&retraceCount);
|
||||||
__features->funcs.wait_video_sync(2,
|
__features->funcs.wait_video_sync (2,
|
||||||
(retraceCount+1)%2, &retraceCount);
|
(retraceCount + 1) % 2,
|
||||||
|
&retraceCount);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CLUTTER_VBLANK_DRI:
|
case CLUTTER_VBLANK_DRI:
|
||||||
|
@ -235,16 +235,18 @@ clutter_dispatch_x_event (XEvent *xevent,
|
|||||||
static void
|
static void
|
||||||
events_init()
|
events_init()
|
||||||
{
|
{
|
||||||
|
ClutterMainContext *clutter_context;
|
||||||
GMainContext *gmain_context;
|
GMainContext *gmain_context;
|
||||||
int connection_number;
|
int connection_number;
|
||||||
GSource *source;
|
GSource *source;
|
||||||
ClutterXEventSource *display_source;
|
ClutterXEventSource *display_source;
|
||||||
|
|
||||||
|
clutter_context = clutter_context_get_default ();
|
||||||
gmain_context = g_main_context_default ();
|
gmain_context = g_main_context_default ();
|
||||||
|
|
||||||
g_main_context_ref (gmain_context);
|
g_main_context_ref (gmain_context);
|
||||||
|
|
||||||
connection_number = ConnectionNumber (ClutterCntx->xdpy);
|
connection_number = ConnectionNumber (clutter_context->xdpy);
|
||||||
|
|
||||||
source = g_source_new ((GSourceFuncs *)&x_event_funcs,
|
source = g_source_new ((GSourceFuncs *)&x_event_funcs,
|
||||||
sizeof (ClutterXEventSource));
|
sizeof (ClutterXEventSource));
|
||||||
@ -253,7 +255,7 @@ events_init()
|
|||||||
|
|
||||||
display_source->event_poll_fd.fd = connection_number;
|
display_source->event_poll_fd.fd = connection_number;
|
||||||
display_source->event_poll_fd.events = G_IO_IN;
|
display_source->event_poll_fd.events = G_IO_IN;
|
||||||
display_source->display = ClutterCntx->xdpy;
|
display_source->display = clutter_context->xdpy;
|
||||||
|
|
||||||
g_source_add_poll (source, &display_source->event_poll_fd);
|
g_source_add_poll (source, &display_source->event_poll_fd);
|
||||||
g_source_set_can_recurse (source, TRUE);
|
g_source_set_can_recurse (source, TRUE);
|
||||||
@ -444,7 +446,9 @@ clutter_threads_leave (void)
|
|||||||
Display*
|
Display*
|
||||||
clutter_xdisplay (void)
|
clutter_xdisplay (void)
|
||||||
{
|
{
|
||||||
return ClutterCntx->xdpy;
|
ClutterMainContext *context = CLUTTER_CONTEXT ();
|
||||||
|
|
||||||
|
return context->xdpy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -457,7 +461,9 @@ clutter_xdisplay (void)
|
|||||||
int
|
int
|
||||||
clutter_xscreen (void)
|
clutter_xscreen (void)
|
||||||
{
|
{
|
||||||
return ClutterCntx->xscreen;
|
ClutterMainContext *context = CLUTTER_CONTEXT ();
|
||||||
|
|
||||||
|
return context->xscreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -470,7 +476,9 @@ clutter_xscreen (void)
|
|||||||
Window
|
Window
|
||||||
clutter_root_xwindow (void)
|
clutter_root_xwindow (void)
|
||||||
{
|
{
|
||||||
return ClutterCntx->xwin_root;
|
ClutterMainContext *context = CLUTTER_CONTEXT ();
|
||||||
|
|
||||||
|
return context->xwin_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -867,9 +875,6 @@ clutter_init_with_args (int *argc,
|
|||||||
return CLUTTER_INIT_ERROR_OPENGL;
|
return CLUTTER_INIT_ERROR_OPENGL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check available features */
|
|
||||||
clutter_feature_init ();
|
|
||||||
|
|
||||||
events_init ();
|
events_init ();
|
||||||
|
|
||||||
return CLUTTER_INIT_SUCCESS;
|
return CLUTTER_INIT_SUCCESS;
|
||||||
@ -927,9 +932,6 @@ clutter_init (int *argc,
|
|||||||
return CLUTTER_INIT_ERROR_OPENGL;
|
return CLUTTER_INIT_ERROR_OPENGL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check available features */
|
|
||||||
clutter_feature_init ();
|
|
||||||
|
|
||||||
events_init ();
|
events_init ();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -83,8 +83,6 @@ typedef enum {
|
|||||||
#define CLUTTER_SET_PRIVATE_FLAGS(a,f) G_STMT_START{ (CLUTTER_PRIVATE_FLAGS (a) |= (f)); }G_STMT_END
|
#define CLUTTER_SET_PRIVATE_FLAGS(a,f) G_STMT_START{ (CLUTTER_PRIVATE_FLAGS (a) |= (f)); }G_STMT_END
|
||||||
#define CLUTTER_UNSET_PRIVATE_FLAGS(a,f) G_STMT_START{ (CLUTTER_PRIVATE_FLAGS (a) &= ~(f)); }G_STMT_END
|
#define CLUTTER_UNSET_PRIVATE_FLAGS(a,f) G_STMT_START{ (CLUTTER_PRIVATE_FLAGS (a) &= ~(f)); }G_STMT_END
|
||||||
|
|
||||||
void clutter_feature_init (void);
|
|
||||||
|
|
||||||
#define CLUTTER_PARAM_READABLE \
|
#define CLUTTER_PARAM_READABLE \
|
||||||
G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB
|
G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB
|
||||||
#define CLUTTER_PARAM_WRITABLE \
|
#define CLUTTER_PARAM_WRITABLE \
|
||||||
|
@ -21,7 +21,7 @@ DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
|
|||||||
DOC_SOURCE_DIR=../../clutter
|
DOC_SOURCE_DIR=../../clutter
|
||||||
|
|
||||||
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
|
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
|
||||||
SCANGOBJ_OPTIONS=--type-init-func="clutter_init(0,0)"
|
SCANGOBJ_OPTIONS=
|
||||||
|
|
||||||
# Extra options to supply to gtkdoc-scan.
|
# Extra options to supply to gtkdoc-scan.
|
||||||
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
|
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
|
||||||
|
@ -23,6 +23,21 @@ ClutterBehaviourScale
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ##### ARG ClutterBehaviourScale:scale-begin ##### -->
|
||||||
|
<para>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<!-- ##### ARG ClutterBehaviourScale:scale-end ##### -->
|
||||||
|
<para>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<!-- ##### ARG ClutterBehaviourScale:scale-gravity ##### -->
|
||||||
|
<para>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
|
||||||
<!-- ##### STRUCT ClutterBehaviourScaleClass ##### -->
|
<!-- ##### STRUCT ClutterBehaviourScaleClass ##### -->
|
||||||
<para>
|
<para>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user