forked from enlightenment/efl
ecore x vsync animator support - add a glx based vsync ticker
this adds a slave process that is useful on nvidia drivers as there isn't another way to get vsync evenys (that i know about). i need to make another slave process to that includes a dri2 protocol implementation since mesa has now hidden its dri2 symbols.
This commit is contained in:
parent
89d0e9f033
commit
2d63a70422
|
@ -64,3 +64,4 @@ tags
|
||||||
/ABOUT-NLS
|
/ABOUT-NLS
|
||||||
/config.rpath
|
/config.rpath
|
||||||
/coverage
|
/coverage
|
||||||
|
/src/lib/ecore_x/ecore_x_vsync
|
||||||
|
|
|
@ -27,6 +27,12 @@ ecorefilesdir = $(datadir)/ecore
|
||||||
ecorefiles_DATA = ecore/checkme
|
ecorefiles_DATA = ecore/checkme
|
||||||
EXTRA_DIST += $(ecorefiles_DATA)
|
EXTRA_DIST += $(ecorefiles_DATA)
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Ecore_X
|
||||||
|
ecore_xfilesdir = $(datadir)/ecore_x
|
||||||
|
ecore_xfiles_DATA = ecore_x/checkme
|
||||||
|
EXTRA_DIST += $(ecore_xfiles_DATA)
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
# Ecore_Imf
|
# Ecore_Imf
|
||||||
ecoreimffilesdir = $(datadir)/ecore_imf
|
ecoreimffilesdir = $(datadir)/ecore_imf
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
This is just a test file used to help ecore determine its prefix location.
|
|
@ -1,5 +1,19 @@
|
||||||
if HAVE_ECORE_X
|
if HAVE_ECORE_X
|
||||||
|
|
||||||
|
ecore_x_vsync_bin_PROGRAMS = lib/ecore_x/ecore_x_vsync
|
||||||
|
ecore_x_vsync_bindir = $(libdir)/ecore_x/bin/$(MODULE_ARCH)
|
||||||
|
lib_ecore_x_ecore_x_vsync_SOURCES = \
|
||||||
|
lib/ecore_x/ecore_x_vsync_tool.c \
|
||||||
|
lib/ecore_x/ecore_x_vsync_tool_glx.c
|
||||||
|
lib_ecore_x_ecore_x_vsync_CPPFLAGS = \
|
||||||
|
-I$(top_builddir)/src/lib/efl \
|
||||||
|
@ECORE_CFLAGS@ @ECORE_CON_CFLAGS@ @EINA_CFLAGS@ \
|
||||||
|
-DPACKAGE_BIN_DIR=\"$(bindir)\" \
|
||||||
|
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
|
||||||
|
-DPACKAGE_DATA_DIR=\"$(datadir)/ecore_x\"
|
||||||
|
lib_ecore_x_ecore_x_vsync_LDADD = @USE_EINA_LIBS@ @USE_ECORE_LIBS@ @USE_ECORE_CON_LIBS@
|
||||||
|
lib_ecore_x_ecore_x_vsync_DEPENDENCIES = @EINA_INTERNAL_LIBS@ @ECORE_INTERNAL_LIBS@ @ECORE_CON_INTERNAL_LIBS@
|
||||||
|
|
||||||
### Library
|
### Library
|
||||||
|
|
||||||
lib_LTLIBRARIES += lib/ecore_x/libecore_x.la
|
lib_LTLIBRARIES += lib/ecore_x/libecore_x.la
|
||||||
|
@ -93,12 +107,17 @@ lib/ecore_x/xlib/ecore_x_gesture.c \
|
||||||
lib/ecore_x/xlib/ecore_x_private.h
|
lib/ecore_x/xlib/ecore_x_private.h
|
||||||
endif
|
endif
|
||||||
|
|
||||||
lib_ecore_x_libecore_x_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_X_CFLAGS@
|
lib_ecore_x_libecore_x_la_CPPFLAGS = \
|
||||||
|
-I$(top_builddir)/src/lib/efl \
|
||||||
|
@ECORE_X_CFLAGS@ @ECORE_CON_CFLAGS@ \
|
||||||
|
-DPACKAGE_BIN_DIR=\"$(bindir)\" \
|
||||||
|
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
|
||||||
|
-DPACKAGE_DATA_DIR=\"$(datadir)/ecore_x\"
|
||||||
if HAVE_ECORE_X_XCB
|
if HAVE_ECORE_X_XCB
|
||||||
lib_ecore_x_libecore_x_la_CPPFLAGS += -I$(top_builddir)/src/lib/ecore_x/xcb
|
lib_ecore_x_libecore_x_la_CPPFLAGS += -I$(top_builddir)/src/lib/ecore_x/xcb
|
||||||
endif
|
endif
|
||||||
|
|
||||||
lib_ecore_x_libecore_x_la_LIBADD = @ECORE_X_LIBS@
|
lib_ecore_x_libecore_x_la_LIBADD = @ECORE_X_LIBS@ @USE_ECORE_CON_LIBS@
|
||||||
lib_ecore_x_libecore_x_la_DEPENDENCIES = @ECORE_X_INTERNAL_LIBS@
|
lib_ecore_x_libecore_x_la_DEPENDENCIES = @ECORE_X_INTERNAL_LIBS@
|
||||||
lib_ecore_x_libecore_x_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
|
lib_ecore_x_libecore_x_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
|
||||||
|
|
||||||
|
@ -125,4 +144,3 @@ utils_ecore_makekeys_CFLAGS = @ECORE_X_CFLAGS@
|
||||||
|
|
||||||
endif
|
endif
|
||||||
EXTRA_DIST += utils/ecore/mkks.sh
|
EXTRA_DIST += utils/ecore/mkks.sh
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,256 @@
|
||||||
|
#include <Eina.h>
|
||||||
|
#include <Ecore.h>
|
||||||
|
#include <Ecore_Con.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MODE_NONE,
|
||||||
|
MODE_GLX
|
||||||
|
};
|
||||||
|
|
||||||
|
int _vsync_init_glx(void);
|
||||||
|
double _vsync_wait_glx(void);
|
||||||
|
|
||||||
|
static void _svr_broadcast_time(double t);
|
||||||
|
|
||||||
|
static int _vsync_mode = MODE_NONE;
|
||||||
|
|
||||||
|
static int
|
||||||
|
_vsync_init(void)
|
||||||
|
{
|
||||||
|
if (_vsync_init_glx()) _vsync_mode = MODE_GLX;
|
||||||
|
else return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double
|
||||||
|
_vsync_wait(void)
|
||||||
|
{
|
||||||
|
if (_vsync_mode == MODE_GLX) return _vsync_wait_glx();
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Eina_Thread_Queue_Msg head;
|
||||||
|
char val;
|
||||||
|
} Msg;
|
||||||
|
|
||||||
|
static int tick = 0;
|
||||||
|
static Eina_Thread_Queue *thq = NULL;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_tick_core(void *data EINA_UNUSED, Ecore_Thread *thread)
|
||||||
|
{
|
||||||
|
Msg *msg;
|
||||||
|
void *ref;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
if (!tick)
|
||||||
|
{
|
||||||
|
msg = eina_thread_queue_wait(thq, &ref);
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
tick = msg->val;
|
||||||
|
eina_thread_queue_wait_done(thq, ref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
again:
|
||||||
|
msg = eina_thread_queue_poll(thq, &ref);
|
||||||
|
if (msg)
|
||||||
|
{
|
||||||
|
tick = msg->val;
|
||||||
|
eina_thread_queue_wait_done(thq, ref);
|
||||||
|
}
|
||||||
|
if (msg) goto again;
|
||||||
|
}
|
||||||
|
if (tick == -1) exit(0);
|
||||||
|
if (tick)
|
||||||
|
{
|
||||||
|
double *t;
|
||||||
|
|
||||||
|
t = malloc(sizeof(*t));
|
||||||
|
if (t)
|
||||||
|
{
|
||||||
|
*t = _vsync_wait();
|
||||||
|
ecore_thread_feedback(thread, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_tick_notify(void *data EINA_UNUSED, Ecore_Thread *thread EINA_UNUSED, void *msg)
|
||||||
|
{
|
||||||
|
double *t = msg;
|
||||||
|
|
||||||
|
if (t)
|
||||||
|
{
|
||||||
|
_svr_broadcast_time(*t);
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_tick_init(void)
|
||||||
|
{
|
||||||
|
thq = eina_thread_queue_new();
|
||||||
|
ecore_thread_feedback_run(_tick_core, _tick_notify,
|
||||||
|
NULL, NULL, NULL, EINA_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_tick_send(char val)
|
||||||
|
{
|
||||||
|
Msg *msg;
|
||||||
|
void *ref;
|
||||||
|
msg = eina_thread_queue_send(thq, sizeof(Msg), &ref);
|
||||||
|
msg->val = val;
|
||||||
|
eina_thread_queue_send_done(thq, ref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_tick_start(void)
|
||||||
|
{
|
||||||
|
tick++;
|
||||||
|
if (tick > 1) return;
|
||||||
|
_tick_send(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_tick_end(void)
|
||||||
|
{
|
||||||
|
tick--;
|
||||||
|
if (tick > 0) return;
|
||||||
|
_tick_send(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
Ecore_Con_Client *client;
|
||||||
|
Eina_Bool enabled : 1;
|
||||||
|
} Clientdata;
|
||||||
|
|
||||||
|
static Ecore_Con_Server *svr = NULL;
|
||||||
|
static Eina_List *clients = NULL;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_svr_broadcast_time(double t)
|
||||||
|
{
|
||||||
|
Eina_List *l;
|
||||||
|
Clientdata *cdat;
|
||||||
|
|
||||||
|
EINA_LIST_FOREACH(clients, l, cdat)
|
||||||
|
{
|
||||||
|
ecore_con_client_send(cdat->client, &t, sizeof(t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_svr_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Con_Event_Client_Add *ev = event;
|
||||||
|
if (svr != ecore_con_client_server_get(ev->client)) return EINA_TRUE;
|
||||||
|
Clientdata *cdat = calloc(1, sizeof(Clientdata));
|
||||||
|
if (cdat)
|
||||||
|
{
|
||||||
|
cdat->client = ev->client;
|
||||||
|
clients = eina_list_append(clients, cdat);
|
||||||
|
ecore_con_client_data_set(ev->client, cdat);
|
||||||
|
}
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_svr_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Con_Event_Client_Del *ev = event;
|
||||||
|
if (svr != ecore_con_client_server_get(ev->client)) return EINA_TRUE;
|
||||||
|
Clientdata *cdat = ecore_con_client_data_get(ev->client);
|
||||||
|
if (cdat)
|
||||||
|
{
|
||||||
|
clients = eina_list_remove(clients, cdat);
|
||||||
|
if (cdat->enabled) _tick_end();
|
||||||
|
free(cdat);
|
||||||
|
}
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_svr_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Con_Event_Client_Data *ev = event;
|
||||||
|
if (svr != ecore_con_client_server_get(ev->client)) return EINA_TRUE;
|
||||||
|
Clientdata *cdat = ecore_con_client_data_get(ev->client);
|
||||||
|
if (cdat)
|
||||||
|
{
|
||||||
|
char *dat = ev->data;
|
||||||
|
|
||||||
|
if (ev->size > 0)
|
||||||
|
{
|
||||||
|
if (dat[ev->size - 1])
|
||||||
|
{
|
||||||
|
if (!cdat->enabled)
|
||||||
|
{
|
||||||
|
_tick_start();
|
||||||
|
cdat->enabled = EINA_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (cdat->enabled)
|
||||||
|
{
|
||||||
|
_tick_end();
|
||||||
|
cdat->enabled = EINA_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_svr_init(void)
|
||||||
|
{
|
||||||
|
char buf[4096], *disp, *s;
|
||||||
|
|
||||||
|
disp = getenv("DISPLAY");
|
||||||
|
if (disp) disp = ":0";
|
||||||
|
snprintf(buf, sizeof(buf), "ecore-x-vsync-%s", disp);
|
||||||
|
for (s = buf; *s; s++)
|
||||||
|
{
|
||||||
|
if (*s == ':') *s = '=';
|
||||||
|
}
|
||||||
|
svr = ecore_con_server_add(ECORE_CON_LOCAL_USER, buf, 1, NULL);
|
||||||
|
if (!svr) exit(0);
|
||||||
|
ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_ADD, _svr_add, NULL);
|
||||||
|
ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DEL, _svr_del, NULL);
|
||||||
|
ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_DATA, _svr_data, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
|
||||||
|
{
|
||||||
|
eina_init();
|
||||||
|
ecore_app_no_system_modules();
|
||||||
|
ecore_init();
|
||||||
|
ecore_con_init();
|
||||||
|
|
||||||
|
if (!_vsync_init()) return 7;
|
||||||
|
_svr_init();
|
||||||
|
_tick_init();
|
||||||
|
|
||||||
|
ecore_main_loop_begin();
|
||||||
|
_tick_send(-1);
|
||||||
|
pause();
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,302 @@
|
||||||
|
#include <Eina.h>
|
||||||
|
#include <Ecore.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define SYM(lib, xx) \
|
||||||
|
do { \
|
||||||
|
sym_ ## xx = dlsym(lib, #xx); \
|
||||||
|
if (!(sym_ ## xx)) { \
|
||||||
|
fail = 1; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define GLX_DRAWABLE_TYPE 0x8010
|
||||||
|
#define GLX_WINDOW_BIT 0x00000001
|
||||||
|
#define GLX_RENDER_TYPE 0x8011
|
||||||
|
#define GLX_RGBA_BIT 0x00000001
|
||||||
|
#define GLX_DOUBLEBUFFER 5
|
||||||
|
#define GLX_RED_SIZE 8
|
||||||
|
#define GLX_GREEN_SIZE 9
|
||||||
|
#define GLX_BLUE_SIZE 10
|
||||||
|
#define GLX_RGBA_TYPE 0x8014
|
||||||
|
typedef struct __GLXFBConfigRec *GLXFBConfig;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void *visual;
|
||||||
|
long visualid;
|
||||||
|
int screen;
|
||||||
|
int depth;
|
||||||
|
int c_class;
|
||||||
|
unsigned long red_mask;
|
||||||
|
unsigned long green_mask;
|
||||||
|
unsigned long blue_mask;
|
||||||
|
int colormap_size;
|
||||||
|
int bits_per_rgb;
|
||||||
|
} XVisualInfo;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
long background_pixmap;
|
||||||
|
unsigned long background_pixel;
|
||||||
|
long border_pixmap;
|
||||||
|
unsigned long border_pixel;
|
||||||
|
int bit_gravity;
|
||||||
|
int win_gravity;
|
||||||
|
int backing_store;
|
||||||
|
unsigned long backing_planes;
|
||||||
|
unsigned long backing_pixel;
|
||||||
|
int save_under;
|
||||||
|
long event_mask;
|
||||||
|
long do_not_propagate_mask;
|
||||||
|
int override_redirect;
|
||||||
|
long colormap;
|
||||||
|
long cursor;
|
||||||
|
} XSetWindowAttributes;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *ext_data;
|
||||||
|
void *display;
|
||||||
|
long root;
|
||||||
|
int width, height;
|
||||||
|
int mwidth, mheight;
|
||||||
|
int ndepths;
|
||||||
|
void *depths;
|
||||||
|
int root_depth;
|
||||||
|
void *root_visual;
|
||||||
|
long default_gc;
|
||||||
|
long cmap;
|
||||||
|
unsigned long white_pixel;
|
||||||
|
unsigned long black_pixel;
|
||||||
|
int max_maps, min_maps;
|
||||||
|
int backing_store;
|
||||||
|
int save_unders;
|
||||||
|
long root_input_mask;
|
||||||
|
} Screen;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void *ext_data;
|
||||||
|
void *private1;
|
||||||
|
int fd;
|
||||||
|
int private2;
|
||||||
|
int proto_major_version;
|
||||||
|
int proto_minor_version;
|
||||||
|
char *vendor;
|
||||||
|
long private3;
|
||||||
|
long private4;
|
||||||
|
long private5;
|
||||||
|
int private6;
|
||||||
|
long (*resource_alloc)(void *);
|
||||||
|
int byte_order;
|
||||||
|
int bitmap_unit;
|
||||||
|
int bitmap_pad;
|
||||||
|
int bitmap_bit_order;
|
||||||
|
int nformats;
|
||||||
|
void *pixmap_format;
|
||||||
|
int private8;
|
||||||
|
int release;
|
||||||
|
void *private9, *private10;
|
||||||
|
int qlen;
|
||||||
|
unsigned long last_request_read;
|
||||||
|
unsigned long request;
|
||||||
|
char *private11;
|
||||||
|
char *private12;
|
||||||
|
char *private13;
|
||||||
|
char *private14;
|
||||||
|
unsigned max_request_size;
|
||||||
|
void *db;
|
||||||
|
int (*private15)(void *);
|
||||||
|
char *display_name;
|
||||||
|
int default_screen;
|
||||||
|
int nscreens;
|
||||||
|
Screen *screens;
|
||||||
|
unsigned long motion_buffer;
|
||||||
|
unsigned long private16;
|
||||||
|
int min_keycode;
|
||||||
|
int max_keycode;
|
||||||
|
char *private17;
|
||||||
|
char *private18;
|
||||||
|
int private19;
|
||||||
|
char *xdefaults;
|
||||||
|
} *_XPrivDisplay;
|
||||||
|
|
||||||
|
#define InputOutput 1
|
||||||
|
#define RootWindow(dpy, scr) (ScreenOfDisplay(dpy,scr)->root)
|
||||||
|
#define ScreenOfDisplay(dpy, scr) (&((_XPrivDisplay)dpy)->screens[scr])
|
||||||
|
#define CWBorderPixel (1L<<3)
|
||||||
|
#define CWColormap (1L<<13)
|
||||||
|
#define CWOverrideRedirect (1L<<9)
|
||||||
|
#define AllocNone 0
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static const char *lib_x11_files[] =
|
||||||
|
{
|
||||||
|
"libX11.so.6",
|
||||||
|
"libX11.so.5",
|
||||||
|
"libX11.so.4",
|
||||||
|
"libX11.so",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
static void *lib_x11 = NULL;
|
||||||
|
static void * (*sym_XOpenDisplay) (char *name) = NULL;
|
||||||
|
static long (*sym_XCreateColormap) (void *d, long w, void *vis, int alloc) = NULL;
|
||||||
|
static long (*sym_XCreateWindow) (void *d, long par, int x, int y, unsigned int w, unsigned int h, unsigned int bd, int depth, unsigned int clas, void *vis, unsigned long valmask, void *attr) = NULL;
|
||||||
|
static int (*sym_XCloseDisplay) (void *d) = NULL;
|
||||||
|
//static void * (*sym_) () = NULL;
|
||||||
|
|
||||||
|
static const char *lib_gl_files[] =
|
||||||
|
{
|
||||||
|
"libGL.so.9",
|
||||||
|
"libGL.so.8",
|
||||||
|
"libGL.so.7",
|
||||||
|
"libGL.so.6",
|
||||||
|
"libGL.so.5",
|
||||||
|
"libGL.so.4",
|
||||||
|
"libGL.so.3",
|
||||||
|
"libGL.so.2",
|
||||||
|
"libGL.so.1",
|
||||||
|
"libGL.so",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
static void *lib_gl = NULL;
|
||||||
|
static GLXFBConfig * (*sym_glXChooseFBConfig) (void *d, int sc, const int *att, int *n) = NULL;
|
||||||
|
static void * (*sym_glXGetVisualFromFBConfig) (void *d, GLXFBConfig fbconfig) = NULL;
|
||||||
|
static void *(*sym_glXCreateNewContext) (void *d, GLXFBConfig config, int rtype, void *shr, int direct) = NULL;
|
||||||
|
static long (*sym_glXCreateWindow) (void *d, GLXFBConfig config, long win, const int *attr) = NULL;
|
||||||
|
static int (*sym_glXMakeContextCurrent) (void *d, long draw, long draw2, void *context) = NULL;
|
||||||
|
static void (*sym_glXSwapBuffers) (void *d, long draw) = NULL;
|
||||||
|
static const char * (*sym_glXQueryExtensionsString) (void *d, int ival) = NULL;
|
||||||
|
static void * (*sym_glXGetProcAddressARB) (const char *sym) = NULL;
|
||||||
|
static int (*sym_glXGetVideoSyncSGI) (unsigned int *cnt) = NULL;
|
||||||
|
static int (*sym_glXWaitVideoSyncSGI) (int divisor, int remainder, unsigned int *cnt) = NULL;
|
||||||
|
//static void * (*sym_) () = NULL;
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static void *disp = NULL;
|
||||||
|
static long gwin = 0;
|
||||||
|
static void *context = NULL;
|
||||||
|
|
||||||
|
static void *
|
||||||
|
lib_load(const char *files[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
void *lib = NULL;
|
||||||
|
|
||||||
|
for (i = 0; files[i]; i++)
|
||||||
|
{
|
||||||
|
lib = dlopen(files[i], RTLD_LOCAL | RTLD_LAZY);
|
||||||
|
if (lib) return lib;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_vsync_init_glx(void)
|
||||||
|
{
|
||||||
|
int fail = 0;
|
||||||
|
GLXFBConfig *fbconfigs;
|
||||||
|
int num = 0;
|
||||||
|
int attr[] =
|
||||||
|
{
|
||||||
|
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||||
|
GLX_RENDER_TYPE, GLX_RGBA_BIT,
|
||||||
|
GLX_DOUBLEBUFFER, 1,
|
||||||
|
GLX_RED_SIZE, 1,
|
||||||
|
GLX_GREEN_SIZE, 1,
|
||||||
|
GLX_BLUE_SIZE, 1,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
XVisualInfo *vi;
|
||||||
|
XSetWindowAttributes wa;
|
||||||
|
long win;
|
||||||
|
const char *extns;
|
||||||
|
|
||||||
|
/*---------------------------*/
|
||||||
|
lib_x11 = lib_load(lib_x11_files);
|
||||||
|
if (!lib_x11) goto err;
|
||||||
|
|
||||||
|
SYM(lib_x11, XOpenDisplay);
|
||||||
|
SYM(lib_x11, XCreateColormap);
|
||||||
|
SYM(lib_x11, XCreateWindow);
|
||||||
|
SYM(lib_x11, XCloseDisplay);
|
||||||
|
if (fail) goto err;
|
||||||
|
|
||||||
|
/*---------------------------*/
|
||||||
|
lib_gl = lib_load(lib_gl_files);
|
||||||
|
if (!lib_gl)
|
||||||
|
{
|
||||||
|
dlclose(lib_x11);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SYM(lib_gl, glXChooseFBConfig);
|
||||||
|
SYM(lib_gl, glXGetVisualFromFBConfig);
|
||||||
|
SYM(lib_gl, glXCreateNewContext);
|
||||||
|
SYM(lib_gl, glXCreateWindow);
|
||||||
|
SYM(lib_gl, glXMakeContextCurrent);
|
||||||
|
SYM(lib_gl, glXSwapBuffers);
|
||||||
|
SYM(lib_gl, glXQueryExtensionsString);
|
||||||
|
SYM(lib_gl, glXGetProcAddressARB);
|
||||||
|
if (fail) goto err;
|
||||||
|
|
||||||
|
/*---------------------------*/
|
||||||
|
disp = sym_XOpenDisplay(NULL);
|
||||||
|
if (!disp) goto err;
|
||||||
|
fbconfigs = sym_glXChooseFBConfig(disp, 0, attr, &num);
|
||||||
|
if (!fbconfigs) goto err;
|
||||||
|
vi = sym_glXGetVisualFromFBConfig(disp, fbconfigs[0]);
|
||||||
|
if (!vi) goto err;
|
||||||
|
wa.override_redirect = 1;
|
||||||
|
wa.border_pixel = 0;
|
||||||
|
wa.colormap = sym_XCreateColormap(disp, RootWindow(disp, vi->screen),
|
||||||
|
vi->visual, AllocNone);
|
||||||
|
if (!wa.colormap) goto err;
|
||||||
|
win = sym_XCreateWindow(disp, RootWindow(disp, vi->screen),
|
||||||
|
-77, -777, 1, 1, 0, vi->depth, InputOutput,
|
||||||
|
vi->visual,
|
||||||
|
CWBorderPixel | CWColormap | CWOverrideRedirect, &wa);
|
||||||
|
if (!win) goto err;
|
||||||
|
context = sym_glXCreateNewContext(disp, fbconfigs[0], GLX_RGBA_TYPE,
|
||||||
|
NULL, 1);
|
||||||
|
if (!context) goto err;
|
||||||
|
gwin = sym_glXCreateWindow(disp, fbconfigs[0], win, NULL);
|
||||||
|
if (!gwin) goto err;
|
||||||
|
extns = sym_glXQueryExtensionsString(disp, 0);
|
||||||
|
if (!extns) goto err;
|
||||||
|
if (!strstr(extns, "GLX_SGI_swap_control")) goto err;
|
||||||
|
sym_glXGetVideoSyncSGI = sym_glXGetProcAddressARB("glXGetVideoSyncSGI");
|
||||||
|
sym_glXWaitVideoSyncSGI = sym_glXGetProcAddressARB("glXWaitVideoSyncSGI");
|
||||||
|
if ((!sym_glXGetVideoSyncSGI) || (!sym_glXWaitVideoSyncSGI)) goto err;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
err:
|
||||||
|
if (disp) sym_XCloseDisplay(disp);
|
||||||
|
if (lib_gl) dlclose(lib_gl);
|
||||||
|
if (lib_x11) dlclose(lib_x11);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
_vsync_wait_glx(void)
|
||||||
|
{
|
||||||
|
double t;
|
||||||
|
unsigned int rc = 0;
|
||||||
|
|
||||||
|
sym_glXMakeContextCurrent(disp, gwin, gwin, context);
|
||||||
|
sym_glXGetVideoSyncSGI(&rc);
|
||||||
|
sym_glXWaitVideoSyncSGI(1, 0, &rc);
|
||||||
|
t = ecore_time_get();
|
||||||
|
return t;
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
#include "Ecore.h"
|
#include "Ecore.h"
|
||||||
#include "ecore_x_private.h"
|
#include "ecore_x_private.h"
|
||||||
#include "Ecore_X.h"
|
#include "Ecore_X.h"
|
||||||
|
#include "Ecore_Con.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -17,6 +18,12 @@
|
||||||
|
|
||||||
#define ECORE_X_VSYNC_DRI2 1
|
#define ECORE_X_VSYNC_DRI2 1
|
||||||
|
|
||||||
|
static Ecore_X_Window vsync_root = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef ECORE_X_VSYNC_DRI2
|
#ifdef ECORE_X_VSYNC_DRI2
|
||||||
// relevant header bits of dri/drm inlined here to avoid needing external
|
// relevant header bits of dri/drm inlined here to avoid needing external
|
||||||
// headers to build
|
// headers to build
|
||||||
|
@ -115,8 +122,6 @@ static Ecore_Fd_Handler *dri_drm_fdh = NULL;
|
||||||
static void *dri_lib = NULL;
|
static void *dri_lib = NULL;
|
||||||
static void *drm_lib = NULL;
|
static void *drm_lib = NULL;
|
||||||
|
|
||||||
static Window dri_drm_vsync_root = 0;
|
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
_dri_drm_tick_schedule(void)
|
_dri_drm_tick_schedule(void)
|
||||||
{
|
{
|
||||||
|
@ -151,6 +156,7 @@ _dri_drm_vblank_handler(int fd EINA_UNUSED,
|
||||||
{
|
{
|
||||||
if (drm_event_is_busy)
|
if (drm_event_is_busy)
|
||||||
{
|
{
|
||||||
|
// XXX: set looptime
|
||||||
ecore_animator_custom_tick();
|
ecore_animator_custom_tick();
|
||||||
_dri_drm_tick_schedule();
|
_dri_drm_tick_schedule();
|
||||||
}
|
}
|
||||||
|
@ -257,13 +263,13 @@ _dri_drm_init(void)
|
||||||
return 0;
|
return 0;
|
||||||
if (dri2_major < 2)
|
if (dri2_major < 2)
|
||||||
return 0;
|
return 0;
|
||||||
if (!sym_DRI2Connect(_ecore_x_disp, dri_drm_vsync_root, &driver_name, &device_name))
|
if (!sym_DRI2Connect(_ecore_x_disp, vsync_root, &driver_name, &device_name))
|
||||||
return 0;
|
return 0;
|
||||||
drm_fd = open(device_name, O_RDWR);
|
drm_fd = open(device_name, O_RDWR);
|
||||||
if (drm_fd < 0)
|
if (drm_fd < 0)
|
||||||
return 0;
|
return 0;
|
||||||
sym_drmGetMagic(drm_fd, &drm_magic);
|
sym_drmGetMagic(drm_fd, &drm_magic);
|
||||||
if (!sym_DRI2Authenticate(_ecore_x_disp, dri_drm_vsync_root, drm_magic))
|
if (!sym_DRI2Authenticate(_ecore_x_disp, vsync_root, drm_magic))
|
||||||
{
|
{
|
||||||
close(drm_fd);
|
close(drm_fd);
|
||||||
drm_fd = -1;
|
drm_fd = -1;
|
||||||
|
@ -307,55 +313,227 @@ _dri_drm_shutdown(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_dri_animator_tick_source_set(void)
|
||||||
|
{
|
||||||
|
if (vsync_root)
|
||||||
|
{
|
||||||
|
if (!_dri_drm_link())
|
||||||
|
{
|
||||||
|
ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
_dri_drm_shutdown();
|
||||||
|
if (!_dri_drm_init())
|
||||||
|
{
|
||||||
|
vsync_root = 0;
|
||||||
|
ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
ecore_animator_custom_source_tick_begin_callback_set
|
||||||
|
(_dri_drm_tick_begin, NULL);
|
||||||
|
ecore_animator_custom_source_tick_end_callback_set
|
||||||
|
(_dri_drm_tick_end, NULL);
|
||||||
|
ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (drm_fd >= 0)
|
||||||
|
{
|
||||||
|
_dri_drm_shutdown();
|
||||||
|
ecore_animator_custom_source_tick_begin_callback_set
|
||||||
|
(NULL, NULL);
|
||||||
|
ecore_animator_custom_source_tick_end_callback_set
|
||||||
|
(NULL, NULL);
|
||||||
|
ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static Ecore_Con_Server *vsync_server = NULL;
|
||||||
|
static Eina_Bool handlers = EINA_FALSE;
|
||||||
|
static Eina_Prefix *_prefix = NULL;
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
vsync_server_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Con_Event_Server_Add *ev = event;
|
||||||
|
if (ev->server != vsync_server) return EINA_TRUE;
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
vsync_server_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Con_Event_Server_Del *ev = event;
|
||||||
|
if (ev->server != vsync_server) return EINA_TRUE;
|
||||||
|
if (vsync_server)
|
||||||
|
{
|
||||||
|
ecore_con_server_del(vsync_server);
|
||||||
|
vsync_server = NULL;
|
||||||
|
ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL);
|
||||||
|
ecore_animator_custom_source_tick_end_callback_set(NULL, NULL);
|
||||||
|
ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
|
||||||
|
}
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
vsync_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
|
||||||
|
{
|
||||||
|
Ecore_Con_Event_Server_Data *ev = event;
|
||||||
|
int i;
|
||||||
|
double t;
|
||||||
|
char *d;
|
||||||
|
if (ev->server != vsync_server) return EINA_TRUE;
|
||||||
|
d = ev->data;;
|
||||||
|
for (i = 0; i < ev->size - (int)(sizeof(double) - 1); i++)
|
||||||
|
{
|
||||||
|
memcpy(&t, &(d[i]), sizeof(double));
|
||||||
|
ecore_loop_time_set(t);
|
||||||
|
ecore_animator_custom_tick();
|
||||||
|
}
|
||||||
|
return EINA_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vsync_tick_begin(void *data EINA_UNUSED)
|
||||||
|
{
|
||||||
|
char val = 1;
|
||||||
|
ecore_con_server_send(vsync_server, &val, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vsync_tick_end(void *data EINA_UNUSED)
|
||||||
|
{
|
||||||
|
char val = 0;
|
||||||
|
ecore_con_server_send(vsync_server, &val, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_glvsync_animator_tick_source_set(void)
|
||||||
|
{
|
||||||
|
if (!vsync_server)
|
||||||
|
{
|
||||||
|
char buf[4096], *disp, *s;
|
||||||
|
int tries = 0;
|
||||||
|
|
||||||
|
if (!handlers)
|
||||||
|
{
|
||||||
|
_prefix = eina_prefix_new(NULL, ecore_x_vsync_animator_tick_source_set,
|
||||||
|
"ECORE_X", "ecore_x", "checkme",
|
||||||
|
PACKAGE_BIN_DIR, PACKAGE_LIB_DIR,
|
||||||
|
PACKAGE_DATA_DIR, PACKAGE_DATA_DIR);
|
||||||
|
ecore_con_init();
|
||||||
|
}
|
||||||
|
disp = getenv("DISPLAY");
|
||||||
|
if (disp) disp = ":0";
|
||||||
|
snprintf(buf, sizeof(buf), "ecore-x-vsync-%s", disp);
|
||||||
|
for (s = buf; *s; s++)
|
||||||
|
{
|
||||||
|
if (*s == ':') *s = '=';
|
||||||
|
}
|
||||||
|
vsync_server = ecore_con_server_connect(ECORE_CON_LOCAL_USER, buf, 1, NULL);
|
||||||
|
while (!vsync_server)
|
||||||
|
{
|
||||||
|
tries++;
|
||||||
|
if (tries > 50) return EINA_FALSE;
|
||||||
|
snprintf(buf, sizeof(buf), "%s/ecore_x/bin/%s/ecore_x_vsync",
|
||||||
|
eina_prefix_lib_get(_prefix), MODULE_ARCH);
|
||||||
|
ecore_exe_run(buf, NULL);
|
||||||
|
usleep(10000);
|
||||||
|
vsync_server = ecore_con_server_connect(ECORE_CON_LOCAL_USER, buf, 0, NULL);
|
||||||
|
}
|
||||||
|
if (!handlers)
|
||||||
|
{
|
||||||
|
ecore_event_handler_add(ECORE_CON_EVENT_SERVER_ADD, vsync_server_add, NULL);
|
||||||
|
ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL, vsync_server_del, NULL);
|
||||||
|
ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA, vsync_server_data, NULL);
|
||||||
|
handlers = EINA_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vsync_root)
|
||||||
|
{
|
||||||
|
ecore_animator_custom_source_tick_begin_callback_set(vsync_tick_begin, NULL);
|
||||||
|
ecore_animator_custom_source_tick_end_callback_set(vsync_tick_end, NULL);
|
||||||
|
ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (vsync_server)
|
||||||
|
{
|
||||||
|
ecore_con_server_del(vsync_server);
|
||||||
|
vsync_server = NULL;
|
||||||
|
}
|
||||||
|
ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL);
|
||||||
|
ecore_animator_custom_source_tick_end_callback_set(NULL, NULL);
|
||||||
|
ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
|
||||||
|
}
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: missing mode 3 == separate x connection with compiled in dri2 proto
|
||||||
|
// handling ala mesa (taken from mesa likely)
|
||||||
|
|
||||||
|
static int mode = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
_vsync_init(void)
|
||||||
|
{
|
||||||
|
static int done = 0;
|
||||||
|
|
||||||
|
if (done) return;
|
||||||
|
|
||||||
|
#ifdef ECORE_X_VSYNC_DRI2
|
||||||
|
// preferred inline dri/drm if possible
|
||||||
|
if (_dri_drm_link())
|
||||||
|
{
|
||||||
|
_dri_drm_shutdown();
|
||||||
|
if (_dri_drm_init())
|
||||||
|
{
|
||||||
|
mode = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// nvidia gl vsync slave mode
|
||||||
|
if (mode == 0)
|
||||||
|
{
|
||||||
|
struct stat stb;
|
||||||
|
|
||||||
|
if (!stat("/dev/nvidiactl", &stb))
|
||||||
|
{
|
||||||
|
mode = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done = 1;
|
||||||
|
}
|
||||||
|
|
||||||
EAPI Eina_Bool
|
EAPI Eina_Bool
|
||||||
ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win)
|
ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win)
|
||||||
{
|
{
|
||||||
#ifdef ECORE_X_VSYNC_DRI2
|
|
||||||
Ecore_X_Window root;
|
Ecore_X_Window root;
|
||||||
|
|
||||||
root = ecore_x_window_root_get(win);
|
root = ecore_x_window_root_get(win);
|
||||||
if (root != dri_drm_vsync_root)
|
if (root != vsync_root)
|
||||||
{
|
{
|
||||||
dri_drm_vsync_root = root;
|
_vsync_init();
|
||||||
if (dri_drm_vsync_root)
|
vsync_root = root;
|
||||||
{
|
#ifdef ECORE_X_VSYNC_DRI2
|
||||||
if (!_dri_drm_link())
|
if (mode == 1) return _dri_animator_tick_source_set();
|
||||||
{
|
|
||||||
ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
|
||||||
_dri_drm_shutdown();
|
|
||||||
if (!_dri_drm_init())
|
|
||||||
{
|
|
||||||
dri_drm_vsync_root = 0;
|
|
||||||
ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
|
|
||||||
return EINA_FALSE;
|
|
||||||
}
|
|
||||||
ecore_animator_custom_source_tick_begin_callback_set
|
|
||||||
(_dri_drm_tick_begin, NULL);
|
|
||||||
ecore_animator_custom_source_tick_end_callback_set
|
|
||||||
(_dri_drm_tick_end, NULL);
|
|
||||||
ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
#endif
|
||||||
if (drm_fd >= 0)
|
if (mode == 2) return _glvsync_animator_tick_source_set();
|
||||||
{
|
else return EINA_FALSE;
|
||||||
_dri_drm_shutdown();
|
|
||||||
ecore_animator_custom_source_tick_begin_callback_set
|
|
||||||
(NULL, NULL);
|
|
||||||
ecore_animator_custom_source_tick_end_callback_set
|
|
||||||
(NULL, NULL);
|
|
||||||
ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
#else
|
|
||||||
return EINA_FALSE;
|
|
||||||
win = 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue