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>
|
||||
|
||||
* clutter/clutter-private.h: Add our own READABLE,
|
||||
|
@ -76,9 +76,11 @@ typedef struct ClutterFeatures
|
||||
gint dri_fd;
|
||||
ClutterVBlankType vblank_type;
|
||||
|
||||
guint features_set : 1;
|
||||
} ClutterFeatures;
|
||||
|
||||
static ClutterFeatures* __features = NULL;
|
||||
G_LOCK_DEFINE_STATIC (__features);
|
||||
|
||||
/* #ifdef linux */
|
||||
#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 */
|
||||
static gboolean
|
||||
check_gl_extension (const gchar *name, const gchar *ext)
|
||||
check_gl_extension (const gchar *name,
|
||||
const gchar *ext)
|
||||
{
|
||||
gchar *end;
|
||||
gint name_len, n;
|
||||
gchar *end;
|
||||
gint name_len, n;
|
||||
|
||||
if (name == NULL || ext == NULL)
|
||||
return FALSE;
|
||||
@ -162,22 +165,27 @@ get_proc_address (const gchar *name)
|
||||
if (dlhand)
|
||||
{
|
||||
dlerror ();
|
||||
get_proc_func
|
||||
= (GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress");
|
||||
|
||||
get_proc_func =
|
||||
(GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress");
|
||||
|
||||
if (dlerror () != NULL)
|
||||
get_proc_func
|
||||
= (GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddressARB");
|
||||
{
|
||||
get_proc_func =
|
||||
(GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddressARB");
|
||||
}
|
||||
|
||||
if (dlerror () != NULL)
|
||||
{
|
||||
get_proc_func = NULL;
|
||||
g_warning
|
||||
("failed to bind GLXGetProcAddress or GLXGetProcAddressARB");
|
||||
g_warning ("failed to bind GLXGetProcAddress "
|
||||
"or GLXGetProcAddressARB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (get_proc_func)
|
||||
return get_proc_func ((unsigned char*)name);
|
||||
return get_proc_func ((unsigned char*) name);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@ -196,25 +204,54 @@ check_vblank_env (const char *name)
|
||||
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)
|
||||
{
|
||||
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() "
|
||||
"more than once.");
|
||||
return;
|
||||
CLUTTER_NOTE (MISC, "allocating features data");
|
||||
|
||||
__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);
|
||||
memset(&__features->funcs, 0, sizeof(ClutterFeatureFuncs));
|
||||
if (!clutter_xdisplay ())
|
||||
return;
|
||||
|
||||
gl_extensions = (const gchar*)glGetString(GL_EXTENSIONS);
|
||||
glx_extensions = glXQueryExtensionsString (clutter_xdisplay(),
|
||||
clutter_xscreen());
|
||||
if (__features->features_set)
|
||||
return;
|
||||
|
||||
gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS);
|
||||
glx_extensions = glXQueryExtensionsString (clutter_xdisplay (),
|
||||
clutter_xscreen ());
|
||||
|
||||
if (check_gl_extension ("GL_ARB_texture_rectangle", gl_extensions))
|
||||
__features->flags |= CLUTTER_FEATURE_TEXTURE_RECTANGLE;
|
||||
|
||||
@ -228,8 +265,8 @@ clutter_feature_init (void)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!check_vblank_env("dri")
|
||||
&& check_gl_extension ("GLX_SGI_video_sync", glx_extensions))
|
||||
if (!check_vblank_env("dri") &&
|
||||
check_gl_extension ("GLX_SGI_video_sync", glx_extensions))
|
||||
{
|
||||
__features->funcs.get_video_sync =
|
||||
(GLXGetVideoSyncProc) get_proc_address ("glXGetVideoSyncSGI");
|
||||
@ -237,8 +274,8 @@ clutter_feature_init (void)
|
||||
__features->funcs.wait_video_sync =
|
||||
(GLXWaitVideoSyncProc) get_proc_address ("glXWaitVideoSyncSGI");
|
||||
|
||||
if (__features->funcs.get_video_sync != NULL
|
||||
&& __features->funcs.wait_video_sync != NULL)
|
||||
if ((__features->funcs.get_video_sync != NULL) &&
|
||||
(__features->funcs.wait_video_sync != NULL))
|
||||
{
|
||||
CLUTTER_NOTE (MISC, "vblank sync: using glx");
|
||||
|
||||
@ -265,6 +302,18 @@ clutter_feature_init (void)
|
||||
"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
|
||||
clutter_feature_available (ClutterFeatureFlags feature)
|
||||
{
|
||||
clutter_feature_do_init ();
|
||||
|
||||
return (__features->flags & feature);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_feature_get_all:
|
||||
*
|
||||
* Returns all the suppoerted features.
|
||||
* Returns all the supported features.
|
||||
*
|
||||
* Return value: a logical OR of all the supported features.
|
||||
*
|
||||
@ -296,6 +347,8 @@ clutter_feature_available (ClutterFeatureFlags feature)
|
||||
ClutterFeatureFlags
|
||||
clutter_feature_get_all (void)
|
||||
{
|
||||
clutter_feature_do_init ();
|
||||
|
||||
return __features->flags;
|
||||
}
|
||||
|
||||
@ -309,14 +362,17 @@ clutter_feature_get_all (void)
|
||||
void
|
||||
clutter_feature_wait_for_vblank (void)
|
||||
{
|
||||
clutter_feature_do_init ();
|
||||
|
||||
switch (__features->vblank_type)
|
||||
{
|
||||
case CLUTTER_VBLANK_GLX:
|
||||
{
|
||||
unsigned int retraceCount;
|
||||
__features->funcs.get_video_sync(&retraceCount);
|
||||
__features->funcs.wait_video_sync(2,
|
||||
(retraceCount+1)%2, &retraceCount);
|
||||
__features->funcs.get_video_sync (&retraceCount);
|
||||
__features->funcs.wait_video_sync (2,
|
||||
(retraceCount + 1) % 2,
|
||||
&retraceCount);
|
||||
}
|
||||
break;
|
||||
case CLUTTER_VBLANK_DRI:
|
||||
|
@ -235,16 +235,18 @@ clutter_dispatch_x_event (XEvent *xevent,
|
||||
static void
|
||||
events_init()
|
||||
{
|
||||
ClutterMainContext *clutter_context;
|
||||
GMainContext *gmain_context;
|
||||
int connection_number;
|
||||
GSource *source;
|
||||
ClutterXEventSource *display_source;
|
||||
|
||||
clutter_context = clutter_context_get_default ();
|
||||
gmain_context = g_main_context_default ();
|
||||
|
||||
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,
|
||||
sizeof (ClutterXEventSource));
|
||||
@ -253,7 +255,7 @@ events_init()
|
||||
|
||||
display_source->event_poll_fd.fd = connection_number;
|
||||
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_set_can_recurse (source, TRUE);
|
||||
@ -444,7 +446,9 @@ clutter_threads_leave (void)
|
||||
Display*
|
||||
clutter_xdisplay (void)
|
||||
{
|
||||
return ClutterCntx->xdpy;
|
||||
ClutterMainContext *context = CLUTTER_CONTEXT ();
|
||||
|
||||
return context->xdpy;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -457,7 +461,9 @@ clutter_xdisplay (void)
|
||||
int
|
||||
clutter_xscreen (void)
|
||||
{
|
||||
return ClutterCntx->xscreen;
|
||||
ClutterMainContext *context = CLUTTER_CONTEXT ();
|
||||
|
||||
return context->xscreen;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -470,7 +476,9 @@ clutter_xscreen (void)
|
||||
Window
|
||||
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;
|
||||
}
|
||||
|
||||
/* Check available features */
|
||||
clutter_feature_init ();
|
||||
|
||||
events_init ();
|
||||
|
||||
return CLUTTER_INIT_SUCCESS;
|
||||
@ -927,9 +932,6 @@ clutter_init (int *argc,
|
||||
return CLUTTER_INIT_ERROR_OPENGL;
|
||||
}
|
||||
|
||||
/* Check available features */
|
||||
clutter_feature_init ();
|
||||
|
||||
events_init ();
|
||||
|
||||
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_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 \
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB
|
||||
#define CLUTTER_PARAM_WRITABLE \
|
||||
|
@ -21,7 +21,7 @@ DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
|
||||
DOC_SOURCE_DIR=../../clutter
|
||||
|
||||
# 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.
|
||||
# e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED"
|
||||
|
@ -23,6 +23,21 @@ ClutterBehaviourScale
|
||||
</para>
|
||||
|
||||
|
||||
<!-- ##### ARG ClutterBehaviourScale:scale-begin ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG ClutterBehaviourScale:scale-end ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### ARG ClutterBehaviourScale:scale-gravity ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### STRUCT ClutterBehaviourScaleClass ##### -->
|
||||
<para>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user