forked from enlightenment/efl
265 lines
6.6 KiB
C
265 lines
6.6 KiB
C
#include "ecore_buffer_con.h"
|
|
|
|
#define DEBUG 1
|
|
|
|
typedef struct _Ecore_Buffer_Con Ecore_Buffer_Con;
|
|
|
|
struct _Ecore_Buffer_Con
|
|
{
|
|
struct wl_display *display;
|
|
struct wl_registry *registry;
|
|
struct bq_mgr *bq_mgr;
|
|
Ecore_Fd_Handler *fd_hdl;
|
|
Ecore_Idle_Enterer *idle_enterer;
|
|
int fd;
|
|
Eina_Bool init_done;
|
|
};
|
|
|
|
static Eina_Bool _connection_fatal_error = EINA_FALSE;
|
|
Ecore_Buffer_Con *_connection = NULL;
|
|
|
|
static void
|
|
_ecore_buffer_con_cb_registry_global(void *data, struct wl_registry *wl_registry, uint32_t id, const char *interface, uint32_t version)
|
|
{
|
|
Ecore_Buffer_Con *conn = data;
|
|
|
|
DBG("Added Wl Global Registry - name %d interface %s version %d",
|
|
id, interface, version);
|
|
|
|
if (!strncmp(interface, "bq_mgr", strlen("bq_mgr")))
|
|
{
|
|
conn->bq_mgr =
|
|
wl_registry_bind(wl_registry, id, &bq_mgr_interface, 1);
|
|
}
|
|
}
|
|
|
|
static void
|
|
_ecore_buffer_con_cb_registry_global_remove(void *data EINA_UNUSED, struct wl_registry *wl_registry EINA_UNUSED, uint32_t name EINA_UNUSED)
|
|
{
|
|
DBG("Removed Wl Global Registry - name %d", name);
|
|
}
|
|
|
|
static void
|
|
_ecore_buffer_con_signal_exit_free(void *data EINA_UNUSED, void *event)
|
|
{
|
|
free(event);
|
|
}
|
|
|
|
static void
|
|
_ecore_buffer_con_signal_exit(void)
|
|
{
|
|
Ecore_Event_Signal_Exit *ev;
|
|
|
|
if (!(ev = calloc(1, sizeof(Ecore_Event_Signal_Exit))))
|
|
return;
|
|
|
|
ev->quit = 1;
|
|
ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, ev,
|
|
_ecore_buffer_con_signal_exit_free, NULL);
|
|
}
|
|
|
|
static Eina_Bool
|
|
_ecore_buffer_con_cb_idle_enterer(void *data)
|
|
{
|
|
Ecore_Buffer_Con *conn;
|
|
int ret = 0;
|
|
|
|
if (_connection_fatal_error) return ECORE_CALLBACK_CANCEL;
|
|
|
|
if (!(conn = data)) return ECORE_CALLBACK_RENEW;
|
|
|
|
ret = wl_display_get_error(conn->display);
|
|
if (ret < 0) goto err;
|
|
|
|
ret = wl_display_flush(conn->display);
|
|
if ((ret < 0) && (errno == EAGAIN))
|
|
ecore_main_fd_handler_active_set(conn->fd_hdl,
|
|
(ECORE_FD_READ | ECORE_FD_WRITE));
|
|
|
|
ret = wl_display_dispatch_pending(conn->display);
|
|
if (ret < 0) goto err;
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
|
|
err:
|
|
if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
|
|
{
|
|
_connection_fatal_error = EINA_TRUE;
|
|
|
|
/* raise exit signal */
|
|
_ecore_buffer_con_signal_exit();
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
}
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static Eina_Bool
|
|
_ecore_buffer_con_cb_fd_handle(void *data, Ecore_Fd_Handler *hdl)
|
|
{
|
|
Ecore_Buffer_Con *conn = data;
|
|
int ret = 0;
|
|
|
|
if (_connection_fatal_error) return ECORE_CALLBACK_CANCEL;
|
|
if (!conn) return ECORE_CALLBACK_RENEW;
|
|
|
|
if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_ERROR))
|
|
{
|
|
ERR("Received error on wayland display fd");
|
|
_connection_fatal_error = EINA_TRUE;
|
|
_ecore_buffer_con_signal_exit();
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
}
|
|
|
|
if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_READ))
|
|
ret = wl_display_dispatch(conn->display);
|
|
else if (ecore_main_fd_handler_active_get(hdl, ECORE_FD_WRITE))
|
|
{
|
|
ret = wl_display_flush(conn->display);
|
|
if (ret == 0)
|
|
ecore_main_fd_handler_active_set(hdl, ECORE_FD_READ);
|
|
}
|
|
|
|
if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
|
|
{
|
|
_connection_fatal_error = EINA_TRUE;
|
|
|
|
/* raise exit signal */
|
|
_ecore_buffer_con_signal_exit();
|
|
|
|
return ECORE_CALLBACK_CANCEL;
|
|
}
|
|
|
|
return ECORE_CALLBACK_RENEW;
|
|
}
|
|
|
|
static void
|
|
_ecore_buffer_con_init_callback(void *data, struct wl_callback *callback, uint32_t serial EINA_UNUSED)
|
|
{
|
|
Ecore_Buffer_Con *conn = data;
|
|
|
|
DBG("Queue Server Connected");
|
|
|
|
if (!conn)
|
|
return;
|
|
|
|
wl_callback_destroy(callback);
|
|
conn->init_done = EINA_TRUE;
|
|
}
|
|
|
|
static const struct wl_callback_listener _ecore_buffer_con_init_sync_listener =
|
|
{
|
|
_ecore_buffer_con_init_callback
|
|
};
|
|
|
|
struct wl_registry_listener _ecore_buffer_registry_listener =
|
|
{
|
|
_ecore_buffer_con_cb_registry_global,
|
|
_ecore_buffer_con_cb_registry_global_remove
|
|
};
|
|
|
|
Eina_Bool
|
|
_ecore_buffer_con_init(void)
|
|
{
|
|
struct wl_callback *callback;
|
|
const char *name = "bq_mgr_daemon";
|
|
|
|
DBG("Ecore_Buffer_Con Init - name %s", name);
|
|
|
|
_connection = calloc(1, sizeof(Ecore_Buffer_Con));
|
|
if (!_connection)
|
|
{
|
|
ERR("Failed to allocation");
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
if (!(_connection->display = wl_display_connect(name)))
|
|
{
|
|
ERR("Failed to connect to Queue Server");
|
|
goto err_connect;
|
|
}
|
|
|
|
_connection->fd = wl_display_get_fd(_connection->display);
|
|
_connection->fd_hdl =
|
|
ecore_main_fd_handler_add(_connection->fd,
|
|
ECORE_FD_READ | ECORE_FD_WRITE | ECORE_FD_ERROR,
|
|
_ecore_buffer_con_cb_fd_handle,
|
|
_connection, NULL, NULL);
|
|
|
|
_connection->idle_enterer =
|
|
ecore_idle_enterer_add(_ecore_buffer_con_cb_idle_enterer, _connection);
|
|
|
|
if (!(_connection->registry = wl_display_get_registry(_connection->display)))
|
|
goto err_get_registry;
|
|
|
|
wl_registry_add_listener(_connection->registry,
|
|
&_ecore_buffer_registry_listener, _connection);
|
|
|
|
_connection->init_done = EINA_FALSE;
|
|
callback = wl_display_sync(_connection->display);
|
|
wl_callback_add_listener(callback, &_ecore_buffer_con_init_sync_listener,
|
|
_connection);
|
|
|
|
return EINA_TRUE;;
|
|
err_get_registry:
|
|
wl_display_disconnect(_connection->display);
|
|
err_connect:
|
|
free(_connection);
|
|
return EINA_FALSE;
|
|
}
|
|
|
|
void
|
|
_ecore_buffer_con_shutdown(void)
|
|
{
|
|
if (!_connection) return;
|
|
|
|
DBG("Ecore_Buffer_Con Shutdown");
|
|
|
|
if (_connection->fd_hdl)
|
|
ecore_main_fd_handler_del(_connection->fd_hdl);
|
|
|
|
if (_connection->idle_enterer)
|
|
ecore_idle_enterer_del(_connection->idle_enterer);
|
|
|
|
if (_connection->bq_mgr)
|
|
bq_mgr_destroy(_connection->bq_mgr);
|
|
|
|
if (_connection->display)
|
|
wl_display_disconnect(_connection->display);
|
|
|
|
free(_connection);
|
|
_connection = NULL;
|
|
}
|
|
|
|
struct bq_provider *
|
|
_ecore_buffer_con_provider_create(const char *name)
|
|
{
|
|
return bq_mgr_create_provider(_connection->bq_mgr, name);
|
|
}
|
|
|
|
struct bq_consumer *
|
|
_ecore_buffer_con_consumer_create(const char *name, int queue_size, int w, int h)
|
|
{
|
|
return bq_mgr_create_consumer(_connection->bq_mgr, name, queue_size, w, h);
|
|
}
|
|
|
|
void
|
|
_ecore_buffer_con_init_wait(void)
|
|
{
|
|
int ret;
|
|
|
|
while (!_connection->init_done)
|
|
{
|
|
ret = wl_display_dispatch(_connection->display);
|
|
if ((ret < 0) && ((errno != EAGAIN) && (errno != EINVAL)))
|
|
{
|
|
/* raise exit signal */
|
|
ERR("Wayland socket error: %s", strerror(errno));
|
|
abort();
|
|
break;
|
|
}
|
|
}
|
|
}
|