forked from enlightenment/efl
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.efl-1.11
parent
89d0e9f033
commit
2d63a70422
7 changed files with 808 additions and 46 deletions
@ -0,0 +1 @@ |
||||
This is just a test file used to help ecore determine its prefix location. |
@ -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; |
||||
} |
Loading…
Reference in new issue