mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
2007-05-16 Matthew Allum <mallum@openedhand.com>
* clutter/clutter-backend.c: * clutter/clutter-backend.h: * clutter/clutter-feature.c: * clutter/clutter-feature.h: * clutter/clutter-main.c: * clutter/clutter-main.h: * clutter/clutter-private.h: * clutter/clutter-stage.c: * clutter/cogl/cogl.h: * clutter/cogl/gl/cogl.c: * clutter/cogl/gles/cogl.c: * clutter/glx/clutter-backend-glx.c: * clutter/glx/clutter-backend-glx.h: * clutter/glx/clutter-glx.h: * clutter/glx/clutter-stage-glx.c: * clutter/glx/clutter-stage-glx.h: Rejig the features() foo, moving mostly into backends/cogl.
This commit is contained in:
parent
aab511d319
commit
ee928107cb
20
ChangeLog
20
ChangeLog
@ -1,3 +1,23 @@
|
|||||||
|
2007-05-16 Matthew Allum <mallum@openedhand.com>
|
||||||
|
|
||||||
|
* clutter/clutter-backend.c:
|
||||||
|
* clutter/clutter-backend.h:
|
||||||
|
* clutter/clutter-feature.c:
|
||||||
|
* clutter/clutter-feature.h:
|
||||||
|
* clutter/clutter-main.c:
|
||||||
|
* clutter/clutter-main.h:
|
||||||
|
* clutter/clutter-private.h:
|
||||||
|
* clutter/clutter-stage.c:
|
||||||
|
* clutter/cogl/cogl.h:
|
||||||
|
* clutter/cogl/gl/cogl.c:
|
||||||
|
* clutter/cogl/gles/cogl.c:
|
||||||
|
* clutter/glx/clutter-backend-glx.c:
|
||||||
|
* clutter/glx/clutter-backend-glx.h:
|
||||||
|
* clutter/glx/clutter-glx.h:
|
||||||
|
* clutter/glx/clutter-stage-glx.c:
|
||||||
|
* clutter/glx/clutter-stage-glx.h:
|
||||||
|
Rejig the features() foo, moving mostly into backends/cogl.
|
||||||
|
|
||||||
2007-05-15 Tomas Frydrych <tf@openedhand.com>
|
2007-05-15 Tomas Frydrych <tf@openedhand.com>
|
||||||
|
|
||||||
* clutter/clutter-actor.c:
|
* clutter/clutter-actor.c:
|
||||||
|
@ -143,16 +143,18 @@ _clutter_backend_init_stage (ClutterBackend *backend,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
ClutterFeatureFlags
|
||||||
_clutter_backend_init_features (ClutterBackend *backend)
|
_clutter_backend_get_features (ClutterBackend *backend)
|
||||||
{
|
{
|
||||||
ClutterBackendClass *klass;
|
ClutterBackendClass *klass;
|
||||||
|
|
||||||
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
|
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
|
||||||
|
|
||||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||||
if (klass->init_features)
|
if (klass->get_features)
|
||||||
klass->init_features (backend);
|
return klass->get_features (backend);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
#include <clutter/clutter-actor.h>
|
#include <clutter/clutter-actor.h>
|
||||||
#include <clutter/clutter-event.h>
|
#include <clutter/clutter-event.h>
|
||||||
|
#include <clutter/clutter-feature.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -66,6 +67,7 @@ struct _ClutterBackendClass
|
|||||||
ClutterActor *(* get_stage) (ClutterBackend *backend);
|
ClutterActor *(* get_stage) (ClutterBackend *backend);
|
||||||
void (* add_options) (ClutterBackend *backend,
|
void (* add_options) (ClutterBackend *backend,
|
||||||
GOptionGroup *group);
|
GOptionGroup *group);
|
||||||
|
ClutterFeatureFlags (* get_features) (ClutterBackend *backend);
|
||||||
};
|
};
|
||||||
|
|
||||||
GType clutter_backend_get_type (void) G_GNUC_CONST;
|
GType clutter_backend_get_type (void) G_GNUC_CONST;
|
||||||
|
@ -35,311 +35,48 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <GL/glx.h>
|
|
||||||
#include <GL/gl.h>
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
#include "clutter-feature.h"
|
#include "clutter-feature.h"
|
||||||
#include "clutter-main.h"
|
#include "clutter-main.h"
|
||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
#include "clutter-debug.h"
|
#include "clutter-debug.h"
|
||||||
|
|
||||||
#ifdef HAVE_CLUTTER_GLX
|
#include "cogl.h"
|
||||||
#include "glx/clutter-glx.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef void (*FuncPtr) (void);
|
|
||||||
typedef int (*GetVideoSyncProc) (unsigned int *count);
|
|
||||||
typedef int (*WaitVideoSyncProc) (int divisor,
|
|
||||||
int remainder,
|
|
||||||
unsigned int *count);
|
|
||||||
typedef FuncPtr (*GLXGetProcAddressProc) (const guint8 *procName);
|
|
||||||
|
|
||||||
typedef struct ClutterFeatureFuncs
|
|
||||||
{
|
|
||||||
GetVideoSyncProc get_video_sync;
|
|
||||||
WaitVideoSyncProc wait_video_sync;
|
|
||||||
|
|
||||||
} ClutterFeatureFuncs;
|
|
||||||
|
|
||||||
typedef enum ClutterVBlankType
|
|
||||||
{
|
|
||||||
CLUTTER_VBLANK_NONE = 0,
|
|
||||||
CLUTTER_VBLANK_GLX,
|
|
||||||
CLUTTER_VBLANK_DRI
|
|
||||||
|
|
||||||
} ClutterVBlankType;
|
|
||||||
|
|
||||||
typedef struct ClutterFeatures
|
typedef struct ClutterFeatures
|
||||||
{
|
{
|
||||||
ClutterFeatureFlags flags;
|
ClutterFeatureFlags flags;
|
||||||
ClutterFeatureFuncs funcs;
|
|
||||||
gint dri_fd;
|
|
||||||
ClutterVBlankType vblank_type;
|
|
||||||
|
|
||||||
guint features_set : 1;
|
guint features_set : 1;
|
||||||
} ClutterFeatures;
|
} ClutterFeatures;
|
||||||
|
|
||||||
static ClutterFeatures* __features = NULL;
|
static ClutterFeatures* __features = NULL;
|
||||||
G_LOCK_DEFINE_STATIC (__features);
|
G_LOCK_DEFINE_STATIC (__features);
|
||||||
|
|
||||||
|
void
|
||||||
#ifdef __linux__
|
_clutter_feature_init (void)
|
||||||
#define DRM_VBLANK_RELATIVE 0x1;
|
|
||||||
|
|
||||||
struct drm_wait_vblank_request {
|
|
||||||
int type;
|
|
||||||
unsigned int sequence;
|
|
||||||
unsigned long signal;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct drm_wait_vblank_reply {
|
|
||||||
int type;
|
|
||||||
unsigned int sequence;
|
|
||||||
long tval_sec;
|
|
||||||
long tval_usec;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef union drm_wait_vblank {
|
|
||||||
struct drm_wait_vblank_request request;
|
|
||||||
struct drm_wait_vblank_reply reply;
|
|
||||||
} drm_wait_vblank_t;
|
|
||||||
|
|
||||||
#define DRM_IOCTL_BASE 'd'
|
|
||||||
#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type)
|
|
||||||
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
|
|
||||||
|
|
||||||
static int drm_wait_vblank(int fd, drm_wait_vblank_t *vbl)
|
|
||||||
{
|
{
|
||||||
int ret, rc;
|
ClutterMainContext *context;
|
||||||
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
|
|
||||||
vbl->request.type &= ~DRM_VBLANK_RELATIVE;
|
|
||||||
rc = errno;
|
|
||||||
}
|
|
||||||
while (ret && rc == EINTR);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Note must be called after context created */
|
|
||||||
static gboolean
|
|
||||||
check_gl_extension (const gchar *name,
|
|
||||||
const gchar *ext)
|
|
||||||
{
|
|
||||||
/* FIXME: move to cogl */
|
|
||||||
gchar *end;
|
|
||||||
gint name_len, n;
|
|
||||||
|
|
||||||
if (name == NULL || ext == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
end = (gchar*)(ext + strlen(ext));
|
|
||||||
|
|
||||||
name_len = strlen(name);
|
|
||||||
|
|
||||||
while (ext < end)
|
|
||||||
{
|
|
||||||
n = strcspn(ext, " ");
|
|
||||||
|
|
||||||
if ((name_len == n) && (!strncmp(name, ext, n)))
|
|
||||||
return TRUE;
|
|
||||||
ext += (n + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: move to cogl */
|
|
||||||
static FuncPtr
|
|
||||||
get_proc_address (const gchar *name)
|
|
||||||
{
|
|
||||||
static GLXGetProcAddressProc get_proc_func = NULL;
|
|
||||||
static void *dlhand = NULL;
|
|
||||||
|
|
||||||
if (get_proc_func == NULL && dlhand == NULL)
|
|
||||||
{
|
|
||||||
dlhand = dlopen (NULL, RTLD_LAZY);
|
|
||||||
|
|
||||||
if (dlhand)
|
|
||||||
{
|
|
||||||
dlerror ();
|
|
||||||
|
|
||||||
get_proc_func =
|
|
||||||
(GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress");
|
|
||||||
|
|
||||||
if (dlerror () != NULL)
|
|
||||||
{
|
|
||||||
get_proc_func =
|
|
||||||
(GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddressARB");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dlerror () != NULL)
|
|
||||||
{
|
|
||||||
get_proc_func = NULL;
|
|
||||||
g_warning ("failed to bind GLXGetProcAddress "
|
|
||||||
"or GLXGetProcAddressARB");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (get_proc_func)
|
|
||||||
return get_proc_func ((unsigned char*) name);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
check_vblank_env (const char *name)
|
|
||||||
{
|
|
||||||
const char *val;
|
|
||||||
|
|
||||||
val = clutter_get_vblank_method ();
|
|
||||||
|
|
||||||
if (val && !strcasecmp(val, name))
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 components if we did not allocate
|
|
||||||
* it; 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 = NULL;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (MISC, "checking features");
|
CLUTTER_NOTE (MISC, "checking features");
|
||||||
|
|
||||||
if (!__features)
|
if (!__features)
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (MISC, "allocating features data");
|
CLUTTER_NOTE (MISC, "allocating features data");
|
||||||
|
|
||||||
__features = g_new0 (ClutterFeatures, 1);
|
__features = g_new0 (ClutterFeatures, 1);
|
||||||
memset(&__features->funcs, 0, sizeof (ClutterFeatureFuncs));
|
|
||||||
__features->features_set = FALSE; /* don't rely on zero-ing */
|
__features->features_set = FALSE; /* don't rely on zero-ing */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_CLUTTER_GLX
|
|
||||||
if (!clutter_glx_get_default_display ())
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (__features->features_set)
|
if (__features->features_set)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef HAVE_CLUTTER_GLX
|
context = clutter_context_get_default ();
|
||||||
glx_extensions
|
|
||||||
= glXQueryExtensionsString (clutter_glx_get_default_display (),
|
|
||||||
clutter_glx_get_default_screen ());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS);
|
__features->flags = cogl_get_features()
|
||||||
|
|_clutter_backend_get_features (context->backend);
|
||||||
if (check_gl_extension ("GL_ARB_texture_rectangle", gl_extensions) ||
|
|
||||||
check_gl_extension ("GL_EXT_texture_rectangle", gl_extensions))
|
|
||||||
{
|
|
||||||
__features->flags |= CLUTTER_FEATURE_TEXTURE_RECTANGLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* vblank */
|
|
||||||
|
|
||||||
__features->vblank_type = CLUTTER_VBLANK_NONE;
|
|
||||||
|
|
||||||
if (getenv("__GL_SYNC_TO_VBLANK") || check_vblank_env ("none"))
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (MISC, "vblank sync: disabled at user request");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef HAVE_CLUTTER_GLX
|
|
||||||
if (!check_vblank_env ("dri") &&
|
|
||||||
check_gl_extension ("GLX_SGI_video_sync", glx_extensions))
|
|
||||||
{
|
|
||||||
__features->funcs.get_video_sync =
|
|
||||||
(GetVideoSyncProc) get_proc_address ("glXGetVideoSyncSGI");
|
|
||||||
|
|
||||||
__features->funcs.wait_video_sync =
|
|
||||||
(WaitVideoSyncProc) get_proc_address ("glXWaitVideoSyncSGI");
|
|
||||||
|
|
||||||
if ((__features->funcs.get_video_sync != NULL) &&
|
|
||||||
(__features->funcs.wait_video_sync != NULL))
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (MISC, "vblank sync: using glx");
|
|
||||||
|
|
||||||
__features->vblank_type = CLUTTER_VBLANK_GLX;
|
|
||||||
__features->flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef __linux__
|
|
||||||
if (!(__features->flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
|
|
||||||
{
|
|
||||||
__features->dri_fd = open("/dev/dri/card0", O_RDWR);
|
|
||||||
if (__features->dri_fd >= 0)
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (MISC, "vblank sync: using dri");
|
|
||||||
|
|
||||||
__features->vblank_type = CLUTTER_VBLANK_DRI;
|
|
||||||
__features->flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!(__features->flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (MISC,
|
|
||||||
"vblank sync: no use-able mechanism found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (MISC, "features checked");
|
|
||||||
|
|
||||||
__features->features_set = TRUE;
|
__features->features_set = TRUE;
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
CLUTTER_NOTE (MISC, "features checked");
|
||||||
clutter_feature_do_init (void)
|
|
||||||
{
|
|
||||||
if (G_UNLIKELY (__features == NULL) ||
|
|
||||||
G_UNLIKELY (__features->features_set == FALSE))
|
|
||||||
{
|
|
||||||
G_LOCK (__features);
|
|
||||||
clutter_feature_init ();
|
|
||||||
G_UNLOCK (__features);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -356,8 +93,6 @@ clutter_feature_do_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,49 +108,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_feature_wait_for_vblank:
|
|
||||||
*
|
|
||||||
* FIXME
|
|
||||||
*
|
|
||||||
* Since: 0.2
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
clutter_feature_wait_for_vblank (void)
|
|
||||||
{
|
|
||||||
clutter_feature_do_init ();
|
|
||||||
|
|
||||||
switch (__features->vblank_type)
|
|
||||||
{
|
|
||||||
case CLUTTER_VBLANK_GLX:
|
|
||||||
#ifdef HAVE_CLUTTER_GLX
|
|
||||||
{
|
|
||||||
unsigned int retraceCount;
|
|
||||||
__features->funcs.get_video_sync (&retraceCount);
|
|
||||||
__features->funcs.wait_video_sync (2,
|
|
||||||
(retraceCount + 1) % 2,
|
|
||||||
&retraceCount);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case CLUTTER_VBLANK_DRI:
|
|
||||||
#ifdef __linux__
|
|
||||||
{
|
|
||||||
drm_wait_vblank_t blank;
|
|
||||||
blank.request.type = DRM_VBLANK_RELATIVE;
|
|
||||||
blank.request.sequence = 1;
|
|
||||||
blank.request.signal = 0;
|
|
||||||
drm_wait_vblank (__features->dri_fd, &blank);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
case CLUTTER_VBLANK_NONE:
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -40,12 +40,12 @@ G_BEGIN_DECLS
|
|||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
CLUTTER_FEATURE_TEXTURE_RECTANGLE = (1 << 1),
|
CLUTTER_FEATURE_TEXTURE_RECTANGLE = (1 << 1),
|
||||||
CLUTTER_FEATURE_SYNC_TO_VBLANK = (1 << 2)
|
CLUTTER_FEATURE_SYNC_TO_VBLANK = (1 << 2),
|
||||||
|
CLUTTER_FEATURE_TEXTURE_READ_PIXELS = (1 << 3)
|
||||||
} ClutterFeatureFlags;
|
} ClutterFeatureFlags;
|
||||||
|
|
||||||
gboolean clutter_feature_available (ClutterFeatureFlags feature);
|
gboolean clutter_feature_available (ClutterFeatureFlags feature);
|
||||||
ClutterFeatureFlags clutter_feature_get_all (void);
|
ClutterFeatureFlags clutter_feature_get_all (void);
|
||||||
void clutter_feature_wait_for_vblank (void);
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -51,7 +51,6 @@ static ClutterMainContext *ClutterCntx = NULL;
|
|||||||
static gboolean clutter_is_initialized = FALSE;
|
static gboolean clutter_is_initialized = FALSE;
|
||||||
static gboolean clutter_show_fps = FALSE;
|
static gboolean clutter_show_fps = FALSE;
|
||||||
static gboolean clutter_fatal_warnings = FALSE;
|
static gboolean clutter_fatal_warnings = FALSE;
|
||||||
static gchar *clutter_vblank_name = NULL;
|
|
||||||
|
|
||||||
guint clutter_debug_flags = 0; /* global clutter debug flag */
|
guint clutter_debug_flags = 0; /* global clutter debug flag */
|
||||||
|
|
||||||
@ -85,20 +84,6 @@ clutter_get_show_fps (void)
|
|||||||
return clutter_show_fps;
|
return clutter_show_fps;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* clutter_get_vblank_method:
|
|
||||||
*
|
|
||||||
* FIXME
|
|
||||||
*
|
|
||||||
* Return value: FIXME
|
|
||||||
*
|
|
||||||
* Since: 0.4
|
|
||||||
*/
|
|
||||||
G_CONST_RETURN gchar *
|
|
||||||
clutter_get_vblank_method (void)
|
|
||||||
{
|
|
||||||
return clutter_vblank_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_redraw:
|
* clutter_redraw:
|
||||||
@ -330,8 +315,6 @@ clutter_arg_no_debug_cb (const char *key,
|
|||||||
static GOptionEntry clutter_args[] = {
|
static GOptionEntry clutter_args[] = {
|
||||||
{ "clutter-show-fps", 0, 0, G_OPTION_ARG_NONE, &clutter_show_fps,
|
{ "clutter-show-fps", 0, 0, G_OPTION_ARG_NONE, &clutter_show_fps,
|
||||||
"Show frames per second", NULL },
|
"Show frames per second", NULL },
|
||||||
{ "clutter-vblank", 0, 0, G_OPTION_ARG_STRING, &clutter_vblank_name,
|
|
||||||
"VBlank method to be used (none, dri or glx)", "METHOD" },
|
|
||||||
{ "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &clutter_fatal_warnings,
|
{ "g-fatal-warnings", 0, 0, G_OPTION_ARG_NONE, &clutter_fatal_warnings,
|
||||||
"Make all warnings fatal", NULL },
|
"Make all warnings fatal", NULL },
|
||||||
#ifdef CLUTTER_ENABLE_DEBUG
|
#ifdef CLUTTER_ENABLE_DEBUG
|
||||||
@ -382,12 +365,6 @@ pre_parse_hook (GOptionContext *context,
|
|||||||
}
|
}
|
||||||
#endif /* CLUTTER_ENABLE_DEBUG */
|
#endif /* CLUTTER_ENABLE_DEBUG */
|
||||||
|
|
||||||
env_string = g_getenv ("CLUTTER_VBLANK");
|
|
||||||
if (env_string)
|
|
||||||
{
|
|
||||||
clutter_vblank_name = g_strdup (env_string);
|
|
||||||
env_string = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
env_string = g_getenv ("CLUTTER_SHOW_FPS");
|
env_string = g_getenv ("CLUTTER_SHOW_FPS");
|
||||||
if (env_string)
|
if (env_string)
|
||||||
@ -555,6 +532,8 @@ clutter_init_with_args (int *argc,
|
|||||||
|
|
||||||
_clutter_backend_init_events (clutter_context->backend);
|
_clutter_backend_init_events (clutter_context->backend);
|
||||||
|
|
||||||
|
_clutter_feature_init ();
|
||||||
|
|
||||||
return CLUTTER_INIT_SUCCESS;
|
return CLUTTER_INIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -615,14 +594,21 @@ clutter_init (int *argc,
|
|||||||
|
|
||||||
g_type_init ();
|
g_type_init ();
|
||||||
|
|
||||||
|
/* parse_args will trigger backend creation and things like
|
||||||
|
* DISPLAY connection etc.
|
||||||
|
*/
|
||||||
if (clutter_parse_args (argc, argv) == FALSE)
|
if (clutter_parse_args (argc, argv) == FALSE)
|
||||||
{
|
{
|
||||||
CLUTTER_NOTE (MISC, "failed to parse arguments.");
|
CLUTTER_NOTE (MISC, "failed to parse arguments.");
|
||||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Note, creates backend if not already existing (though parse args will
|
||||||
|
* have likely created it)
|
||||||
|
*/
|
||||||
context = clutter_context_get_default ();
|
context = clutter_context_get_default ();
|
||||||
|
|
||||||
|
/* Stage will give us a GL Context etc */
|
||||||
stage_error = NULL;
|
stage_error = NULL;
|
||||||
if (!_clutter_backend_init_stage (context->backend, &stage_error))
|
if (!_clutter_backend_init_stage (context->backend, &stage_error))
|
||||||
{
|
{
|
||||||
@ -632,8 +618,12 @@ clutter_init (int *argc,
|
|||||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Initiate event collection */
|
||||||
_clutter_backend_init_events (context->backend);
|
_clutter_backend_init_events (context->backend);
|
||||||
|
|
||||||
|
/* finally features - will call to backend and cogl */
|
||||||
|
_clutter_feature_init ();
|
||||||
|
|
||||||
return CLUTTER_INIT_SUCCESS;
|
return CLUTTER_INIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,6 @@ void clutter_redraw (void);
|
|||||||
|
|
||||||
gboolean clutter_get_debug_enabled (void);
|
gboolean clutter_get_debug_enabled (void);
|
||||||
gboolean clutter_get_show_fps (void);
|
gboolean clutter_get_show_fps (void);
|
||||||
G_CONST_RETURN gchar *clutter_get_vblank_method (void);
|
|
||||||
|
|
||||||
void clutter_threads_enter (void);
|
void clutter_threads_enter (void);
|
||||||
void clutter_threads_leave (void);
|
void clutter_threads_leave (void);
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "clutter-event.h"
|
#include "clutter-event.h"
|
||||||
#include "clutter-backend.h"
|
#include "clutter-backend.h"
|
||||||
#include "clutter-stage.h"
|
#include "clutter-stage.h"
|
||||||
|
#include "clutter-feature.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
@ -103,12 +104,14 @@ gboolean _clutter_backend_init_stage (ClutterBackend *backend,
|
|||||||
GError **error);
|
GError **error);
|
||||||
void _clutter_backend_init_events (ClutterBackend *backend);
|
void _clutter_backend_init_events (ClutterBackend *backend);
|
||||||
|
|
||||||
void _clutter_backend_init_features (ClutterBackend *backend);
|
ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend);
|
||||||
|
|
||||||
/* backend helpers */
|
/* backend helpers */
|
||||||
void _clutter_event_button_generate (ClutterBackend *backend,
|
void _clutter_event_button_generate (ClutterBackend *backend,
|
||||||
ClutterEvent *event);
|
ClutterEvent *event);
|
||||||
|
|
||||||
|
void _clutter_feature_init (void);
|
||||||
|
|
||||||
/* FIXME: move elsewhere via ClutterAudience */
|
/* FIXME: move elsewhere via ClutterAudience */
|
||||||
void _clutter_stage_sync_viewport (ClutterStage *stage);
|
void _clutter_stage_sync_viewport (ClutterStage *stage);
|
||||||
|
|
||||||
|
@ -178,6 +178,8 @@ void
|
|||||||
cogl_alpha_func (COGLenum func,
|
cogl_alpha_func (COGLenum func,
|
||||||
ClutterFixed ref);
|
ClutterFixed ref);
|
||||||
|
|
||||||
|
ClutterFeatureFlags
|
||||||
|
cogl_get_features ();
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
|
@ -84,11 +84,56 @@ error_string(GLenum errorCode)
|
|||||||
#define GE(x) (x);
|
#define GE(x) (x);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
check_gl_extension (const gchar *name,
|
||||||
|
const gchar *ext)
|
||||||
|
{
|
||||||
|
gchar *end;
|
||||||
|
gint name_len, n;
|
||||||
|
|
||||||
|
if (name == NULL || ext == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
end = (gchar*)(ext + strlen(ext));
|
||||||
|
|
||||||
|
name_len = strlen(name);
|
||||||
|
|
||||||
|
while (ext < end)
|
||||||
|
{
|
||||||
|
n = strcspn(ext, " ");
|
||||||
|
|
||||||
|
if ((name_len == n) && (!strncmp(name, ext, n)))
|
||||||
|
return TRUE;
|
||||||
|
ext += (n + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_gl_version_at_least_12 (void)
|
||||||
|
{
|
||||||
|
/* FIXME: This likely needs to live elsewhere in features or cogl */
|
||||||
|
return
|
||||||
|
(g_ascii_strtod ((const gchar*) glGetString (GL_VERSION), NULL) >= 1.2);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* At least GL 1.2 is needed for CLAMP_TO_EDGE */
|
||||||
|
/* FIXME: move to cogl... */
|
||||||
|
if (!is_gl_version_at_least_12 ())
|
||||||
|
{
|
||||||
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||||
|
CLUTTER_INIT_ERROR_BACKEND,
|
||||||
|
"Clutter needs at least version 1.2 of OpenGL");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
CoglFuncPtr
|
CoglFuncPtr
|
||||||
cogl_get_proc_address (const gchar* name)
|
cogl_get_proc_address (const gchar* name)
|
||||||
{
|
{
|
||||||
return NULL;
|
/* FIXME */
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -527,3 +572,24 @@ cogl_setup_viewport (guint width,
|
|||||||
1.0f / width) );
|
1.0f / width) );
|
||||||
GE( glTranslatef (0.0f, -1.0 * height, 0.0f) );
|
GE( glTranslatef (0.0f, -1.0 * height, 0.0f) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClutterFeatureFlags
|
||||||
|
cogl_get_features ()
|
||||||
|
{
|
||||||
|
ClutterFeatureFlags flags = 0;
|
||||||
|
const gchar *gl_extensions;
|
||||||
|
|
||||||
|
flags = CLUTTER_FEATURE_TEXTURE_READ_PIXELS;
|
||||||
|
|
||||||
|
gl_extensions = (const gchar*) glGetString (GL_EXTENSIONS);
|
||||||
|
|
||||||
|
|
||||||
|
if (check_gl_extension ("GL_ARB_texture_rectangle", gl_extensions) ||
|
||||||
|
check_gl_extension ("GL_EXT_texture_rectangle", gl_extensions))
|
||||||
|
{
|
||||||
|
flags |= CLUTTER_FEATURE_TEXTURE_RECTANGLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -515,5 +515,11 @@ cogl_setup_viewport (guint w,
|
|||||||
CFX_ONE / width));
|
CFX_ONE / width));
|
||||||
|
|
||||||
GE( glTranslatex (0, -CFX_ONE * height, 0) );
|
GE( glTranslatex (0, -CFX_ONE * height, 0) );
|
||||||
|
}
|
||||||
|
|
||||||
|
ClutterFeatureFlags
|
||||||
|
cogl_get_features ()
|
||||||
|
{
|
||||||
|
/* Suck */
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -29,16 +29,31 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <GL/glx.h>
|
||||||
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
#include "clutter-backend-glx.h"
|
#include "clutter-backend-glx.h"
|
||||||
#include "clutter-stage-glx.h"
|
#include "clutter-stage-glx.h"
|
||||||
|
#include "clutter-glx.h"
|
||||||
|
|
||||||
#include "../clutter-event.h"
|
#include "../clutter-event.h"
|
||||||
#include "../clutter-main.h"
|
#include "../clutter-main.h"
|
||||||
#include "../clutter-debug.h"
|
#include "../clutter-debug.h"
|
||||||
#include "../clutter-private.h"
|
#include "../clutter-private.h"
|
||||||
|
|
||||||
|
#include "cogl.h"
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterBackendGlx, clutter_backend_glx, CLUTTER_TYPE_BACKEND);
|
G_DEFINE_TYPE (ClutterBackendGlx, clutter_backend_glx, CLUTTER_TYPE_BACKEND);
|
||||||
|
|
||||||
|
typedef CoglFuncPtr (*GLXGetProcAddressProc) (const guint8 *procName);
|
||||||
|
|
||||||
/* singleton object */
|
/* singleton object */
|
||||||
static ClutterBackendGlx *backend_singleton = NULL;
|
static ClutterBackendGlx *backend_singleton = NULL;
|
||||||
|
|
||||||
@ -50,6 +65,56 @@ static gint clutter_screen = 0;
|
|||||||
static int TrappedErrorCode = 0;
|
static int TrappedErrorCode = 0;
|
||||||
static int (* old_error_handler) (Display *, XErrorEvent *);
|
static int (* old_error_handler) (Display *, XErrorEvent *);
|
||||||
|
|
||||||
|
static gchar *clutter_vblank_name = NULL;
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#define DRM_VBLANK_RELATIVE 0x1;
|
||||||
|
|
||||||
|
struct drm_wait_vblank_request {
|
||||||
|
int type;
|
||||||
|
unsigned int sequence;
|
||||||
|
unsigned long signal;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct drm_wait_vblank_reply {
|
||||||
|
int type;
|
||||||
|
unsigned int sequence;
|
||||||
|
long tval_sec;
|
||||||
|
long tval_usec;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef union drm_wait_vblank {
|
||||||
|
struct drm_wait_vblank_request request;
|
||||||
|
struct drm_wait_vblank_reply reply;
|
||||||
|
} drm_wait_vblank_t;
|
||||||
|
|
||||||
|
#define DRM_IOCTL_BASE 'd'
|
||||||
|
#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type)
|
||||||
|
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
|
||||||
|
|
||||||
|
static int drm_wait_vblank(int fd, drm_wait_vblank_t *vbl)
|
||||||
|
{
|
||||||
|
int ret, rc;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
|
||||||
|
vbl->request.type &= ~DRM_VBLANK_RELATIVE;
|
||||||
|
rc = errno;
|
||||||
|
}
|
||||||
|
while (ret && rc == EINTR);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
G_CONST_RETURN gchar*
|
||||||
|
clutter_backend_glx_get_vblank_method (void)
|
||||||
|
{
|
||||||
|
return clutter_vblank_name;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
clutter_backend_glx_pre_parse (ClutterBackend *backend,
|
clutter_backend_glx_pre_parse (ClutterBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -66,6 +131,13 @@ clutter_backend_glx_pre_parse (ClutterBackend *backend,
|
|||||||
env_string = NULL;
|
env_string = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
env_string = g_getenv ("CLUTTER_VBLANK");
|
||||||
|
if (env_string)
|
||||||
|
{
|
||||||
|
clutter_vblank_name = g_strdup (env_string);
|
||||||
|
env_string = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,13 +192,6 @@ clutter_backend_glx_post_parse (ClutterBackend *backend,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
is_gl_version_at_least_12 (void)
|
|
||||||
{
|
|
||||||
/* FIXME: This likely needs to live elsewhere in features or cogl */
|
|
||||||
return
|
|
||||||
(g_ascii_strtod ((const gchar*) glGetString (GL_VERSION), NULL) >= 1.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
clutter_backend_glx_init_stage (ClutterBackend *backend,
|
clutter_backend_glx_init_stage (ClutterBackend *backend,
|
||||||
@ -146,6 +211,7 @@ clutter_backend_glx_init_stage (ClutterBackend *backend,
|
|||||||
stage_glx->xdpy = backend_glx->xdpy;
|
stage_glx->xdpy = backend_glx->xdpy;
|
||||||
stage_glx->xwin_root = backend_glx->xwin_root;
|
stage_glx->xwin_root = backend_glx->xwin_root;
|
||||||
stage_glx->xscreen = backend_glx->xscreen_num;
|
stage_glx->xscreen = backend_glx->xscreen_num;
|
||||||
|
stage_glx->backend = backend_glx;
|
||||||
|
|
||||||
CLUTTER_NOTE (MISC, "GLX stage created (display:%p, screen:%d, root:%u)",
|
CLUTTER_NOTE (MISC, "GLX stage created (display:%p, screen:%d, root:%u)",
|
||||||
stage_glx->xdpy,
|
stage_glx->xdpy,
|
||||||
@ -166,16 +232,6 @@ clutter_backend_glx_init_stage (ClutterBackend *backend,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* At least GL 1.2 is needed for CLAMP_TO_EDGE */
|
|
||||||
/* FIXME: move to cogl... */
|
|
||||||
if (!is_gl_version_at_least_12 ())
|
|
||||||
{
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"Clutter needs at least version 1.2 of OpenGL");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,6 +265,11 @@ static const GOptionEntry entries[] =
|
|||||||
G_OPTION_ARG_INT, &clutter_screen,
|
G_OPTION_ARG_INT, &clutter_screen,
|
||||||
"X screen to use", "SCREEN"
|
"X screen to use", "SCREEN"
|
||||||
},
|
},
|
||||||
|
{ "vblank", 0,
|
||||||
|
G_OPTION_FLAG_IN_MAIN,
|
||||||
|
G_OPTION_ARG_STRING, &clutter_vblank_name,
|
||||||
|
"VBlank method to be used (none, dri or glx)", "METHOD"
|
||||||
|
},
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -274,6 +335,115 @@ clutter_backend_glx_constructor (GType gtype,
|
|||||||
return g_object_ref (backend_singleton);
|
return g_object_ref (backend_singleton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
check_vblank_env (const char *name)
|
||||||
|
{
|
||||||
|
if (clutter_vblank_name && !strcasecmp(clutter_vblank_name, name))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglFuncPtr
|
||||||
|
get_proc_address (const gchar* name)
|
||||||
|
{
|
||||||
|
static GLXGetProcAddressProc get_proc_func = NULL;
|
||||||
|
static void *dlhand = NULL;
|
||||||
|
|
||||||
|
if (get_proc_func == NULL && dlhand == NULL)
|
||||||
|
{
|
||||||
|
dlhand = dlopen (NULL, RTLD_LAZY);
|
||||||
|
|
||||||
|
if (dlhand)
|
||||||
|
{
|
||||||
|
dlerror ();
|
||||||
|
|
||||||
|
get_proc_func =
|
||||||
|
(GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress");
|
||||||
|
|
||||||
|
if (dlerror () != NULL)
|
||||||
|
{
|
||||||
|
get_proc_func =
|
||||||
|
(GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddressARB");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dlerror () != NULL)
|
||||||
|
{
|
||||||
|
get_proc_func = NULL;
|
||||||
|
g_warning ("failed to bind GLXGetProcAddress "
|
||||||
|
"or GLXGetProcAddressARB");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_proc_func)
|
||||||
|
return get_proc_func ((unsigned char*) name);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ClutterFeatureFlags
|
||||||
|
clutter_backend_glx_get_features (ClutterBackend *backend)
|
||||||
|
{
|
||||||
|
ClutterBackendGlx *backend_glx = CLUTTER_BACKEND_GLX (backend);
|
||||||
|
const gchar *glx_extensions = NULL;
|
||||||
|
ClutterFeatureFlags flags = 0;
|
||||||
|
|
||||||
|
/* FIXME: we really need to check if gl context is set */
|
||||||
|
|
||||||
|
glx_extensions
|
||||||
|
= glXQueryExtensionsString (clutter_glx_get_default_display (),
|
||||||
|
clutter_glx_get_default_screen ());
|
||||||
|
|
||||||
|
if (getenv("__GL_SYNC_TO_VBLANK") || check_vblank_env ("none"))
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (MISC, "vblank sync: disabled at user request");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!check_vblank_env ("dri") &&
|
||||||
|
cogl_check_extension ("GLX_SGI_video_sync", glx_extensions))
|
||||||
|
{
|
||||||
|
backend_glx->get_video_sync =
|
||||||
|
(GetVideoSyncProc) get_proc_address ("glXGetVideoSyncSGI");
|
||||||
|
|
||||||
|
backend_glx->wait_video_sync =
|
||||||
|
(WaitVideoSyncProc) get_proc_address ("glXWaitVideoSyncSGI");
|
||||||
|
|
||||||
|
if ((backend_glx->get_video_sync != NULL) &&
|
||||||
|
(backend_glx->wait_video_sync != NULL))
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (MISC, "vblank sync: using glx");
|
||||||
|
|
||||||
|
backend_glx->vblank_type = CLUTTER_VBLANK_GLX;
|
||||||
|
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef __linux__
|
||||||
|
if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
|
||||||
|
{
|
||||||
|
backend_glx->dri_fd = open("/dev/dri/card0", O_RDWR);
|
||||||
|
if (backend_glx->dri_fd >= 0)
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (MISC, "vblank sync: using dri");
|
||||||
|
|
||||||
|
backend_glx->vblank_type = CLUTTER_VBLANK_DRI;
|
||||||
|
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
|
||||||
|
{
|
||||||
|
CLUTTER_NOTE (MISC,
|
||||||
|
"vblank sync: no use-able mechanism found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CLUTTER_NOTE (MISC, "backend features checked");
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_backend_glx_class_init (ClutterBackendGlxClass *klass)
|
clutter_backend_glx_class_init (ClutterBackendGlxClass *klass)
|
||||||
{
|
{
|
||||||
@ -290,6 +460,7 @@ clutter_backend_glx_class_init (ClutterBackendGlxClass *klass)
|
|||||||
backend_class->init_events = clutter_backend_glx_init_events;
|
backend_class->init_events = clutter_backend_glx_init_events;
|
||||||
backend_class->get_stage = clutter_backend_glx_get_stage;
|
backend_class->get_stage = clutter_backend_glx_get_stage;
|
||||||
backend_class->add_options = clutter_backend_glx_add_options;
|
backend_class->add_options = clutter_backend_glx_add_options;
|
||||||
|
backend_class->get_features = clutter_backend_glx_get_features;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -317,6 +488,38 @@ error_handler(Display *xdpy,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
clutter_backend_glx_wait_for_vblank (ClutterBackendGlx *backend_glx)
|
||||||
|
{
|
||||||
|
switch (backend_glx->vblank_type)
|
||||||
|
{
|
||||||
|
case CLUTTER_VBLANK_GLX:
|
||||||
|
{
|
||||||
|
unsigned int retraceCount;
|
||||||
|
backend_glx->get_video_sync (&retraceCount);
|
||||||
|
backend_glx->wait_video_sync (2,
|
||||||
|
(retraceCount + 1) % 2,
|
||||||
|
&retraceCount);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CLUTTER_VBLANK_DRI:
|
||||||
|
#ifdef __linux__
|
||||||
|
{
|
||||||
|
drm_wait_vblank_t blank;
|
||||||
|
blank.request.type = DRM_VBLANK_RELATIVE;
|
||||||
|
blank.request.sequence = 1;
|
||||||
|
blank.request.signal = 0;
|
||||||
|
drm_wait_vblank (backend_glx->dri_fd, &blank);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case CLUTTER_VBLANK_NONE:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clutter_glx_trap_x_errors:
|
* clutter_glx_trap_x_errors:
|
||||||
*
|
*
|
||||||
@ -378,16 +581,16 @@ clutter_glx_get_default_display (void)
|
|||||||
*
|
*
|
||||||
* Since: 0.4
|
* Since: 0.4
|
||||||
*/
|
*/
|
||||||
Screen *
|
int
|
||||||
clutter_glx_get_default_screen (void)
|
clutter_glx_get_default_screen (void)
|
||||||
{
|
{
|
||||||
if (!backend_singleton)
|
if (!backend_singleton)
|
||||||
{
|
{
|
||||||
g_critical ("GLX backend has not been initialised");
|
g_critical ("GLX backend has not been initialised");
|
||||||
return NULL;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return backend_singleton->xscreen;
|
return backend_singleton->xscreen_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,6 +42,19 @@ G_BEGIN_DECLS
|
|||||||
typedef struct _ClutterBackendGlx ClutterBackendGlx;
|
typedef struct _ClutterBackendGlx ClutterBackendGlx;
|
||||||
typedef struct _ClutterBackendGlxClass ClutterBackendGlxClass;
|
typedef struct _ClutterBackendGlxClass ClutterBackendGlxClass;
|
||||||
|
|
||||||
|
typedef enum ClutterGLXVBlankType
|
||||||
|
{
|
||||||
|
CLUTTER_VBLANK_NONE = 0,
|
||||||
|
CLUTTER_VBLANK_GLX,
|
||||||
|
CLUTTER_VBLANK_DRI
|
||||||
|
|
||||||
|
} ClutterGLXVBlankType;
|
||||||
|
|
||||||
|
typedef int (*GetVideoSyncProc) (unsigned int *count);
|
||||||
|
typedef int (*WaitVideoSyncProc) (int divisor,
|
||||||
|
int remainder,
|
||||||
|
unsigned int *count);
|
||||||
|
|
||||||
struct _ClutterBackendGlx
|
struct _ClutterBackendGlx
|
||||||
{
|
{
|
||||||
ClutterBackend parent_instance;
|
ClutterBackend parent_instance;
|
||||||
@ -57,6 +70,12 @@ struct _ClutterBackendGlx
|
|||||||
|
|
||||||
/* event source */
|
/* event source */
|
||||||
GSource *event_source;
|
GSource *event_source;
|
||||||
|
|
||||||
|
/* Vblank stuff */
|
||||||
|
GetVideoSyncProc get_video_sync;
|
||||||
|
WaitVideoSyncProc wait_video_sync;
|
||||||
|
gint dri_fd;
|
||||||
|
ClutterGLXVBlankType vblank_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterBackendGlxClass
|
struct _ClutterBackendGlxClass
|
||||||
@ -67,6 +86,8 @@ struct _ClutterBackendGlxClass
|
|||||||
void _clutter_backend_glx_events_init (ClutterBackend *backend);
|
void _clutter_backend_glx_events_init (ClutterBackend *backend);
|
||||||
void _clutter_backend_glx_events_uninit (ClutterBackend *backend);
|
void _clutter_backend_glx_events_uninit (ClutterBackend *backend);
|
||||||
|
|
||||||
|
void clutter_backend_glx_wait_for_vblank (ClutterBackendGlx *backend_glx);
|
||||||
|
|
||||||
GType clutter_backend_glx_get_type (void) G_GNUC_CONST;
|
GType clutter_backend_glx_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
@ -37,7 +37,7 @@ void clutter_glx_trap_x_errors (void);
|
|||||||
gint clutter_glx_untrap_x_errors (void);
|
gint clutter_glx_untrap_x_errors (void);
|
||||||
|
|
||||||
Display *clutter_glx_get_default_display (void);
|
Display *clutter_glx_get_default_display (void);
|
||||||
Screen * clutter_glx_get_default_screen (void);
|
int clutter_glx_get_default_screen (void);
|
||||||
Window clutter_glx_get_root_window (void);
|
Window clutter_glx_get_root_window (void);
|
||||||
|
|
||||||
Window clutter_glx_get_stage_window (ClutterStage *stage);
|
Window clutter_glx_get_stage_window (ClutterStage *stage);
|
||||||
@ -46,6 +46,7 @@ XVisualInfo *clutter_glx_get_stage_visual (ClutterStage *stage);
|
|||||||
gboolean clutter_glx_set_stage_foreign (ClutterStage *stage,
|
gboolean clutter_glx_set_stage_foreign (ClutterStage *stage,
|
||||||
Window xwindow);
|
Window xwindow);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __CLUTTER_GLX_H__ */
|
#endif /* __CLUTTER_GLX_H__ */
|
||||||
|
@ -331,7 +331,7 @@ clutter_stage_glx_paint (ClutterActor *self)
|
|||||||
*/
|
*/
|
||||||
if (stage_glx->xwin)
|
if (stage_glx->xwin)
|
||||||
{
|
{
|
||||||
clutter_feature_wait_for_vblank ();
|
clutter_backend_glx_wait_for_vblank (stage_glx->backend);
|
||||||
glXSwapBuffers (stage_glx->xdpy, stage_glx->xwin);
|
glXSwapBuffers (stage_glx->xdpy, stage_glx->xwin);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -373,7 +373,6 @@ clutter_stage_glx_request_coords (ClutterActor *self,
|
|||||||
ClutterStageGlx *stage_glx = CLUTTER_STAGE_GLX (self);
|
ClutterStageGlx *stage_glx = CLUTTER_STAGE_GLX (self);
|
||||||
gint new_width, new_height;
|
gint new_width, new_height;
|
||||||
|
|
||||||
/* FIXME: some how have X configure_notfiys call this ? */
|
|
||||||
new_width = ABS (box->x2 - box->x1);
|
new_width = ABS (box->x2 - box->x1);
|
||||||
new_height = ABS (box->y2 - box->y1);
|
new_height = ABS (box->y2 - box->y1);
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
#include <GL/glx.h>
|
#include <GL/glx.h>
|
||||||
#include <GL/gl.h>
|
#include <GL/gl.h>
|
||||||
|
|
||||||
|
#include "clutter-backend-glx.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define CLUTTER_TYPE_STAGE_GLX (clutter_stage_glx_get_type ())
|
#define CLUTTER_TYPE_STAGE_GLX (clutter_stage_glx_get_type ())
|
||||||
@ -60,6 +62,9 @@ struct _ClutterStageGlx
|
|||||||
GLXContext gl_context;
|
GLXContext gl_context;
|
||||||
|
|
||||||
guint is_foreign_xwin : 1;
|
guint is_foreign_xwin : 1;
|
||||||
|
|
||||||
|
ClutterBackendGlx *backend;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _ClutterStageGlxClass
|
struct _ClutterStageGlxClass
|
||||||
|
Loading…
Reference in New Issue
Block a user