efl/src/lib/ecore_x/ecore_x_vsync_tool.c

276 lines
5.9 KiB
C

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#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 Eina_Thread_Queue *thq = NULL;
static volatile int ticking = 0;
static void
_tick_core(void *data EINA_UNUSED, Ecore_Thread *thread)
{
Msg *msg;
void *ref;
int tick = 0;
for (;;)
{
if (!tick)
{
msg = eina_thread_queue_wait(thq, &ref);
if (msg)
{
tick = msg->val;
eina_thread_queue_wait_done(thq, ref);
}
}
else
{
do
{
msg = eina_thread_queue_poll(thq, &ref);
if (msg)
{
tick = msg->val;
eina_thread_queue_wait_done(thq, ref);
}
}
while (msg);
}
if (tick == -1) exit(0);
if (tick)
{
double *t;
t = malloc(sizeof(*t));
if (t)
{
*t = _vsync_wait();
do
{
msg = eina_thread_queue_poll(thq, &ref);
if (msg)
{
tick = msg->val;
eina_thread_queue_wait_done(thq, ref);
}
}
while (msg);
if (tick) 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)
{
ticking++;
if (ticking == 1) _tick_send(1);
}
static void
_tick_end(void)
{
if (ticking <= 0) return;
ticking--;
if (ticking == 0) _tick_send(0);
}
/*--------------------------------------------------------------------*/
typedef struct
{
Ecore_Con_Client *client;
int enabled;
} 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)
{
if (cdat->enabled > 0)
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)
{
while (cdat->enabled > 0)
{
cdat->enabled--;
if (cdat->enabled == 0) _tick_end();
}
clients = eina_list_remove(clients, cdat);
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;
int i;
int penabled = cdat->enabled;
for (i = 0; i < ev->size; i++)
{
if (dat[i]) cdat->enabled++;
else if (cdat->enabled > 0) cdat->enabled--;
}
if (ev->size > 0)
{
if (penabled != cdat->enabled)
{
if (cdat->enabled == 1) _tick_start();
else if (cdat->enabled == 0) _tick_end();
}
}
}
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 >= 'a') && (*s <= 'z')) ||
((*s >= 'A') && (*s <= 'Z')) ||
((*s >= '0') && (*s <= '9')))) *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;
}