#include "e_mod_main.h"
#include "eom-server-protocol.h"
#include "Ecore_Drm.h"
+#include <wayland-tbm-server.h>
E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "EOM Module" };
-static E_EomEventData g_eom_event_data;
-static E_EomFakeBuffers fake_buffers;
static E_EomPtr g_eom = NULL;
+static const struct wl_eom_interface _e_eom_wl_implementation =
+{
+ _e_eom_cb_wl_request_set_attribute,
+ _e_eom_cb_wl_request_get_output_info
+};
+
/* EOM Output Attributes
+----------------+------------+----------------+-------------+
"DSI",
};
-static inline enum wl_eom_mode
-_e_eom_get_eom_mode()
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static inline eom_output_mode_e
+_e_eom_output_state_get_mode(E_EomOutputPtr output)
{
- return g_eom->eom_mode;
+ if (output == NULL)
+ return EOM_OUTPUT_MODE_NONE;
+ return output->mode;
}
static inline void
-_e_eom_set_eom_mode(enum wl_eom_mode mode)
+_e_eom_output_state_set_mode(E_EomOutputPtr output, eom_output_mode_e mode)
{
- g_eom->eom_mode = mode;
+ if (output == NULL)
+ return;
+ output->mode = mode;
}
-static inline enum wl_eom_attribute_state
-_e_eom_get_eom_attribute_state()
+static inline eom_output_attribute_e
+_e_eom_output_state_get_attribute_state(E_EomOutputPtr output)
{
- return g_eom->eom_attribute_state;
+ if (output == NULL)
+ return EOM_OUTPUT_ATTRIBUTE_STATE_NONE;
+ return output->attribute_state;
}
static inline void
-_e_eom_set_eom_attribute_state(enum wl_eom_attribute_state attribute_state)
+_e_eom_output_attribute_state_set(E_EomOutputPtr output, eom_output_attribute_e attribute_state)
{
- g_eom->eom_attribute_state = attribute_state;
+ if (output == NULL)
+ return;
+ output->attribute_state = attribute_state;
}
-static inline enum wl_eom_attribute
-_e_eom_get_eom_attribute()
+static inline eom_output_attribute_e
+_e_eom_output_state_get_attribute(E_EomOutputPtr output)
{
- return g_eom->eom_attribute;
+ if (output == NULL)
+ return EOM_OUTPUT_ATTRIBUTE_NONE;
+ return output->attribute;
}
static inline void
-_e_eom_set_eom_attribute_by_current_client(enum wl_eom_attribute attribute)
+_e_eom_output_state_set_force_attribute(E_EomOutputPtr output, eom_output_attribute_e attribute)
{
- g_eom->eom_attribute = attribute;
+ if (output == NULL)
+ return;
+ output->attribute = attribute;
}
static inline Eina_Bool
-_e_eom_set_eom_attribute(enum wl_eom_attribute attribute)
+_e_eom_output_state_set_attribute(E_EomOutputPtr output, eom_output_attribute_e attribute)
{
- if (attribute == WL_EOM_ATTRIBUTE_NONE || g_eom->eom_attribute == WL_EOM_ATTRIBUTE_NONE)
+ if (output == NULL)
+ return EINA_FALSE;
+
+ if (attribute == EOM_OUTPUT_ATTRIBUTE_NONE || output->attribute == EOM_OUTPUT_ATTRIBUTE_NONE)
{
- g_eom->eom_attribute = attribute;
+ output->attribute = attribute;
return EINA_TRUE;
}
- if (eom_output_attributes[g_eom->eom_attribute - 1][attribute - 1] == 1)
+ if (eom_output_attributes[output->attribute - 1][attribute - 1] == 1)
{
- g_eom->eom_attribute = attribute;
+ output->attribute = attribute;
return EINA_TRUE;
}
return EINA_FALSE;
}
-static inline enum wl_eom_status
-_e_eom_get_eom_status()
+static inline tdm_output_conn_status
+_e_eom_output_state_get_status(E_EomOutputPtr output)
{
- return g_eom->eom_status;
+ if (output == NULL)
+ return TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+ return output->status;
}
static inline void
-_e_eom_set_eom_status(enum wl_eom_status status)
+_e_eom_output_state_set_status(E_EomOutputPtr output, tdm_output_conn_status status)
{
- g_eom->eom_status = status;
+ if (output == NULL)
+ return;
+ output->status = status;
}
static void
-_e_eom_pp_cb(tbm_surface_h surface, void *user_data)
+_e_eom_cb_wl_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
{
- tdm_error tdm_err = TDM_ERROR_NONE;
- E_EomEventDataPtr eom_data = NULL;
+ struct wl_resource *resource = NULL;
+ E_EomClientPtr new_client = NULL;
- RETURNIFTRUE(user_data == NULL, "ERROR: PP EVENT: user data is NULL");
+ RETURNIFTRUE(data == NULL, "ERROR: data is NULL");
- eom_data = (E_EomEventDataPtr)user_data;
+ E_EomPtr eom = data;
- tdm_buffer_remove_release_handler(eom_data->dst_buffers[eom_data->pp_buffer],
- _e_eom_pp_cb, eom_data);
+ resource = wl_resource_create(client,
+ &wl_eom_interface,
+ MIN(version, 1),
+ id);
+ if (resource == NULL)
+ {
+ EOM_ERR("error. resource is null. (version :%d, id:%d)\n", version, id);
+ wl_client_post_no_memory(client);
+ return;
+ }
- /* Stop EOM */
- if (g_eom->eom_sate != UP)
- return;
+ wl_resource_set_implementation(resource,
+ &_e_eom_wl_implementation,
+ eom,
+ _e_eom_cb_wl_resource_destory);
- /* TODO: lock that flag??? */
- /* If a client has committed its buffer stop mirror mode */
- if (g_eom->is_mirror_mode == DOWN)
- return;
+ EOM_DBG("send - output count : %d\n", g_eom->output_count);
- tbm_surface_h src_buffer;
- src_buffer = _e_eom_root_internal_tdm_surface_get(g_eom->int_output_name);
- RETURNIFTRUE(src_buffer == NULL, "ERROR: PP EVENT: get root tdm surface");
+ wl_eom_send_output_count(resource, g_eom->output_count);
- g_eom_event_data.pp_buffer = !g_eom_event_data.current_buffer;
+ if (g_eom->outputs)
+ {
+ Eina_List *l;
+ E_EomOutputPtr output = NULL;
- tdm_err = tdm_buffer_add_release_handler(g_eom_event_data.dst_buffers[g_eom_event_data.pp_buffer],
- _e_eom_pp_cb, &g_eom_event_data);
- RETURNIFTRUE(tdm_err != TDM_ERROR_NONE, "ERROR: PP EVENT: set pp hadler:%d", tdm_err );
+ EINA_LIST_FOREACH(g_eom->outputs, l, output)
+ {
+ EOM_DBG("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d\n",
+ output->id, output->type, output->mode, output->width, output->height,
+ output->phys_width, output->phys_height, output->status);
+ wl_eom_send_output_info(resource, output->id, output->type, output->mode, output->width, output->height,
+ output->phys_width, output->phys_height, output->status);
- tdm_err = tdm_pp_attach(eom_data->pp, src_buffer, g_eom_event_data.dst_buffers[g_eom_event_data.pp_buffer]);
- RETURNIFTRUE(tdm_err != TDM_ERROR_NONE, "ERROR: pp attach:%d\n", tdm_err);
+ wl_eom_send_output_attribute(resource,
+ output->id,
+ _e_eom_output_state_get_attribute(output),
+ _e_eom_output_state_get_attribute_state(output),
+ EOM_ERROR_NONE);
+ }
+ }
- tdm_err = tdm_pp_commit(g_eom_event_data.pp);
- RETURNIFTRUE(tdm_err != TDM_ERROR_NONE, "ERROR: PP EVENT: pp commit:%d", tdm_err );
+ new_client = E_NEW(E_EomClient, 1);
+ if (new_client == NULL)
+ {
+ EOM_ERR("allocate new client");
+ /*TODO: should resource be deleted?*/
+ return;
+ }
+
+ new_client->resource = resource;
+ new_client->current = EINA_FALSE;
+ new_client->output_id = -1;
+ new_client->buffers = NULL;
+
+ g_eom->clients = eina_list_append(g_eom->clients, new_client);
}
static void
-_e_eom_commit_cb(tdm_output *output EINA_UNUSED, unsigned int sequence EINA_UNUSED,
- unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED,
- void *user_data)
+_e_eom_cb_wl_resource_destory(struct wl_resource *resource)
{
- E_EomClientBufferPtr client_buffer = NULL;
- E_EomEventDataPtr eom_data = NULL;
- tdm_error err = TDM_ERROR_NONE;
-
- RETURNIFTRUE(user_data == NULL, "ERROR: PP EVENT: user data is NULL");
-
- eom_data = (E_EomEventDataPtr)user_data;
+ E_EomClientPtr client = NULL, iterator = NULL;
+ E_EomOutputPtr output = NULL;
+ Eina_List *l = NULL;
+ Eina_Bool ret;
- /* Stop EOM */
- if (g_eom->eom_sate != UP)
- return;
+ EOM_DBG("client unbind\n");
- /* TODO: Maybe better to separating that callback on to mirror and extended callbacks */
- if (g_eom->is_mirror_mode == UP)
- {
- if (eom_data->current_buffer == 1)
- {
- eom_data->current_buffer = 0;
-
- err = tdm_layer_set_buffer(eom_data->layer,
- eom_data->dst_buffers[!eom_data->pp_buffer]);
- RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: EVENT: set buffer 0 err:%d", err);
- }
- else
- {
- eom_data->current_buffer = 1;
-
- err = tdm_layer_set_buffer(eom_data->layer,
- eom_data->dst_buffers[!eom_data->pp_buffer]);
- RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: EVENT: set buffer 1 err:%d", err);
- }
-
- err = tdm_output_commit(eom_data->output, 0, _e_eom_commit_cb, eom_data);
- RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: EVENT commit");
- }
- else
- {
- client_buffer = _e_eom_get_client_buffer_from_list();
- RETURNIFTRUE(client_buffer == NULL, "ERROR: EVENT: client buffer is NULL");
+ client = _e_eom_client_get_by_resource(resource);
+ RETURNIFTRUE(client == NULL, "destroy client: client is NULL");
- err = tdm_layer_set_buffer(eom_data->layer, client_buffer->tbm_buffer);
- RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: EVENT: set buffer 1");
+ g_eom->clients = eina_list_remove(g_eom->clients, client);
- err = tdm_output_commit(eom_data->output, 0, _e_eom_commit_cb, eom_data);
- RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: EVENT: commit");
- }
-}
+ /* If it is not current client do nothing */
+ GOTOIFTRUE(client->current == EINA_FALSE, end2, "");
-static void
-_e_eom_deinit_external_output()
-{
- tdm_error err = TDM_ERROR_NONE;
- int i = 0;
+ output = _e_eom_output_get_by_id(client->output_id);
+ GOTOIFTRUE(output == NULL, end2, "destroy client: client is NULL");
- if (g_eom_event_data.layer)
- {
- err = tdm_layer_unset_buffer(g_eom_event_data.layer);
- if (err != TDM_ERROR_NONE)
- EOM_DBG("EXT OUTPUT DEINIT: fail unset buffer:%d\n", err);
- else
- EOM_DBG("EXT OUTPUT DEINIT: ok unset buffer:%d\n", err);
+ _e_eom_client_free_buffers(client);
- err = tdm_output_commit(g_eom_event_data.output, 0, NULL, &g_eom_event_data);
- if (err != TDM_ERROR_NONE)
- EOM_DBG ("EXT OUTPUT DEINIT: fail commit:%d\n", err);
- else
- EOM_DBG("EXT OUTPUT DEINIT: ok commit:%d\n", err);
- }
+ _e_eom_output_state_set_mode(output, EOM_OUTPUT_MODE_MIRROR);
+ ret = _e_eom_output_state_set_attribute(output, EOM_OUTPUT_ATTRIBUTE_NONE);
+ (void)ret;
- /* TODO: do I need to do DPMS off? */
- err = tdm_output_set_dpms(g_eom_event_data.output, TDM_OUTPUT_DPMS_OFF);
- if (err != TDM_ERROR_NONE)
- EOM_ERR("EXT OUTPUT DEINIT: failed set DPMS off:%d\n", err);
+ /* TODO: process case when output is not connected */
+ if (output->state == NONE)
+ goto end;
- for (i = 0; i < NUM_MAIN_BUF; i++)
+ /* If a client has been disconnected and mirror mode has not
+ * been restored, start mirror mode
+ */
+ if (output->state != MIRROR)
{
- tdm_buffer_remove_release_handler(g_eom_event_data.dst_buffers[i],
- _e_eom_pp_cb, &g_eom_event_data);
- if (g_eom_event_data.dst_buffers[i])
- tbm_surface_destroy(g_eom_event_data.dst_buffers[i]);
- }
+ output->state = MIRROR;
- if (g_eom->eom_sate == DOWN)
- _e_eom_client_buffers_list_free(g_eom->eom_clients);
+ ret = _e_eom_output_start_pp(output);
+ GOTOIFTRUE(ret == EINA_FALSE, end,
+ "ERROR: restore mirror mode after a client disconnection\n");
+ }
- if (g_eom->int_output_name)
+end:
+ /* Notify eom clients which are binded to a concrete output that the
+ * state and mode of the output has been changed */
+ EINA_LIST_FOREACH(g_eom->clients, l, iterator)
{
- free(g_eom->int_output_name);
- g_eom->int_output_name = NULL;
+ if (iterator && iterator->output_id == output->id)
+ {
+ wl_eom_send_output_attribute(iterator->resource,
+ output->id,
+ _e_eom_output_state_get_attribute(output),
+ _e_eom_output_state_get_attribute_state(output),
+ EOM_OUTPUT_MODE_NONE);
+
+ wl_eom_send_output_mode(iterator->resource,
+ output->id,
+ _e_eom_output_state_get_mode(output));
+ }
}
- if (g_eom->ext_output_name)
- {
- free(g_eom->ext_output_name);
- g_eom->ext_output_name = NULL;
- }
-
- if (g_eom->wl_output)
- g_eom->wl_output = NULL;
+end2:
+ free(client);
}
-
-static tdm_layer *
-_e_eom_hal_layer_get(tdm_output *output, int width, int height)
+static Eina_Bool
+_e_eom_cb_ecore_drm_output(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
- int i = 0;
- int count = 0;
- tdm_layer *layer = NULL;
- tdm_error err = TDM_ERROR_NONE;
- tdm_layer_capability capa;
- tdm_info_layer layer_info;
+ Ecore_Drm_Event_Output *e = NULL;
+ char buff[PATH_MAX];
+
+ if (!(e = event)) return ECORE_CALLBACK_PASS_ON;;
+ EOM_DBG("id:%d (x,y,w,h):(%d,%d,%d,%d) (w_mm,h_mm):(%d,%d) refresh:%d subpixel_order:%d transform:%d make:%s model:%s name:%s plug:%d\n",
+ e->id, e->x, e->y, e->w, e->h, e->phys_width, e->phys_height, e->refresh, e->subpixel_order, e->transform, e->make, e->model, e->name, e->plug);
- err = tdm_output_get_layer_count(output, &count);
- if (err != TDM_ERROR_NONE)
- {
- EOM_DBG ("tdm_output_get_layer_count fail(%d)\n", err);
- return NULL;
- }
+ snprintf(buff, sizeof(buff), "%s", e->name);
- for (i = 0; i < count; i++)
+ /* main output */
+ if (e->id == 0)
{
- layer = (tdm_layer *)tdm_output_get_layer(output, i, &err);
- RETURNVALIFTRUE(err != TDM_ERROR_NONE, NULL, "tdm_output_get_layer fail(%d)\n", err);
-
- err = tdm_layer_get_capabilities(layer, &capa);
- RETURNVALIFTRUE(err != TDM_ERROR_NONE, NULL, "tdm_layer_get_capabilities fail(%d)\n", err);
+ if (e->plug == 1)
+ {
+ g_eom->width = e->w;
+ g_eom->height = e->h;
+ if (g_eom->main_output_name == NULL)
+ g_eom->main_output_name = strdup(buff);
- if (capa & TDM_LAYER_CAPABILITY_PRIMARY)
+ g_eom->main_output_state = UP;
+ }
+ else
{
- EOM_DBG("TDM_LAYER_CAPABILITY_PRIMARY layer found : %d\n", i);
- break;
+ g_eom->width = -1;
+ g_eom->height = -1;
+ if (g_eom->main_output_name)
+ free(g_eom->main_output_name);
+
+ g_eom->main_output_state = DOWN;
}
}
- memset(&layer_info, 0x0, sizeof(tdm_info_layer));
- layer_info.src_config.size.h = width;
- layer_info.src_config.size.v = height;
- layer_info.src_config.pos.x = 0;
- layer_info.src_config.pos.y = 0;
- layer_info.src_config.pos.w = width;
- layer_info.src_config.pos.h = height;
- layer_info.src_config.format = TBM_FORMAT_ARGB8888;
- layer_info.dst_pos.x = 0;
- layer_info.dst_pos.y = 0;
- layer_info.dst_pos.w = width;
- layer_info.dst_pos.h = height;
- layer_info.transform = TDM_TRANSFORM_NORMAL;
-
- err = tdm_layer_set_info(layer, &layer_info);
- RETURNVALIFTRUE(err != TDM_ERROR_NONE, NULL, "tdm_layer_set_info fail(%d)\n", err);
-
- return layer;
+ return ECORE_CALLBACK_PASS_ON;
}
-/* TODO: Models commited clients buffers */
-/*
-static void
-_e_eom_create_fake_buffers(int width, int height)
+static Eina_Bool
+_e_eom_cb_ecore_drm_activate(void *data, int type EINA_UNUSED, void *event)
{
- tbm_surface_info_s buffer_info;
- tbm_surface_h buffer = NULL;
+ /*
+ Ecore_Drm_Event_Activate *e = NULL;
+ E_EomPtr eom = NULL;
- buffer = tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
- GOTOIFTRUE(buffer == NULL, err, "can not create fake_buffer\n");
+ EOM_DBG("_e_eom_cb_ecore_drm_activate called\n");
- memset(&buffer_info, 0x0, sizeof(tbm_surface_info_s));
- if (tbm_surface_map(buffer,
- TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
- &buffer_info) != TBM_SURFACE_ERROR_NONE)
+ if ((!event) || (!data)) goto end;
+ e = event;
+ eom = data;
+
+ EOM_DBG("e->active:%d\n", e->active);
+
+ if (e->active)
{
- EOM_DBG("can not mmap fake_buffer\n");
- goto err;
+ ;
+ }
+ else
+ {
+ ;
}
- memset(buffer_info.planes[0].ptr, 0xFF, buffer_info.planes[0].size);
- tbm_surface_unmap(buffer);
-
- fake_buffers.fake_buffers[0] = buffer;
+end:
-err:
- return;
-}
*/
+ return ECORE_CALLBACK_PASS_ON;
+}
static Eina_Bool
-_e_eom_create_output_buffers(E_EomEventDataPtr eom_data, int width, int height)
+_e_eom_cb_client_buffer_change(void *data, int type, void *event)
{
- tbm_surface_info_s buffer_info;
- tbm_surface_h buffer = NULL;
-
- /*
- * TODO: Add support of other formats
- */
- buffer = tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
- GOTOIFTRUE(buffer == NULL, err, "can not create dst_buffer 1");
+ E_Comp_Wl_Buffer *external_wl_buffer = NULL;
+ E_EomClientBufferPtr client_buffer = NULL;
+ E_EomClientPtr client = NULL;
+ E_EomOutputPtr output = NULL;
+ E_Event_Client *ev = event;
+ E_Client *ec = NULL;
+ const char *output_name = NULL;
+ tbm_surface_h external_tbm_buffer = NULL;
+/*
+ tbm_surface_info_s surface_info;
+ int ret;
+*/
- /*
- * TODO: temp code for testing, actual convert will be in _e_eom_put_src_to_dst()
- */
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
- memset(&buffer_info, 0x0, sizeof(tbm_surface_info_s));
- if (tbm_surface_map(buffer,
- TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
- &buffer_info) != TBM_SURFACE_ERROR_NONE)
+ ec = ev->ec;
+ if (e_object_is_del(E_OBJECT(ec)))
{
- EOM_DBG("can not mmap buffer\n");
- goto err;
+ EOM_ERR("ERROR: BUFF CHANGE: ec objects is del\n");
+ return ECORE_CALLBACK_PASS_ON;
}
- memset(buffer_info.planes[0].ptr, 0x0, buffer_info.planes[0].size);
- tbm_surface_unmap(buffer);
+ /* TODO: implemente new client's buffers hooking mechanism */
+ return ECORE_CALLBACK_PASS_ON;
- eom_data->dst_buffers[0] = buffer;
+ output = _e_eom_output_get_by_name(output_name);
+ RETURNVALIFTRUE(output == NULL,
+ ECORE_CALLBACK_PASS_ON,
+ "ERROR:BUFF CHANGE: eom_output is NULL\n");
- /*
- * TODO: Add support of other formats
- */
- buffer = tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
- GOTOIFTRUE(buffer == NULL, err, "can not create dst_buffer 2");
+ if (ec->pixmap == NULL)
+ return ECORE_CALLBACK_PASS_ON;
- /*
- * TODO: temp code for testing, actual convert will be in _e_eom_put_src_to_dst()
- */
- memset(&buffer_info, 0x00, sizeof(tbm_surface_info_s));
- if (tbm_surface_map(buffer,
- TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
- &buffer_info) != TBM_SURFACE_ERROR_NONE)
+ external_wl_buffer = e_pixmap_resource_get(ec->pixmap);
+ RETURNVALIFTRUE(external_wl_buffer == NULL,
+ ECORE_CALLBACK_PASS_ON,
+ "ERROR:BUFF CHANGE: wl buffer is NULL\n");
+/*
+ EOM_DBG("BUFF CHANGE: wl_buff:%dx%d type:%d",
+ external_wl_buffer->w,
+ external_wl_buffer->h,
+ external_wl_buffer->type);
+*/
+
+ /* TODO: support buffers smaller then output resolution */
+ if (external_wl_buffer->w != output->width ||
+ external_wl_buffer->h != output->height )
{
- EOM_DBG("can not mmap buffer\n");
- goto err;
+ EOM_ERR("BUFF CHANGE: ERROR: tbm_buffer does not fit output's resolution");
+ return ECORE_CALLBACK_PASS_ON;
}
- memset(buffer_info.planes[0].ptr, 0x0, buffer_info.planes[0].size);
- tbm_surface_unmap(buffer);
-
- eom_data->dst_buffers[1] = buffer;
+ /* TODO: support different external_wl_buffer->type */
- return EINA_TRUE;
+ if (external_wl_buffer->resource == NULL)
+ {
+ EOM_ERR("ERROR: BUFF CHANGE: resource is NULL\n");
+ return ECORE_CALLBACK_PASS_ON;
+ }
-err:
+ external_tbm_buffer = wayland_tbm_server_get_surface(
+ e_comp->wl_comp_data->tbm.server,
+ external_wl_buffer->resource);
+ if (external_tbm_buffer == NULL)
+ {
+ EOM_ERR("ERROR: BUFF CHANGE: client tbm buffer is NULL\n");
+ return ECORE_CALLBACK_PASS_ON;
+ }
-/*
- * Add deinitialization
- */
- return EINA_FALSE;
-}
+ EOM_DBG("BUFF CHANGE: tbm_buffer %p", external_tbm_buffer);
-static enum wl_eom_type
-_e_eom_output_name_to_eom_type(const char *output_name)
-{
- enum wl_eom_type eom_type;
+#if 0
+ _e_eom_util_draw(external_tbm_buffer);
+#endif
- if (output_name == NULL)
- return WL_EOM_TYPE_NONE;
+ /* mmap that buffer to get width and height for test's sake */
+ /*
+ memset(&surface_info, 0, sizeof(tbm_surface_info_s));
+ ret = tbm_surface_map(external_tbm_buffer, TBM_SURF_OPTION_READ |
+ TBM_SURF_OPTION_WRITE, &surface_info);
+ if (ret != TBM_SURFACE_ERROR_NONE)
+ {
+ EOM_ERR("BUFF CHANGE: failed mmap buffer: %d", ret);
+ return ECORE_CALLBACK_PASS_ON;
+ }
- /* TODO: Add other external outputs */
- if (strcmp(output_name, "HDMI-A-0") == 0)
- eom_type = WL_EOM_TYPE_HDMIA;
- else
- eom_type = WL_EOM_TYPE_NONE;
+ EOM_DBG("BUFF CHANGE: tbm_buffer: %dx%d", surface_info.width, surface_info.height);
- return eom_type;
+ tbm_surface_unmap(external_tbm_buffer);
+ */
+
+ client_buffer = _e_eom_util_create_client_buffer(external_wl_buffer, external_tbm_buffer);
+ /* client_buffer = _e_eom_util_create_client_buffer(external_wl_buffer, output->fake_buffer); */
+ RETURNVALIFTRUE(client_buffer == NULL,
+ ECORE_CALLBACK_PASS_ON,
+ "ERROR: BUFF CHANGE: alloc client buffer");
+
+ /* TODO: What if not current client has committed a buffer */
+ client = _e_eom_client_current_by_id_get(output->id);
+ if (client == NULL)
+ {
+ EOM_ERR("ERROR: BUFF CHANGE: current client is NULL");
+ E_FREE(client_buffer);
+ return ECORE_CALLBACK_PASS_ON;
+ }
+
+ _e_eom_client_add_buffer(client, client_buffer);
+
+ output->state = PRESENTATION;
+
+ return ECORE_CALLBACK_PASS_ON;
}
-static Eina_Bool
-_e_eom_mirror_start(const char *output_name, int width, int height)
+static void
+_e_eom_cb_pp(tbm_surface_h surface, void *user_data)
{
- /* should be changed in HWC enable environment */
- tbm_surface_info_s src_buffer_info;
- tbm_surface_h src_buffer = NULL;
- Eina_Bool ret = EINA_FALSE;
+ tdm_error tdm_err = TDM_ERROR_NONE;
+ E_EomOutputPtr eom_output = NULL;
- src_buffer = _e_eom_root_internal_tdm_surface_get(output_name);
- RETURNVALIFTRUE(src_buffer == NULL, EINA_FALSE, "ERROR: get root tdm surfcae\n");
+ eom_output = (E_EomOutputPtr)user_data;
+ RETURNIFTRUE(user_data == NULL, "ERROR: PP EVENT: user data is NULL");
- tbm_surface_get_info(src_buffer, &src_buffer_info );
+ tdm_buffer_remove_release_handler(eom_output->dst_buffers[eom_output->pp_buffer],
+ _e_eom_cb_pp, eom_output);
- EOM_DBG("FRAMEBUFFER TDM: %dx%d bpp:%d size:%d",
- src_buffer_info.width, src_buffer_info.height,
- src_buffer_info.bpp, src_buffer_info.size);
+ /* TODO: lock these flags??? */
+ if (g_eom->main_output_state == DOWN)
+ return;
- /*
- g_eom->src_mode.w = width;
- g_eom->src_mode.h = height;
- g_eom->int_output_name = strdup(output_name);
- */
+ /* If a client has committed its buffer stop mirror mode */
+ if (eom_output->state != MIRROR)
+ return;
- /* TODO: if internal and external outputs are equal */
- ret = _e_eom_pp_is_needed(g_eom->src_mode.w, g_eom->src_mode.h,
- g_eom->dst_mode.w, g_eom->dst_mode.h);
- RETURNVALIFTRUE(ret == EINA_FALSE, EINA_TRUE, "pp is not required\n");
+ tbm_surface_h src_buffer;
+ src_buffer = _e_eom_util_get_output_surface(g_eom->main_output_name);
+ RETURNIFTRUE(src_buffer == NULL, "ERROR: PP EVENT: get root tdm surface");
- ret = _e_eom_pp_src_to_dst(src_buffer);
- RETURNVALIFTRUE(ret == EINA_FALSE, EINA_FALSE, "ERROR: init pp\n");
+ /*TODO: rewrite the mirror mode buffer's switching */
+ eom_output->pp_buffer ^= 1;
- return EINA_TRUE;
+ tdm_err = tdm_buffer_add_release_handler(eom_output->dst_buffers[eom_output->pp_buffer],
+ _e_eom_cb_pp, eom_output);
+ RETURNIFTRUE(tdm_err != TDM_ERROR_NONE, "ERROR: PP EVENT: set pp hadler:%d", tdm_err );
+
+ tdm_err = tdm_pp_attach(eom_output->pp, src_buffer, eom_output->dst_buffers[eom_output->pp_buffer]);
+ RETURNIFTRUE(tdm_err != TDM_ERROR_NONE, "ERROR: pp attach:%d\n", tdm_err);
+
+ tdm_err = tdm_pp_commit(eom_output->pp);
+ RETURNIFTRUE(tdm_err != TDM_ERROR_NONE, "ERROR: PP EVENT: pp commit:%d", tdm_err );
}
-static tbm_surface_h
-_e_eom_root_internal_tdm_surface_get(const char *name)
+static void
+_e_eom_cb_commit(tdm_output *output EINA_UNUSED, unsigned int sequence EINA_UNUSED,
+ unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED,
+ void *user_data)
{
- Ecore_Drm_Output *primary_output = NULL;
- Ecore_Drm_Device *dev;
- const Eina_List *l;
-#if 0
- Ecore_Drm_Fb *fb;
-#else
- tdm_output *tdm_output_obj = NULL;
- tbm_surface_h tbm = NULL;
+ E_EomClientBufferPtr client_buffer = NULL;
+ E_EomOutputPtr eom_output = NULL;
+ E_EomClientPtr eom_client = NULL;
tdm_error err = TDM_ERROR_NONE;
- int count = 0, i = 0;
-#endif
- EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
+ eom_output = (E_EomOutputPtr)user_data;
+ RETURNIFTRUE(user_data == NULL, "ERROR: COMMIT EVENT: user data is NULL");
+
+ if (g_eom->main_output_state == DOWN)
+ return;
+
+ /* TODO: Maybe better to separating that callback on to mirror and extended callbacks */
+ if (eom_output->state == MIRROR)
{
- primary_output = ecore_drm_device_output_name_find(dev, name);
- if (primary_output != NULL)
- break;
+ /*TODO: rewrite the mirror mode buffer's switching */
+ eom_output->current_buffer ^= 1;
+ err = tdm_layer_set_buffer(eom_output->layer,
+ eom_output->dst_buffers[eom_output->current_buffer]);
+
+ RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: COMMIT EVENT: MIRROR: set buffer 0 err:%d", err);
+
+ err = tdm_output_commit(eom_output->output, 0, _e_eom_cb_commit, eom_output);
+ RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: COMMIT EVENT: MIRROR: commit");
}
+ else if (eom_output->state == PRESENTATION)
+ {
+ eom_client = _e_eom_client_current_by_id_get(eom_output->id);
-#if 0
- RETURNVALIFTRUE(primary_output == NULL, NULL,
- "ERROR: get primary output.(%s)\n",
- name);
-
- /* I think it is more convenient than one upon, but E took first
- * output as primary and it can be not internal output
- *
- primary_output = ecore_drm_output_primary_get();
- RETURNVALIFTRUE(primary_output == NULL, NULL, "ERROR: get primary output\n");
- */
-#else
+ client_buffer = _e_eom_client_get_buffer(eom_client);
+ RETURNIFTRUE(client_buffer == NULL, "ERROR: COMMIT EVENT: PRESENTATION: client buffer is NULL");
- if (primary_output == NULL)
+ err = tdm_layer_set_buffer(eom_output->layer, client_buffer->tbm_buffer);
+ RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: COMMIT EVENT: PRESENTATION: set client buffer");
+
+ err = tdm_output_commit(eom_output->output, 0, _e_eom_cb_commit, eom_output);
+ RETURNIFTRUE(err != TDM_ERROR_NONE, "ERROR: COMMIT EVENT: PRESENTATION: commit");
+ }
+}
+
+static void
+_e_eom_cb_tdm_output_status_change(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data)
+{
+ tdm_output_type tdm_type;
+ tdm_error ret = TDM_ERROR_NONE;
+ tdm_output_conn_status status;
+ tdm_output_conn_status status2;
+ const char *maker = NULL, *model = NULL, *name = NULL;
+ const char *tmp_name;
+ char new_name[DRM_CONNECTOR_NAME_LEN];
+ E_EomOutputPtr eom_output = NULL;
+ tdm_output_conn_status plug;
+ E_EomClientPtr iterator = NULL;
+ Eina_List *l;
+
+ if (type == TDM_OUTPUT_CHANGE_DPMS || g_eom->main_output_state == DOWN)
+ return;
+
+ if (g_eom->outputs)
{
- EOM_ERR("ERROR: get primary output.(%s)\n", name);
- EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
- {
- primary_output = ecore_drm_output_primary_get(dev);
- if (primary_output != NULL)
- break;
- }
+ Eina_List *l;
+ E_EomOutputPtr eom_output_tmp;
- if (primary_output == NULL)
+ EINA_LIST_FOREACH(g_eom->outputs, l, eom_output_tmp)
{
- EOM_ERR("ERROR: get primary output.(%s)\n", name);
- return NULL;
+ if (eom_output_tmp->output == output)
+ eom_output = eom_output_tmp;
}
}
-#endif
-#if 0
- fb = ecore_drm_display_output_primary_layer_fb_get(primary_output);
- RETURNVALIFTRUE(fb == NULL, NULL, "ERROR: get primary frambuffer\n");
- /*EOM_DBG("FRAMEBUFFER ECORE_DRM: is_client:%d mode%dx%d\n", fb->from_client, fb->w, fb->h);*/
+ ret = tdm_output_get_output_type(output, &tdm_type);
+ RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_output_type fail(%d)", ret);
- return (tbm_surface_h)fb->hal_buffer;
-#else
- tdm_output_obj = tdm_display_get_output(g_eom->dpy, 0, &err);
- if (tdm_output_obj == NULL || err != TDM_ERROR_NONE)
+ ret = tdm_output_get_model_info(output, &maker, &model, &name);
+ RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_model_info fail(%d)", ret);
+
+ ret = tdm_output_get_conn_status(output, &status);
+ RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_conn_status fail(%d)", ret);
+
+ status2 = value.u32;
+
+ EOM_DBG("id (%d), type(%d, %d), status(%d, %d) (%s,%s,%s)", eom_output->id, type, tdm_type, status, status2, maker, model, name);
+
+ if (tdm_type < ALEN(eom_conn_types))
+ tmp_name = eom_conn_types[tdm_type];
+ else
+ tmp_name = "unknown";
+ /*TODO: What if there will more then one output of same type.
+ *e.g. "HDMI and HDMI" "LVDS and LVDS"*/
+ snprintf(new_name, sizeof(new_name), "%s-%d", tmp_name, 0);
+
+ plug = value.u32;
+
+ if (plug == TDM_OUTPUT_CONN_STATUS_CONNECTED || plug == TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
{
- EOM_ERR("tdm_display_get_output 0 fail\n");
- return NULL;
+ unsigned int mmWidth, mmHeight, subpixel;
+ const tdm_output_mode *mode;
+ int x = 0;
+
+ ret = tdm_output_get_physical_size(output, &mmWidth, &mmHeight);
+ RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_physical_size fail(%d)", ret);
+
+ ret = tdm_output_get_subpixel(output, &subpixel);
+ RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_subpixel fail(%d)", ret);
+
+ mode = _e_eom_output_get_best_mode(output);
+ RETURNIFTRUE(mode == NULL, "_e_eom_get_best_resolution fail");
+
+ ret = tdm_output_set_mode(output, mode);
+ RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_set_mode fail(%d)", ret);
+
+ x = _e_eom_output_get_position();
+ EOM_DBG("mode: %dx%d, phy(%dx%d), pos(%d,0), refresh:%d, subpixel:%d",
+ mode->hdisplay, mode->vdisplay, mmWidth, mmHeight, x, mode->vrefresh, subpixel);
+
+ /* model is substituted with new_name.
+ * It used to bind wl_output with eom_output in libeom. */
+ if (!e_comp_wl_output_init(new_name, maker, new_name, x, 0,
+ mode->hdisplay, mode->vdisplay,
+ mmWidth, mmHeight, mode->vrefresh, subpixel, 0))
+ {
+ EOM_ERR("Could not setup new output: %s", new_name);
+ return;
+ }
+ EOM_DBG("Setup new output: %s", new_name);
+
+ /* update eom_output connect */
+ eom_output->width = mode->hdisplay;
+ eom_output->height = mode->vdisplay;
+ eom_output->phys_width = mmWidth;
+ eom_output->phys_height = mmHeight;
+ eom_output->status = plug;
+ eom_output->name = eina_stringshare_add(new_name);
+ eom_output->type = (eom_output_type_e)tdm_type;
+
+ /* Create fake buffer */
+ eom_output->fake_buffer = _e_eom_util_create_fake_buffer(eom_output->width, eom_output->height);
+
+ /* TODO: check output mode(presentation set) and HDMI type */
+ _e_eom_output_start_mirror(eom_output, mode->hdisplay, mode->vdisplay);
+
+ /* If there were previously connected clients to the output - notify them */
+ EINA_LIST_FOREACH(g_eom->clients, l, iterator)
+ {
+ if (iterator)
+ {
+ EOM_DBG("Send MIRROR ON notification to clients");
+
+ wl_eom_send_output_info(iterator->resource, eom_output->id,
+ eom_output->type, eom_output->mode,
+ eom_output->width, eom_output->height,
+ eom_output->phys_width, eom_output->phys_height,
+ eom_output->status);
+
+ wl_eom_send_output_attribute(iterator->resource,
+ eom_output->id,
+ _e_eom_output_state_get_attribute(eom_output),
+ _e_eom_output_state_get_attribute_state(eom_output),
+ EOM_ERROR_NONE);
+ }
+ }
}
- err = tdm_output_get_layer_count(tdm_output_obj, &count);
- if (err != TDM_ERROR_NONE)
+ else /*TDM_OUTPUT_CONN_STATUS_DISCONNECTED*/
{
- EOM_ERR("tdm_output_get_layer_count fail\n");
- return NULL;
- }
+ if (eom_output->state == MIRROR)
+ _e_eom_output_stop_mirror(eom_output);
- for (i = 0; i < count; i++)
- {
- tdm_layer *layer = tdm_output_get_layer(tdm_output_obj, i, NULL);
- tdm_layer_capability capabilities = 0;
- tdm_layer_get_capabilities(layer, &capabilities);
- if (capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
+ /* update eom_output disconnect */
+ eom_output->width = 0;
+ eom_output->height = 0;
+ eom_output->phys_width = 0;
+ eom_output->phys_height = 0;
+ eom_output->status = plug;
+
+ /* If there were previously connected clients to the output - notify them */
+ EINA_LIST_FOREACH(g_eom->clients, l, iterator)
{
- tbm = tdm_layer_get_displaying_buffer(layer, &err);
- if (err != TDM_ERROR_NONE)
+ if (iterator)
{
- EOM_ERR("tdm_layer_get_displaying_buffer fail\n");
- return NULL;
+ EOM_DBG("Send MIRROR OFF notification to clients");
+
+ wl_eom_send_output_info(iterator->resource, eom_output->id,
+ eom_output->type, eom_output->mode,
+ eom_output->width, eom_output->height,
+ eom_output->phys_width, eom_output->phys_height,
+ eom_output->status);
+
+ wl_eom_send_output_attribute(iterator->resource,
+ eom_output->id,
+ _e_eom_output_state_get_attribute(eom_output),
+ EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
+ EOM_ERROR_NONE);
}
- break;
- }
- }
+ }
- return tbm;
-#endif
+ if (eom_output->fake_buffer)
+ tbm_surface_destroy(eom_output->fake_buffer);
+
+ e_comp_wl_output_remove(new_name);
+ EOM_DBG("Destory output: %s", new_name);
+ eina_stringshare_del(eom_output->name);
+ }
}
static void
-_e_eom_calculate_fullsize(int src_h, int src_v, int dst_size_h, int dst_size_v,
- int *dst_x, int *dst_y, int *dst_w, int *dst_h)
+_e_eom_cb_wl_request_set_attribute(struct wl_client *client, struct wl_resource *resource, uint32_t output_id, uint32_t attribute)
{
- double h_ratio, v_ratio;
+ eom_error_e eom_error = EOM_ERROR_NONE;
+ E_EomClientPtr eom_client = NULL, iterator = NULL;
+ E_EomOutputPtr eom_output = NULL;
+ Eina_Bool changes = EINA_FALSE;
+ Eina_Bool mode_change = EINA_FALSE;
+ Eina_Bool ret = EINA_FALSE;
+ Eina_List *l;
- h_ratio = src_h / dst_size_h;
- v_ratio = src_v / dst_size_v;
+ eom_client = _e_eom_client_get_by_resource(resource);
+ RETURNIFTRUE(eom_client == NULL, "client is NULL");
- if (h_ratio == v_ratio)
+ /* Bind the client with a concrete output */
+ if (eom_client->output_id == -1)
+ eom_client->output_id = output_id;
+
+ eom_output = _e_eom_output_get_by_id(output_id);
+ GOTOIFTRUE(eom_output == NULL, no_output, "output is NULL");
+
+ if (eom_client->current == EINA_TRUE && eom_output->id == eom_client->output_id)
{
- *dst_x = 0;
- *dst_y = 0;
- *dst_w = dst_size_h;
- *dst_h = dst_size_v;
+ /* Current client can set any flag it wants */
+ _e_eom_output_state_set_force_attribute(eom_output, attribute);
+ changes = EINA_TRUE;
}
- else if (h_ratio < v_ratio)
+ else
{
- *dst_y = 0;
- *dst_h = dst_size_v;
- *dst_w = dst_size_v * src_h / src_v;
- *dst_x = (dst_size_h - *dst_w) / 2;
+ ret = _e_eom_output_state_set_attribute(eom_output, attribute);
+ if (ret == EINA_FALSE)
+ {
+ EOM_DBG("set attribute FAILED\n");
+
+ eom_error = EOM_ERROR_INVALID_PARAMETER;
+ goto end;
+ }
+
+ eom_client->output_id = output_id;
+ changes = EINA_TRUE;
}
- else /* (h_ratio > v_ratio) */
+
+ EOM_DBG("set attribute OK\n");
+
+ /* If client has set EOM_OUTPUT_ATTRIBUTE_NONE, eom will be
+ * switched to mirror mode
+ */
+ if (attribute == EOM_OUTPUT_ATTRIBUTE_NONE && eom_output->state != MIRROR)
{
- *dst_x = 0;
- *dst_w = dst_size_h;
- *dst_h = dst_size_h * src_h / src_v;
- *dst_y = (dst_size_v - *dst_h) / 2;
- }
-}
+ eom_output->state = MIRROR;
+ eom_client->current = EINA_FALSE;
-static Eina_Bool
-_e_eom_pp_src_to_dst(tbm_surface_h src_buffer)
-{
- tdm_error err = TDM_ERROR_NONE;
- tdm_info_pp pp_info;
- tdm_pp *pp = NULL;
- int x, y, w, h;
+ _e_eom_output_state_set_mode(eom_output, EOM_OUTPUT_ATTRIBUTE_NONE);
+ mode_change = EINA_TRUE;
- pp = tdm_display_create_pp(g_eom->dpy, &err);
- RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: create pp:%d\n", err);
+ ret = _e_eom_output_state_set_attribute(eom_output, EOM_OUTPUT_ATTRIBUTE_NONE);
+ (void)ret;
- /* TO DO : consider rotation */
- _e_eom_calculate_fullsize(g_eom->src_mode.w, g_eom->src_mode.h,
- g_eom->dst_mode.w, g_eom->dst_mode.h,
- &x, &y, &w, &h);
- EOM_DBG("x:%d, y:%d, w:%d, h:%d\n", x, y, w, h);
+ _e_eom_client_free_buffers(eom_client);
- g_eom_event_data.pp = pp;
+ if (eom_output->status == 0)
+ {
+ EOM_DBG("ATTRIBUTE: output:%d is disconnected", output_id);
+ goto end;
+ }
- pp_info.src_config.size.h = g_eom->src_mode.w;
- pp_info.src_config.size.v = g_eom->src_mode.h;
- pp_info.src_config.pos.x = 0;
- pp_info.src_config.pos.y = 0;
- pp_info.src_config.pos.w = g_eom->src_mode.w;
- pp_info.src_config.pos.h = g_eom->src_mode.h;
- pp_info.src_config.format = TBM_FORMAT_ARGB8888;
+ ret = _e_eom_output_start_pp(eom_output);
+ GOTOIFTRUE(ret == EINA_FALSE, end,
+ "ERROR: restore mirror mode after a client disconnection\n");
+ goto end;
+ }
- pp_info.dst_config.size.h = g_eom->dst_mode.w;
- pp_info.dst_config.size.v = g_eom->dst_mode.h;
- pp_info.dst_config.pos.x = x;
- pp_info.dst_config.pos.y = y;
- pp_info.dst_config.pos.w = w;
- pp_info.dst_config.pos.h = h;
- pp_info.dst_config.format = TBM_FORMAT_ARGB8888;
+end:
+ wl_eom_send_output_attribute(eom_client->resource,
+ eom_output->id,
+ _e_eom_output_state_get_attribute(eom_output),
+ _e_eom_output_state_get_attribute_state(eom_output),
+ eom_error);
- /* TO DO : get rotation */
- pp_info.transform = TDM_TRANSFORM_NORMAL;
- pp_info.sync = 0;
- pp_info.flags = 0;
+ /* Notify eom clients that eom state has been changed */
+ if (changes == EINA_TRUE)
+ {
+ EINA_LIST_FOREACH(g_eom->clients, l, iterator)
+ {
+ if (iterator && iterator->resource == resource)
+ continue;
- err = tdm_pp_set_info(pp, &pp_info);
- RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: set pp info:%d\n", err);
+ if (iterator && iterator->output_id == eom_output->id)
+ {
+ iterator->current = 0;
+
+ if (eom_output->state == MIRROR)
+ {
+ wl_eom_send_output_attribute(iterator->resource,
+ eom_output->id,
+ _e_eom_output_state_get_attribute(eom_output),
+ _e_eom_output_state_get_attribute_state(eom_output),
+ EOM_ERROR_NONE);
+ }
+ else
+ {
+ wl_eom_send_output_attribute(iterator->resource,
+ eom_output->id,
+ _e_eom_output_state_get_attribute(eom_output),
+ EOM_OUTPUT_ATTRIBUTE_STATE_LOST,
+ EOM_ERROR_NONE);
+ }
+
+ if (mode_change == EINA_TRUE)
+ {
+ wl_eom_send_output_mode(iterator->resource,
+ eom_output->id,
+ _e_eom_output_state_get_mode(eom_output));
+ }
+ }
+ }
- g_eom_event_data.pp_buffer = !g_eom_event_data.current_buffer;
- EOM_DBG("PP: curr:%d pp:%d\n",
- g_eom_event_data.current_buffer,
- g_eom_event_data.pp_buffer);
+ eom_client->current= EINA_TRUE;
+ }
- err = tdm_buffer_add_release_handler(g_eom_event_data.dst_buffers[g_eom_event_data.pp_buffer],
- _e_eom_pp_cb, &g_eom_event_data);
- RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: set pp hadler:%d\n", err);
+ return;
- err = tdm_pp_attach(pp, src_buffer,
- g_eom_event_data.dst_buffers[g_eom_event_data.pp_buffer]);
- RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: pp attach:%d\n", err);
+ /* Get here if EOM does not have output with output_id is */
+no_output:
- err = tdm_pp_commit(g_eom_event_data.pp);
- RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: pp commit:%d\n", err);
+ wl_eom_send_output_attribute(eom_client->resource,
+ output_id,
+ EOM_OUTPUT_ATTRIBUTE_NONE,
+ EOM_OUTPUT_ATTRIBUTE_STATE_NONE,
+ EOM_ERROR_NO_SUCH_DEVICE);
- return EINA_TRUE;
+ wl_eom_send_output_mode(eom_client->resource,
+ output_id,
+ EOM_OUTPUT_MODE_NONE);
+
+ wl_eom_send_output_type(eom_client->resource,
+ output_id,
+ EOM_OUTPUT_ATTRIBUTE_STATE_NONE,
+ TDM_OUTPUT_CONN_STATUS_DISCONNECTED);
+ return;
}
-static Eina_Bool
-_e_eom_pp_is_needed(int src_w, int src_h, int dst_w, int dst_h)
+static void
+_e_eom_cb_wl_request_get_output_info(struct wl_client *client, struct wl_resource *resource, uint32_t output_id)
{
- if (src_w != dst_w)
- return EINA_TRUE;
+ EOM_DBG("output:%d\n", output_id);
- if (src_h != dst_h)
- return EINA_TRUE;
+ if (g_eom->outputs)
+ {
+ Eina_List *l;
+ E_EomOutputPtr output = NULL;
- return EINA_FALSE;
+ EINA_LIST_FOREACH(g_eom->outputs, l, output)
+ {
+ if (output->id == output_id)
+ {
+ EOM_DBG("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d\n",
+ output->id, output->type, output->mode, output->width, output->height,
+ output->phys_width, output->phys_height, output->status);
+
+ wl_eom_send_output_info(resource, output->id, output->type, output->mode, output->width, output->height,
+ output->phys_width, output->phys_height, output->status);
+ }
+ }
+ }
}
static Eina_Bool
-_e_eom_ecore_drm_output_cb(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
+_e_eom_output_init(tdm_display *dpy)
{
- Ecore_Drm_Event_Output *e = NULL;
- char buff[PATH_MAX];
-
- if (!(e = event)) return ECORE_CALLBACK_PASS_ON;;
+ tdm_error ret = TDM_ERROR_NONE;
+ int i, count;
- EOM_DBG("id:%d (x,y,w,h):(%d,%d,%d,%d) (w_mm,h_mm):(%d,%d) refresh:%d subpixel_order:%d transform:%d make:%s model:%s name:%s plug:%d\n",
- e->id, e->x, e->y, e->w, e->h, e->phys_width, e->phys_height, e->refresh, e->subpixel_order, e->transform, e->make, e->model, e->name, e->plug);
+ ret = tdm_display_get_output_count(dpy, &count);
+ RETURNVALIFTRUE(ret != TDM_ERROR_NONE,
+ EINA_FALSE,
+ "tdm_display_get_output_count fail");
+ RETURNVALIFTRUE(count <= 1,
+ EINA_FALSE,
+ "output count is 1. device doesn't support external outputs.\n");
- snprintf(buff, sizeof(buff), "%s", e->name);
+ g_eom->output_count = count - 1;
+ EOM_DBG("external output count : %d\n", g_eom->output_count);
- if (e->id == 0) /* main output */
+ /* skip main output id:0 */
+ /* start from 1 */
+ for (i = 1; i < count; i++)
{
- if (e->plug == 1)
+ const tdm_output_mode *mode = NULL;
+ E_EomOutputPtr new_output = NULL;
+ unsigned int mmWidth, mmHeight;
+ tdm_output_conn_status status;
+ tdm_output *output = NULL;
+ tdm_output_type type;
+
+ output = tdm_display_get_output(dpy, i, &ret);
+ GOTOIFTRUE(ret != TDM_ERROR_NONE,
+ err,
+ "tdm_display_get_output fail(ret:%d)", ret);
+
+ GOTOIFTRUE(output == NULL,
+ err,
+ "tdm_display_get_output fail(no output:%d)", ret);
+
+ ret = tdm_output_get_output_type(output, &type);
+ GOTOIFTRUE(ret != TDM_ERROR_NONE,
+ err,
+ "tdm_output_get_output_type fail(%d)", ret);
+
+ new_output = E_NEW(E_EomOutput, 1);
+ GOTOIFTRUE(new_output == NULL,
+ err,
+ "calloc fail");
+
+ ret = tdm_output_get_conn_status(output, &status);
+ if (ret != TDM_ERROR_NONE)
+ {
+ EOM_ERR("tdm_output_get_conn_status fail(%d)", ret);
+ free(new_output);
+ goto err;
+ }
+ new_output->id = i;
+ new_output->type = type;
+ new_output->status = status;
+ new_output->mode = EOM_OUTPUT_MODE_NONE;
+ new_output->output = output;
+
+ ret = tdm_output_add_change_handler(output, _e_eom_cb_tdm_output_status_change, NULL);
+ if (ret != TDM_ERROR_NONE)
{
- g_eom->src_mode.w = e->w;
- g_eom->src_mode.h = e->h;
- if (g_eom->int_output_name == NULL)
- g_eom->int_output_name = strdup(buff);
+ EOM_ERR("tdm_output_add_change_handler fail(%d)", ret);
+ free(new_output);
+ goto err;
+ }
- g_eom->eom_sate = UP;
+ if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
+ {
+ EOM_DBG("create(%d)output, type:%d, status:%d",
+ new_output->id, new_output->type, new_output->status);
+ g_eom->outputs = eina_list_append(g_eom->outputs, new_output);
+ continue;
}
+ new_output->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
+
+ ret = tdm_output_get_mode(output, &mode);
+ if (ret != TDM_ERROR_NONE)
+ {
+ EOM_ERR("tdm_output_get_mode fail(%d)", ret);
+ free(new_output);
+ goto err;
+ }
+
+ if (mode == NULL)
+ {
+ new_output->width = 0;
+ new_output->height = 0;
+ }
+
else
{
- g_eom->src_mode.w = -1;
- g_eom->src_mode.h = -1;
- if (g_eom->int_output_name)
- free(g_eom->int_output_name);
+ new_output->width = mode->hdisplay;
+ new_output->height = mode->vdisplay;
+ }
- g_eom->eom_sate = DOWN;
+ ret = tdm_output_get_physical_size(output, &mmWidth, &mmHeight);
+ if (ret != TDM_ERROR_NONE)
+ {
+ EOM_ERR("tdm_output_get_conn_status fail(%d)", ret);
+ free(new_output);
+ goto err;
}
+ new_output->phys_width = mmWidth;
+ new_output->phys_height = mmHeight;
+
+ EOM_DBG("create(%d)output, type:%d, status:%d, w:%d, h:%d, mm_w:%d, mm_h:%d",
+ new_output->id, new_output->type, new_output->status,
+ new_output->width, new_output->height, new_output->phys_width, new_output->phys_height);
+
+ g_eom->outputs = eina_list_append(g_eom->outputs, new_output);
}
- return ECORE_CALLBACK_PASS_ON;
+ return EINA_TRUE;
+
+err:
+ if (g_eom->outputs)
+ {
+ Eina_List *l;
+ E_EomOutputPtr output;
+
+ EINA_LIST_FOREACH(g_eom->outputs, l, output)
+ {
+ free(output);
+ }
+ eina_list_free(g_eom->outputs);
+ }
+
+ return EINA_FALSE;
}
static const tdm_output_mode *
-_e_eom_get_best_mode(tdm_output *output)
+_e_eom_output_get_best_mode(tdm_output *output)
{
tdm_error ret = TDM_ERROR_NONE;
const tdm_output_mode *modes;
unsigned int value;
int i, count = 0;
- ret = tdm_output_get_available_modes(output, &modes, &count);
- if (ret != TDM_ERROR_NONE)
- {
- EOM_ERR("tdm_output_get_available_modes fail(%d)\n", ret);
- return NULL;
- }
-#if 0
- /* kernel error */
- for (i = 0; i < count; i++)
- {
- value = modes[i].vdisplay + modes[i].hdisplay;
- if (value > best_value)
- best_value = value;
- }
-
- for (i = 0; i < count; i++)
- {
- value = modes[i].vdisplay + modes[i].hdisplay;
- if (value != best_value)
- continue;
-
- if (modes[i].vrefresh > vrefresh)
- {
- mode = &modes[i];
- vrefresh = modes[i].vrefresh;
- }
+ ret = tdm_output_get_available_modes(output, &modes, &count);
+ if (ret != TDM_ERROR_NONE)
+ {
+ EOM_ERR("tdm_output_get_available_modes fail(%d)\n", ret);
+ return NULL;
}
-#else
+
for (i = 0; i < count; i++)
{
value = modes[i].vdisplay + modes[i].hdisplay;
mode = &modes[i];
}
}
-#endif
+
EOM_DBG("bestmode : %s, (%dx%d) r(%d), f(%d), t(%d)",
mode->name, mode->hdisplay, mode->vdisplay, mode->vrefresh, mode->flags, mode->type);
}
static int
-_e_eom_get_output_position(void)
+_e_eom_output_get_position(void)
{
tdm_output *output_main = NULL;
const tdm_output_mode *mode;
EINA_LIST_FOREACH(g_eom->outputs, l, eom_output_tmp)
{
if (eom_output_tmp->status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
- x += eom_output_tmp->w;
+ x += eom_output_tmp->width;
}
}
}
static void
-_e_eom_start_mirror(E_EomOutputPtr eom_output, int width, int height)
+_e_eom_output_start_mirror(E_EomOutputPtr eom_output, int width, int height)
{
tdm_output *output;
tdm_layer *hal_layer;
tdm_info_layer layer_info;
tdm_error tdm_err = TDM_ERROR_NONE;
- E_EomEventDataPtr eom_event_data = &g_eom_event_data;
int ret = 0;
- if (eom_output->mirror_run == UP)
+ if (eom_output->state == MIRROR)
return;
output = eom_output->output;
- hal_layer = _e_eom_hal_layer_get(output, width, height);
+ hal_layer = _e_eom_output_get_layer(output, width, height);
GOTOIFTRUE(hal_layer == NULL, err, "ERROR: get hal layer\n");
- ret = _e_eom_create_output_buffers(eom_event_data, width, height);
+ ret = _e_eom_util_create_buffers(eom_output, width, height);
GOTOIFTRUE(ret == EINA_FALSE, err, "ERROR: create buffers \n");
tdm_err = tdm_layer_get_info(hal_layer, &layer_info);
layer_info.dst_pos.x, layer_info.dst_pos.y,
layer_info.dst_pos.w, layer_info.dst_pos.h);
- g_eom->dst_mode.w = width;
- g_eom->dst_mode.h = height;
- /* TODO: free that memory */
- /*g_eom->ext_output_name = strdup(output_name);*/
+ eom_output->layer = hal_layer;
+ eom_output->output = output;
+ eom_output->current_buffer = 0;
- eom_event_data->layer = hal_layer;
- eom_event_data->output = output;
- eom_event_data->current_buffer = 0;
-
- tdm_err = tdm_layer_set_buffer(hal_layer, eom_event_data->dst_buffers[eom_event_data->current_buffer]);
+ tdm_err = tdm_layer_set_buffer(hal_layer, eom_output->dst_buffers[eom_output->current_buffer]);
GOTOIFTRUE(tdm_err != TDM_ERROR_NONE, err, "ERROR: set buffer on layer:%d\n", tdm_err);
- g_eom->is_external_init = 1;
- g_eom->id = eom_output->id;
-
tdm_err = tdm_output_set_dpms(output, TDM_OUTPUT_DPMS_ON);
GOTOIFTRUE(tdm_err != TDM_ERROR_NONE, err, "ERROR: tdm_output_set_dpms on\n");
/* get main surface */
- ret = _e_eom_mirror_start(g_eom->int_output_name, g_eom->src_mode.w, g_eom->src_mode.h);
+ ret = _e_eom_output_start_pp(eom_output);
GOTOIFTRUE(ret == EINA_FALSE, err, "ERROR: get root surfcae\n");
- tdm_err = tdm_output_commit(output, 0, _e_eom_commit_cb, &g_eom_event_data);
+ tdm_err = tdm_output_commit(output, 0, _e_eom_cb_commit, eom_output);
GOTOIFTRUE(tdm_err != TDM_ERROR_NONE, err, "ERROR: commit crtc:%d\n", tdm_err);
- _e_eom_set_eom_mode(WL_EOM_MODE_MIRROR);
-
- eom_output->mirror_run = UP;
+ _e_eom_output_state_set_mode(eom_output, EOM_OUTPUT_MODE_MIRROR);
+ _e_eom_output_state_set_attribute(eom_output, EOM_OUTPUT_ATTRIBUTE_NONE);
+ eom_output->state = MIRROR;
return;
}
static void
-_e_eom_stop_mirror(E_EomOutputPtr eom_output)
+_e_eom_output_stop_mirror(E_EomOutputPtr eom_output)
{
- if (eom_output->mirror_run == DOWN)
+ if (eom_output->state == NONE)
return;
- g_eom->is_external_init = 0;
- g_eom->is_internal_grab = 0;
- g_eom->id = -1;
-
- _e_eom_set_eom_status(WL_EOM_STATUS_DISCONNECTION);
- _e_eom_set_eom_mode(WL_EOM_MODE_NONE);
+ _e_eom_output_state_set_status(eom_output, TDM_OUTPUT_CONN_STATUS_DISCONNECTED);
+ _e_eom_output_state_set_mode(eom_output, EOM_OUTPUT_MODE_NONE);
+ _e_eom_output_state_set_attribute(eom_output, EOM_OUTPUT_ATTRIBUTE_NONE);
- _e_eom_deinit_external_output();
+ _e_eom_output_deinit(eom_output);
- eom_output->mirror_run = DOWN;
+ eom_output->state = NONE;
}
static void
-_e_eom_tdm_output_status_change_cb(tdm_output *output, tdm_output_change_type type, tdm_value value, void *user_data)
+_e_eom_output_deinit(E_EomOutputPtr eom_output)
{
- tdm_output_type tdm_type;
- tdm_error ret = TDM_ERROR_NONE;
- tdm_output_conn_status status;
- tdm_output_conn_status status2;
- const char *maker = NULL, *model = NULL, *name = NULL;
- const char *tmp_name;
- char new_name[DRM_CONNECTOR_NAME_LEN];
- E_EomOutputPtr eom_output = NULL;
- tdm_output_conn_status plug;
-
- if (type == TDM_OUTPUT_CHANGE_DPMS)
- return;
+ tdm_error err = TDM_ERROR_NONE;
+ E_EomClientPtr iterator = NULL;
+ Eina_List *l;
+ int i = 0;
- if (g_eom->outputs)
+ if (eom_output->layer)
{
- Eina_List *l;
- E_EomOutputPtr eom_output_tmp;
+ err = tdm_layer_unset_buffer(eom_output->layer);
+ if (err != TDM_ERROR_NONE)
+ EOM_DBG("EXT OUTPUT DEINIT: fail unset buffer:%d\n", err);
+ else
+ EOM_DBG("EXT OUTPUT DEINIT: ok unset buffer:%d\n", err);
- EINA_LIST_FOREACH(g_eom->outputs, l, eom_output_tmp)
- {
- if (eom_output_tmp->output == output)
- eom_output = eom_output_tmp;
- }
- }
+ err = tdm_output_commit(eom_output->output, 0, NULL, eom_output);
+ if (err != TDM_ERROR_NONE)
+ EOM_DBG ("EXT OUTPUT DEINIT: fail commit:%d\n", err);
+ else
+ EOM_DBG("EXT OUTPUT DEINIT: ok commit:%d\n", err);
+ }
- ret = tdm_output_get_output_type(output, &tdm_type);
- RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_output_type fail(%d)", ret);
+ /* TODO: do I need to do DPMS off? */
- ret = tdm_output_get_model_info(output, &maker, &model, &name);
- RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_model_info fail(%d)", ret);
+ err = tdm_output_set_dpms(eom_output->output, TDM_OUTPUT_DPMS_OFF);
+ if (err != TDM_ERROR_NONE)
+ EOM_ERR("EXT OUTPUT DEINIT: failed set DPMS off:%d\n", err);
- ret = tdm_output_get_conn_status(output, &status);
- RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_conn_status fail(%d)", ret);
+ for (i = 0; i < NUM_MAIN_BUF; i++)
+ {
+ tdm_buffer_remove_release_handler(eom_output->dst_buffers[i],
+ _e_eom_cb_pp, eom_output);
- status2 = value.u32;
+ if (eom_output->dst_buffers[i])
+ tbm_surface_destroy(eom_output->dst_buffers[i]);
+ }
- EOM_DBG("type(%d, %d), status(%d, %d) (%s,%s,%s)", type, tdm_type, status, status2, maker, model, name);
+ /*TODO: what is that for?*/
+ if (g_eom->main_output_state == DOWN)
+ EINA_LIST_FOREACH(g_eom->clients, l, iterator)
+ {
+ if (iterator && iterator->output_id == eom_output->id)
+ _e_eom_client_free_buffers(iterator);
+ }
+}
- if (tdm_type < ALEN(eom_conn_types))
- tmp_name = eom_conn_types[tdm_type];
- else
- tmp_name = "unknown";
- snprintf(new_name, sizeof(new_name), "%s-%d", tmp_name, 0);
+static tdm_layer *
+_e_eom_output_get_layer(tdm_output *output, int width, int height)
+{
+ int i = 0;
+ int count = 0;
+ tdm_layer *layer = NULL;
+ tdm_error err = TDM_ERROR_NONE;
+ tdm_layer_capability capa;
+ tdm_info_layer layer_info;
- plug = value.u32;
+ err = tdm_output_get_layer_count(output, &count);
+ if (err != TDM_ERROR_NONE)
+ {
+ EOM_DBG ("tdm_output_get_layer_count fail(%d)\n", err);
+ return NULL;
+ }
- if (plug == TDM_OUTPUT_CONN_STATUS_CONNECTED)
+ for (i = 0; i < count; i++)
{
- unsigned int mmWidth, mmHeight, subpixel;
- const tdm_output_mode *mode;
- int x = 0;
+ layer = (tdm_layer *)tdm_output_get_layer(output, i, &err);
+ RETURNVALIFTRUE(err != TDM_ERROR_NONE, NULL, "tdm_output_get_layer fail(%d)\n", err);
- ret = tdm_output_get_physical_size(output, &mmWidth, &mmHeight);
- RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_physical_size fail(%d)", ret);
+ err = tdm_layer_get_capabilities(layer, &capa);
+ RETURNVALIFTRUE(err != TDM_ERROR_NONE, NULL, "tdm_layer_get_capabilities fail(%d)\n", err);
- ret = tdm_output_get_subpixel(output, &subpixel);
- RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_get_subpixel fail(%d)", ret);
+ if (capa & TDM_LAYER_CAPABILITY_PRIMARY)
+ {
+ EOM_DBG("TDM_LAYER_CAPABILITY_PRIMARY layer found : %d\n", i);
+ break;
+ }
+ }
- mode = _e_eom_get_best_mode(output);
- RETURNIFTRUE(mode == NULL, "_e_eom_get_best_resolution fail");
+ memset(&layer_info, 0x0, sizeof(tdm_info_layer));
+ layer_info.src_config.size.h = width;
+ layer_info.src_config.size.v = height;
+ layer_info.src_config.pos.x = 0;
+ layer_info.src_config.pos.y = 0;
+ layer_info.src_config.pos.w = width;
+ layer_info.src_config.pos.h = height;
+ layer_info.src_config.format = TBM_FORMAT_ARGB8888;
+ layer_info.dst_pos.x = 0;
+ layer_info.dst_pos.y = 0;
+ layer_info.dst_pos.w = width;
+ layer_info.dst_pos.h = height;
+ layer_info.transform = TDM_TRANSFORM_NORMAL;
- ret = tdm_output_set_mode(output, mode);
- RETURNIFTRUE(ret != TDM_ERROR_NONE, "tdm_output_set_mode fail(%d)", ret);
+ err = tdm_layer_set_info(layer, &layer_info);
+ RETURNVALIFTRUE(err != TDM_ERROR_NONE, NULL, "tdm_layer_set_info fail(%d)\n", err);
- x = _e_eom_get_output_position();
- EOM_DBG("mode: %dx%d, phy(%dx%d), pos(%d,0), refresh:%d, subpixel:%d",
- mode->hdisplay, mode->vdisplay, mmWidth, mmHeight, x, mode->vrefresh, subpixel);
+ return layer;
+}
- if (!e_comp_wl_output_init(new_name, maker, model, x, 0,
- mode->hdisplay, mode->vdisplay,
- mmWidth, mmHeight, mode->vrefresh, subpixel, 0))
- {
- EOM_ERR("Could not setup new output: %s", new_name);
- return;
- }
- EOM_DBG("Setup new output: %s", new_name);
+static E_EomOutputPtr
+_e_eom_output_get_by_id(int id)
+{
+ Eina_List *l;
+ E_EomOutputPtr output;
- /* update eom_output connect */
- eom_output->w = mode->hdisplay;
- eom_output->h = mode->vdisplay;
- eom_output->phys_width = mmWidth;
- eom_output->phys_height = mmHeight;
- eom_output->status = plug;
+ EINA_LIST_FOREACH(g_eom->outputs, l, output)
+ {
+ if (output && output->id == id)
+ return output;
+ }
- g_eom->is_mirror_mode = UP;
- g_eom->eom_sate = UP;
+ return NULL;
+}
- /* TODO: check output mode(presentation set) and HDMI type */
- _e_eom_start_mirror(eom_output, mode->hdisplay, mode->vdisplay);
- }
- else if (plug == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
+static E_EomOutputPtr
+_e_eom_output_get_by_name(const char *name)
+{
+ Eina_List *l;
+ E_EomOutputPtr output;
+
+ EINA_LIST_FOREACH(g_eom->outputs, l, output)
{
- if (eom_output->mirror_run == UP)
- _e_eom_stop_mirror(eom_output);
+ if (output && strcmp(output->name, name) == 0)
+ return output;
+ }
- /* update eom_output disconnect */
- eom_output->w = 0;
- eom_output->h = 0;
- eom_output->phys_width = 0;
- eom_output->phys_height = 0;
- eom_output->status = plug;
+ return NULL;
+}
+
+static Eina_Bool
+_e_eom_output_start_pp(E_EomOutputPtr eom_output)
+{
+ /* should be changed in HWC enable environment */
+ tbm_surface_info_s src_buffer_info;
+ tbm_surface_h src_buffer = NULL;
+ Eina_Bool ret = EINA_FALSE;
- g_eom->is_mirror_mode = DOWN;
- g_eom->eom_sate = DOWN;
+ src_buffer = _e_eom_util_get_output_surface(g_eom->main_output_name);
+ RETURNVALIFTRUE(src_buffer == NULL, EINA_FALSE, "ERROR: get root tdm surfcae\n");
- e_comp_wl_output_remove(new_name);
- EOM_DBG("Destory output: %s", new_name);
- }
+ tbm_surface_get_info(src_buffer, &src_buffer_info);
+
+ EOM_DBG("FRAMEBUFFER TDM: %dx%d bpp:%d size:%d",
+ src_buffer_info.width, src_buffer_info.height,
+ src_buffer_info.bpp, src_buffer_info.size);
+
+ /* TODO: if internal and external outputs are equal */
+ ret = _e_eom_pp_is_needed(g_eom->width, g_eom->height,
+ eom_output->width, eom_output->height);
+ RETURNVALIFTRUE(ret == EINA_FALSE, EINA_TRUE, "pp is not required\n");
+
+ ret = _e_eom_pp_init(eom_output, src_buffer);
+ RETURNVALIFTRUE(ret == EINA_FALSE, EINA_FALSE, "ERROR: init pp\n");
+
+ return EINA_TRUE;
}
static Eina_Bool
-_e_eom_client_buffer_change(void *data, int type, void *event)
+_e_eom_pp_init(E_EomOutputPtr eom_output, tbm_surface_h src_buffer)
{
- E_Comp_Wl_Buffer *external_wl_buffer = NULL;
- E_EomClientBufferPtr client_buffer = NULL;
- E_Event_Client *ev = event;
- E_Client *ec = NULL;
- /* Eina_Bool ret_err; */
- /*
- tbm_surface_h external_tbm_buffer = NULL;
- tbm_surface_info_s surface_info;
- int ret;
- */
+ tdm_error err = TDM_ERROR_NONE;
+ tdm_info_pp pp_info;
+ tdm_pp *pp = NULL;
+ int x, y, w, h;
- EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
- EINA_SAFETY_ON_NULL_RETURN_VAL(ev->ec, ECORE_CALLBACK_PASS_ON);
+ pp = tdm_display_create_pp(g_eom->dpy, &err);
+ RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: create pp:%d\n", err);
- return ECORE_CALLBACK_PASS_ON;
+ eom_output->pp = pp;
- ec = ev->ec;
- if (e_object_is_del(E_OBJECT(ec)))
- {
- EOM_ERR("ERROR: BUFF CHANGE: ec objects is del\n");
- return ECORE_CALLBACK_PASS_ON;
- }
+ /* TO DO : consider rotation */
+ _e_eom_util_calculate_fullsize(g_eom->width, g_eom->height,
+ eom_output->width, eom_output->height,
+ &x, &y, &w, &h);
+ EOM_DBG("x:%d, y:%d, w:%d, h:%d\n", x, y, w, h);
- /* TODO: Make all goto same, not err, end, ret etc. */
- /* We are not interested in non external clients */
- /*
- ret_err = e_client_is_external_output_client(ec);
- RETURNVALIFTRUE(ret_err != EINA_TRUE,
- ECORE_CALLBACK_PASS_ON,
- "ERROR: BUFF CHANGE: ec is not external\n");
- */
+ pp_info.src_config.size.h = g_eom->width;
+ pp_info.src_config.size.v = g_eom->height;
+ pp_info.src_config.pos.x = 0;
+ pp_info.src_config.pos.y = 0;
+ pp_info.src_config.pos.w = g_eom->width;
+ pp_info.src_config.pos.h = g_eom->height;
+ pp_info.src_config.format = TBM_FORMAT_ARGB8888;
- if (ec->pixmap == NULL)
- return ECORE_CALLBACK_PASS_ON;
+ pp_info.dst_config.size.h = eom_output->width;
+ pp_info.dst_config.size.v = eom_output->height;
+ pp_info.dst_config.pos.x = x;
+ pp_info.dst_config.pos.y = y;
+ pp_info.dst_config.pos.w = w;
+ pp_info.dst_config.pos.h = h;
+ pp_info.dst_config.format = TBM_FORMAT_ARGB8888;
- external_wl_buffer = e_pixmap_resource_get(ec->pixmap);
- RETURNVALIFTRUE(external_wl_buffer == NULL,
- ECORE_CALLBACK_PASS_ON,
- "ERROR:BUFF CHANGE: wl buffer is NULL\n");
+ /* TO DO : get rotation */
+ pp_info.transform = TDM_TRANSFORM_NORMAL;
+ pp_info.sync = 0;
+ pp_info.flags = 0;
- EOM_DBG("BUFF CHANGE: wl_buff:%dx%d",
- external_wl_buffer->w,
- external_wl_buffer->h);
+ err = tdm_pp_set_info(pp, &pp_info);
+ RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: set pp info:%d\n", err);
- if (external_wl_buffer->w == 1 && external_wl_buffer->h == 1)
- {
- EOM_ERR("ERROR:BUFF CHANGE: skip first 1x1 client buffer\n");
- return ECORE_CALLBACK_PASS_ON;
- }
+ eom_output->pp_buffer = !eom_output->current_buffer;
+ EOM_DBG("PP: curr:%d pp:%d\n",
+ eom_output->current_buffer,
+ eom_output->pp_buffer);
- /*TODO: wayland_tbm_server_get_surface is implicit declarated */
- /*external_tbm_buffer = wayland_tbm_server_get_surface(NULL,
- external_wl_buffer->resource);
- if (external_tbm_buffer == NULL)
- {
- EOM_ERR("ERROR: BUFF CHANGE: client tbm buffer is NULL\n");
- return ECORE_CALLBACK_PASS_ON;
- }
+ err = tdm_buffer_add_release_handler(eom_output->dst_buffers[eom_output->pp_buffer],
+ _e_eom_cb_pp, eom_output);
+ RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: set pp hadler:%d\n", err);
- EOM_DBG("BUFF CHANGE: tbm_buffer %p", external_tbm_buffer);
- */
+ err = tdm_pp_attach(pp, src_buffer,
+ eom_output->dst_buffers[eom_output->pp_buffer]);
+ RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: pp attach:%d\n", err);
+
+ err = tdm_pp_commit(eom_output->pp);
+ RETURNVALIFTRUE(err != TDM_ERROR_NONE, EINA_FALSE, "ERROR: pp commit:%d\n", err);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool
+_e_eom_pp_is_needed(int src_w, int src_h, int dst_w, int dst_h)
+{
+ if (src_w != dst_w)
+ return EINA_TRUE;
+
+ if (src_h != dst_h)
+ return EINA_TRUE;
+
+ return EINA_FALSE;
+}
+
+static tbm_surface_h
+_e_eom_util_create_fake_buffer(int width, int height)
+{
+ tbm_surface_info_s buffer_info;
+ tbm_surface_h buffer = NULL;
- /* mmap that buffer to get width and height for test's sake */
- /*
- memset(&surface_info, 0, sizeof(tbm_surface_info_s));
- ret = tbm_surface_map(external_tbm_buffer, TBM_SURF_OPTION_READ |
- TBM_SURF_OPTION_WRITE, &surface_info);
- if (ret != TBM_SURFACE_ERROR_NONE)
+ buffer = tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+ GOTOIFTRUE(buffer == NULL, err, "can not create fake_buffer\n");
+
+ memset(&buffer_info, 0x0, sizeof(tbm_surface_info_s));
+ if (tbm_surface_map(buffer,
+ TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
+ &buffer_info) != TBM_SURFACE_ERROR_NONE)
{
- EOM_ERR("BUFF CHANGE: failed mmap buffer: %d", ret);
- //return ECORE_CALLBACK_PASS_ON;
+ EOM_DBG("can not mmap fake_buffer\n");
+ goto err;
}
- EOM_DBG("BUFF CHANGE: tbm_buffer: %dx%d", surface_info.width, surface_info.height);
+ memset(buffer_info.planes[0].ptr, 0xFF, buffer_info.planes[0].size);
+ tbm_surface_unmap(buffer);
- tbm_surface_unmap(external_tbm_buffer);
- */
+ return buffer;
+err:
- /* TODO: Must find proper way of getting tbm_surface */
- /*client_buffer = _e_eom_create_client_buffer(external_wl_buffer, external_tbm_buffer);*/
- client_buffer = _e_eom_create_client_buffer(external_wl_buffer, fake_buffers.fake_buffers[0]);
- RETURNVALIFTRUE(client_buffer == NULL,
- ECORE_CALLBACK_PASS_ON,
- "ERROR: BUFF CHANGE: alloc client buffer");
+ if (buffer)
+ tbm_surface_destroy(buffer);
- _e_eom_add_client_buffer_to_list(client_buffer);
+ /* TODO: check if the fake buffer is NULL along the code */
+ return NULL;
+}
- /* Stop mirror mode */
- g_eom->is_mirror_mode = DOWN;
+static Eina_Bool
+_e_eom_util_create_buffers(E_EomOutputPtr eom_output, int width, int height)
+{
+ tbm_surface_info_s buffer_info;
+ tbm_surface_h buffer = NULL;
+ int i = 0;
- return ECORE_CALLBACK_PASS_ON;
+ /*
+ * TODO: Add support of other formats
+ */
+ buffer = tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+ GOTOIFTRUE(buffer == NULL, err, "can not create dst_buffer 1");
- /* TODO: deinitialization */
-}
+ /*
+ * TODO: temp code for testing, actual convert will be in _e_eom_put_src_to_dst()
+ */
+ memset(&buffer_info, 0x0, sizeof(tbm_surface_info_s));
+ if (tbm_surface_map(buffer,
+ TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
+ &buffer_info) != TBM_SURFACE_ERROR_NONE)
+ {
+ EOM_DBG("can not mmap buffer\n");
+ goto err;
+ }
-static void
-_e_eom_add_client_buffer_to_list(E_EomClientBufferPtr client_buffer)
-{
- _e_eom_client_buffers_list_free();
+ memset(buffer_info.planes[0].ptr, 0x0, buffer_info.planes[0].size);
+ tbm_surface_unmap(buffer);
- g_eom_event_data.client_buffers_list = eina_list_append(g_eom_event_data.client_buffers_list, client_buffer);
-}
+ eom_output->dst_buffers[0] = buffer;
-static void
-_e_eom_client_buffers_list_free()
-{
- E_EomClientBufferPtr *buffer = NULL;
- Eina_List *l;
+ /*
+ * TODO: Add support of other formats
+ */
+ buffer = tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+ GOTOIFTRUE(buffer == NULL, err, "can not create dst_buffer 2");
- EINA_LIST_FOREACH(g_eom_event_data.client_buffers_list, l, buffer)
+ /*
+ * TODO: temp code for testing, actual convert will be in _e_eom_put_src_to_dst()
+ */
+ memset(&buffer_info, 0x00, sizeof(tbm_surface_info_s));
+ if (tbm_surface_map(buffer,
+ TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
+ &buffer_info) != TBM_SURFACE_ERROR_NONE)
{
- if (buffer)
- {
- /* I am not sure if it is necessary */
- /* tbm_surface_internal_unref(buffer->tbm_buffer); */
+ EOM_DBG("can not mmap buffer\n");
+ goto err;
+ }
- /* TODO: Do we need reference that buffer? */
- /*e_comp_wl_buffer_reference(buffer->tbm_buffer, NULL);*/
+ memset(buffer_info.planes[0].ptr, 0x0, buffer_info.planes[0].size);
+ tbm_surface_unmap(buffer);
- g_eom_event_data.client_buffers_list = eina_list_remove(g_eom_event_data.client_buffers_list, buffer);
- E_FREE(buffer);
- }
- }
+ eom_output->dst_buffers[1] = buffer;
+
+ return EINA_TRUE;
+
+err:
+ for (i = 0; i < NUM_MAIN_BUF; i++)
+ if (eom_output->dst_buffers[i])
+ tbm_surface_destroy(eom_output->dst_buffers[i]);
+
+ return EINA_FALSE;
}
static E_EomClientBufferPtr
-_e_eom_create_client_buffer(E_Comp_Wl_Buffer *wl_buffer, tbm_surface_h tbm_buffer)
+_e_eom_util_create_client_buffer(E_Comp_Wl_Buffer *wl_buffer, tbm_surface_h tbm_buffer)
{
E_EomClientBufferPtr buffer = NULL;
buffer->wl_buffer = wl_buffer;
buffer->tbm_buffer = tbm_buffer;
/* TODO: It is not used right now */
- buffer->stamp = _e_eom_get_time_in_mseconds();
+ buffer->stamp = _e_eom_util_get_stamp();
/* I am not sure if it is necessary */
- /* tbm_surface_internal_ref(tbm_buffer); */
+ tbm_surface_internal_ref(tbm_buffer);
/* TODO: Do we need reference that buffer? */
- /*e_comp_wl_buffer_reference(buffer->tbm_buffer, NULL);*/
+ /* e_comp_wl_buffer_reference(buffer->tbm_buffer, NULL);*/
return buffer;
}
-static E_EomClientBufferPtr
-_e_eom_get_client_buffer_from_list()
-{
- E_EomClientBufferPtr buffer = NULL;
- Eina_List *l;
-
- /* There must be only one buffer */
- EINA_LIST_FOREACH(g_eom_event_data.client_buffers_list, l, buffer)
- {
- if (buffer)
- return buffer;
- }
-
- return NULL;
-}
-
-static int
-_e_eom_get_time_in_mseconds()
-{
- struct timespec tp;
-
- clock_gettime(CLOCK_MONOTONIC, &tp);
-
- return ((tp.tv_sec * 1000) + (tp.tv_nsec / 1000));
-}
-
-static Eina_Bool
-_e_eom_ecore_drm_activate_cb(void *data, int type EINA_UNUSED, void *event)
+static tbm_surface_h
+_e_eom_util_get_output_surface(const char *name)
{
- /*
- Ecore_Drm_Event_Activate *e = NULL;
- E_EomPtr eom = NULL;
-
- EOM_DBG("_e_eom_ecore_drm_activate_cb called\n");
-
- if ((!event) || (!data)) goto end;
- e = event;
- eom = data;
-
- EOM_DBG("e->active:%d\n", e->active);
+ Ecore_Drm_Output *primary_output = NULL;
+ Ecore_Drm_Device *dev;
+ const Eina_List *l;
+ tdm_output *tdm_output_obj = NULL;
+ tbm_surface_h tbm = NULL;
+ tdm_error err = TDM_ERROR_NONE;
+ int count = 0, i = 0;
- if (e->active)
- {
- ;
- }
- else
+ EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
{
- ;
+ primary_output = ecore_drm_device_output_name_find(dev, name);
+ if (primary_output != NULL)
+ break;
}
-end:
-
-*/
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static void
-_e_eom_wl_request_set_attribute_cb(struct wl_client *client, struct wl_resource *resource, uint32_t output_id, uint32_t attribute)
-{
- enum wl_eom_error eom_error = WL_EOM_ERROR_NONE;
- struct wl_resource *iterator = NULL;
- Eina_Bool changes = EINA_FALSE;
- Eina_Bool ret = EINA_FALSE;
- Eina_List *l;
-
- if (resource == g_eom->current_client)
- {
- /* Current client can set any flag it wants */
- _e_eom_set_eom_attribute_by_current_client(attribute);
- changes = EINA_TRUE;
- }
- else
+ if (primary_output == NULL)
{
- ret = _e_eom_set_eom_attribute(attribute);
- if (ret == EINA_FALSE)
+ EOM_ERR("ERROR: get primary output.(%s)\n", name);
+ EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev)
{
- EOM_DBG("set attribute FAILED\n");
-
- eom_error = WL_EOM_ERROR_OUTPUT_OCCUPIED;
- goto end;
+ primary_output = ecore_drm_output_primary_get(dev);
+ if (primary_output != NULL)
+ break;
}
- changes = EINA_TRUE;
+ if (primary_output == NULL)
+ {
+ EOM_ERR("ERROR: get primary output.(%s)\n", name);
+ return NULL;
+ }
}
- EOM_DBG("set attribute OK\n");
-
- /* If client has set WL_EOM_ATTRIBUTE_NONE, eom will be
- * switched to mirror mode
- */
- if (attribute == WL_EOM_ATTRIBUTE_NONE && g_eom->is_mirror_mode == DOWN)
+ tdm_output_obj = tdm_display_get_output(g_eom->dpy, 0, &err);
+ if (tdm_output_obj == NULL || err != TDM_ERROR_NONE)
{
- g_eom->is_mirror_mode = UP;
- ret = _e_eom_set_eom_attribute(WL_EOM_ATTRIBUTE_NONE);
- _e_eom_set_eom_mode(WL_EOM_MODE_MIRROR);
-
- _e_eom_client_buffers_list_free();
-
- ret = _e_eom_mirror_start(g_eom->int_output_name,
- g_eom->src_mode.w,
- g_eom->src_mode.h);
- GOTOIFTRUE(ret == EINA_FALSE,
- end,
- "ERROR: restore mirror mode after a client disconnection\n");
-
- goto end;
+ EOM_ERR("tdm_display_get_output 0 fail\n");
+ return NULL;
+ }
+ err = tdm_output_get_layer_count(tdm_output_obj, &count);
+ if (err != TDM_ERROR_NONE)
+ {
+ EOM_ERR("tdm_output_get_layer_count fail\n");
+ return NULL;
}
-end:
- wl_eom_send_output_attribute(resource,
- g_eom->id,
- _e_eom_get_eom_attribute(),
- _e_eom_get_eom_attribute_state(),
- eom_error);
-
- /* Notify eom clients that eom state has been changed */
- if (changes == EINA_TRUE)
+ for (i = 0; i < count; i++)
{
- EINA_LIST_FOREACH(g_eom->eom_clients, l, iterator)
+ tdm_layer *layer = tdm_output_get_layer(tdm_output_obj, i, NULL);
+ tdm_layer_capability capabilities = 0;
+ tdm_layer_get_capabilities(layer, &capabilities);
+ if (capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
{
- if (iterator == resource)
- continue;
-
- if (iterator)
+ tbm = tdm_layer_get_displaying_buffer(layer, &err);
+ if (err != TDM_ERROR_NONE)
{
- if (g_eom->is_mirror_mode == UP)
- wl_eom_send_output_attribute(iterator,
- g_eom->id,
- _e_eom_get_eom_attribute(),
- _e_eom_get_eom_attribute_state(),
- WL_EOM_ERROR_NONE);
- else
- wl_eom_send_output_attribute(iterator,
- g_eom->id,
- _e_eom_get_eom_attribute(),
- WL_EOM_ATTRIBUTE_STATE_LOST,
- WL_EOM_ERROR_NONE);
+ EOM_ERR("tdm_layer_get_displaying_buffer fail\n");
+ return NULL;
}
- }
-
- g_eom->current_client = resource;
+ break;
+ }
}
- return;
+ return tbm;
}
static void
-_e_eom_wl_request_get_output_info_cb(struct wl_client *client, struct wl_resource *resource, uint32_t output_id)
+_e_eom_util_calculate_fullsize(int src_h, int src_v, int dst_size_h, int dst_size_v,
+ int *dst_x, int *dst_y, int *dst_w, int *dst_h)
{
- EOM_DBG("output:%d\n", output_id);
-
- if (g_eom->outputs)
- {
- Eina_List *l;
- E_EomOutputPtr output = NULL;
+ double h_ratio, v_ratio;
- EINA_LIST_FOREACH(g_eom->outputs, l, output)
- {
- if (output->id == output_id)
- {
- EOM_DBG("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d\n",
- output->id, output->type, output->mode, output->w, output->h,
- output->phys_width, output->phys_height, output->status);
+ h_ratio = src_h / dst_size_h;
+ v_ratio = src_v / dst_size_v;
- wl_eom_send_output_info(resource, output->id, output->type, output->mode, output->w, output->h,
- output->phys_width, output->phys_height, output->status);
- }
- }
+ if (h_ratio == v_ratio)
+ {
+ *dst_x = 0;
+ *dst_y = 0;
+ *dst_w = dst_size_h;
+ *dst_h = dst_size_v;
+ }
+ else if (h_ratio < v_ratio)
+ {
+ *dst_y = 0;
+ *dst_h = dst_size_v;
+ *dst_w = dst_size_v * src_h / src_v;
+ *dst_x = (dst_size_h - *dst_w) / 2;
+ }
+ else /* (h_ratio > v_ratio) */
+ {
+ *dst_x = 0;
+ *dst_w = dst_size_h;
+ *dst_h = dst_size_h * src_h / src_v;
+ *dst_y = (dst_size_v - *dst_h) / 2;
}
}
-static const struct wl_eom_interface _e_eom_wl_implementation =
-{
- _e_eom_wl_request_set_attribute_cb,
- _e_eom_wl_request_get_output_info_cb
-};
-
-/* wl_eom global object destroy function */
-static void
-_e_eom_wl_resource_destory_cb(struct wl_resource *resource)
+static int
+_e_eom_util_get_stamp()
{
- struct wl_resource *iterator = NULL;
- Eina_List *l = NULL;
- Eina_Bool ret;
+ struct timespec tp;
- EOM_DBG("client unbind\n");
+ clock_gettime(CLOCK_MONOTONIC, &tp);
- g_eom->eom_clients = eina_list_remove(g_eom->eom_clients, resource);
+ return ((tp.tv_sec * 1000) + (tp.tv_nsec / 1000));
+}
- /* If not current client has been destroyed do nothing */
- if (resource != g_eom->current_client)
- goto end2;
+#if 0
+static void
+_e_eom_util_draw(tbm_surface_h surface)
+{
+ int i = 0, j = 0;
- /* If a client has been disconnected and mirror mode has not
- * been restore, start mirror mode
- */
- if (g_eom->is_mirror_mode == DOWN)
- {
- g_eom->is_mirror_mode = UP;
- ret = _e_eom_set_eom_attribute(WL_EOM_ATTRIBUTE_NONE);
- _e_eom_set_eom_mode(WL_EOM_MODE_MIRROR);
+ tbm_bo bo = tbm_surface_internal_get_bo(surface, 0);
+ RETURNIFTRUE(bo == NULL, "bo is NULL");
- _e_eom_client_buffers_list_free();
+ unsigned int *mm = (unsigned int *)tbm_bo_map(bo, TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE).ptr;
+ RETURNIFTRUE(mm == NULL, "mm is NULL");
- ret = _e_eom_mirror_start(g_eom->int_output_name,
- g_eom->src_mode.w,
- g_eom->src_mode.h);
- GOTOIFTRUE(ret == EINA_FALSE,
- end,
- "ERROR: restore mirror mode after a client disconnection\n");
- }
+ unsigned char r = 0;
+ unsigned char g = 255;
+ unsigned char b = 0;
+ unsigned char a = 0;
-end:
- /* Notify eom clients that eom state has been changed */
- EINA_LIST_FOREACH(g_eom->eom_clients, l, iterator)
- {
- if (iterator)
- {
- wl_eom_send_output_attribute(iterator,
- g_eom->id,
- _e_eom_get_eom_attribute(),
- _e_eom_get_eom_attribute_state(),
- WL_EOM_ERROR_NONE);
- }
- }
+ int w = (int)tbm_surface_get_width(surface);
+ int h = (int)tbm_surface_get_height(surface);
-end2:
- g_eom->current_client = NULL;
+ for (i = 0; i < w; i++)
+ for (j = 0; j < h/2; j++)
+ {
+ mm[i*w + j] = r << 24 | g << 16 | b << 8 | a;
+ }
}
+#endif
-/* wl_eom global object bind function */
static void
-_e_eom_wl_bind_cb(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+_e_eom_client_add_buffer(E_EomClientPtr client, E_EomClientBufferPtr buffer)
{
- enum wl_eom_type eom_type = WL_EOM_TYPE_NONE;
- struct wl_resource *resource = NULL;
+ _e_eom_client_free_buffers(client);
- RETURNIFTRUE(data == NULL, "ERROR: data is NULL");
+ client->buffers = eina_list_append(client->buffers, buffer);
+}
- E_EomPtr eom = data;
+static void
+_e_eom_client_free_buffers(E_EomClientPtr client)
+{
+ E_EomClientBufferPtr buffer = NULL;
+ Eina_List *l;
- resource = wl_resource_create(client,
- &wl_eom_interface,
- MIN(version, 1),
- id);
- if (resource == NULL)
+ EINA_LIST_FOREACH(client->buffers, l, buffer)
{
- EOM_ERR("error. resource is null. (version :%d, id:%d)\n", version, id);
- wl_client_post_no_memory(client);
- return;
- }
-
- wl_resource_set_implementation(resource,
- &_e_eom_wl_implementation,
- eom,
- _e_eom_wl_resource_destory_cb);
-
- eom_type = _e_eom_output_name_to_eom_type(g_eom->ext_output_name);
-
- wl_eom_send_output_type(resource,
- eom->id,
- eom_type,
- _e_eom_get_eom_status());
-
- wl_eom_send_output_attribute(resource,
- eom->id,
- _e_eom_get_eom_attribute(),
- _e_eom_get_eom_attribute_state(),
- WL_EOM_ERROR_NONE);
-
- wl_eom_send_output_mode(resource,
- eom->id,
- _e_eom_get_eom_mode());
-
- EOM_DBG("send - output count : %d\n", g_eom->output_count);
- wl_eom_send_output_count(resource,
- g_eom->output_count);
+ if (buffer)
+ {
+ /* I am not sure if it is necessary */
+ if (buffer->tbm_buffer)
+ tbm_surface_internal_unref(buffer->tbm_buffer);
- if (g_eom->outputs)
- {
- Eina_List *l;
- E_EomOutputPtr output = NULL;
+ /* TODO: Do we need reference that buffer? */
+ /* e_comp_wl_buffer_reference(buffer->tbm_buffer, NULL); */
- EINA_LIST_FOREACH(g_eom->outputs, l, output)
- {
- EOM_DBG("send - id : %d, type : %d, mode : %d, w : %d, h : %d, w_mm : %d, h_mm : %d, conn : %d\n",
- output->id, output->type, output->mode, output->w, output->h,
- output->phys_width, output->phys_height, output->status);
- wl_eom_send_output_info(resource, output->id, output->type, output->mode, output->w, output->h,
- output->phys_width, output->phys_height, output->status);
+ client->buffers = eina_list_remove(client->buffers, buffer);
+ E_FREE(buffer);
}
}
-
- g_eom->eom_clients = eina_list_append(g_eom->eom_clients, resource);
}
-static void
-_e_eom_deinit()
+static E_EomClientBufferPtr
+_e_eom_client_get_buffer(E_EomClientPtr client)
{
- Ecore_Event_Handler *h = NULL;
-
- if (g_eom == NULL) return;
+ E_EomClientBufferPtr buffer = NULL;
+ Eina_List *l;
- if (g_eom->handlers)
+ /* There must be only one buffer */
+ EINA_LIST_FOREACH(client->buffers, l, buffer)
{
- EINA_LIST_FREE(g_eom->handlers, h)
- ecore_event_handler_del(h);
+ if (buffer)
+ return buffer;
}
- if (g_eom->dpy) tdm_display_deinit(g_eom->dpy);
- if (g_eom->bufmgr) tbm_bufmgr_deinit(g_eom->bufmgr);
-
- if (g_eom->global) wl_global_destroy(g_eom->global);
-
- E_FREE(g_eom);
+ return NULL;
}
-static Eina_Bool
-_e_eom_output_info_get(tdm_display *dpy)
+static E_EomClientPtr
+_e_eom_client_get_by_resource(struct wl_resource *resource)
{
- tdm_error ret = TDM_ERROR_NONE;
- int i, count;
-
- ret = tdm_display_get_output_count(dpy, &count);
- RETURNVALIFTRUE(ret != TDM_ERROR_NONE,
- EINA_FALSE,
- "tdm_display_get_output_count fail");
- RETURNVALIFTRUE(count <= 1,
- EINA_FALSE,
- "output count is 1. device doesn't support external outputs.\n");
-
- g_eom->output_count = count - 1;
- EOM_DBG("external output count : %d\n", g_eom->output_count);
+ Eina_List *l;
+ E_EomClientPtr client;
- /* skip main output id:0 */
- /* start from 1 */
- for (i = 1; i < count; i++)
+ EINA_LIST_FOREACH(g_eom->clients, l, client)
{
- const tdm_output_mode *mode = NULL;
- E_EomOutputPtr new_output = NULL;
- unsigned int mmWidth, mmHeight;
- tdm_output_conn_status status;
- tdm_output *output = NULL;
- tdm_output_type type;
+ if (client && client->resource == resource)
+ return client;
+ }
- output = tdm_display_get_output(dpy, i, &ret);
- GOTOIFTRUE(ret != TDM_ERROR_NONE,
- err,
- "tdm_display_get_output fail(ret:%d)", ret);
+ return NULL;
+}
- GOTOIFTRUE(output == NULL,
- err,
- "tdm_display_get_output fail(no output:%d)", ret);
+static E_EomClientPtr
+_e_eom_client_current_by_id_get(int id)
+{
+ Eina_List *l;
+ E_EomClientPtr client;
- ret = tdm_output_get_output_type(output, &type);
- GOTOIFTRUE(ret != TDM_ERROR_NONE,
- err,
- "tdm_output_get_output_type fail(%d)", ret);
+ EINA_LIST_FOREACH(g_eom->clients, l, client)
+ {
+ if (client &&
+ client->current == EINA_TRUE &&
+ client->output_id == id)
+ return client;
+ }
- new_output = E_NEW(E_EomOutput, 1);
- GOTOIFTRUE(new_output == NULL,
- err,
- "calloc fail");
+ return NULL;
+}
- ret = tdm_output_get_conn_status(output, &status);
- if (ret != TDM_ERROR_NONE)
- {
- EOM_ERR("tdm_output_get_conn_status fail(%d)", ret);
- free(new_output);
- goto err;
- }
- new_output->id = i;
- new_output->type = type;
- new_output->status = status;
- new_output->mode = EOM_OUTPUT_MODE_NONE;
- new_output->output = output;
+static Eina_Bool
+_e_eom_init()
+{
+ Eina_Bool ret = EINA_FALSE;
- ret = tdm_output_add_change_handler(output, _e_eom_tdm_output_status_change_cb, NULL);
- if (ret != TDM_ERROR_NONE)
- {
- EOM_ERR("tdm_output_add_change_handler fail(%d)", ret);
- free(new_output);
- goto err;
- }
+ EINA_SAFETY_ON_NULL_GOTO(e_comp_wl, err);
- if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
- {
- EOM_DBG("create(%d)output, type:%d, status:%d",
- new_output->id, new_output->type, new_output->status);
- g_eom->outputs = eina_list_append(g_eom->outputs, new_output);
- continue;
- }
- new_output->status = TDM_OUTPUT_CONN_STATUS_CONNECTED;
+ g_eom = E_NEW(E_Eom, 1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(g_eom, EINA_FALSE);
- ret = tdm_output_get_mode(output, &mode);
- if (ret != TDM_ERROR_NONE)
- {
- EOM_ERR("tdm_output_get_mode fail(%d)", ret);
- free(new_output);
- goto err;
- }
+ g_eom->global = wl_global_create(e_comp_wl->wl.disp,
+ &wl_eom_interface,
+ 1,
+ g_eom,
+ _e_eom_cb_wl_bind);
- if (mode == NULL)
- {
- new_output->w = 0;
- new_output->h = 0;
- }
+ uint32_t id = wl_display_get_serial(e_comp_wl->wl.disp);
+ EOM_DBG("eom name: %d", id);
- else
- {
- new_output->w = mode->hdisplay;
- new_output->h = mode->vdisplay;
- }
+ EINA_SAFETY_ON_NULL_GOTO(g_eom->global, err);
- ret = tdm_output_get_physical_size(output, &mmWidth, &mmHeight);
- if (ret != TDM_ERROR_NONE)
- {
- EOM_ERR("tdm_output_get_conn_status fail(%d)", ret);
- free(new_output);
- goto err;
- }
- new_output->phys_width = mmWidth;
- new_output->phys_height = mmHeight;
+ ret = _e_eom_init_internal();
+ GOTOIFTRUE(ret == EINA_FALSE, err, "failed init_internal()");
- EOM_DBG("create(%d)output, type:%d, status:%d, w:%d, h:%d, mm_w:%d, mm_h:%d",
- new_output->id, new_output->type, new_output->status,
- new_output->w, new_output->h, new_output->phys_width, new_output->phys_height);
+ E_LIST_HANDLER_APPEND(g_eom->handlers, ECORE_DRM_EVENT_ACTIVATE, _e_eom_cb_ecore_drm_activate, g_eom);
+ E_LIST_HANDLER_APPEND(g_eom->handlers, ECORE_DRM_EVENT_OUTPUT, _e_eom_cb_ecore_drm_output, g_eom);
+ E_LIST_HANDLER_APPEND(g_eom->handlers, E_EVENT_CLIENT_BUFFER_CHANGE, _e_eom_cb_client_buffer_change, NULL);
- g_eom->outputs = eina_list_append(g_eom->outputs, new_output);
- }
+ g_eom->main_output_name = NULL;
return EINA_TRUE;
err:
- if (g_eom->outputs)
- {
- Eina_List *l;
- E_EomOutputPtr output;
-
- EINA_LIST_FOREACH(g_eom->outputs, l, output)
- {
- free(output);
- }
- eina_list_free(g_eom->outputs);
- }
-
+ _e_eom_deinit();
return EINA_FALSE;
}
g_eom->bufmgr = tbm_bufmgr_init(g_eom->fd);
GOTOIFTRUE(g_eom->bufmgr == NULL, err, "tbm_bufmgr_init fail");
- if (_e_eom_output_info_get(g_eom->dpy) != EINA_TRUE)
+ if (_e_eom_output_init(g_eom->dpy) != EINA_TRUE)
{
- EOM_ERR("_e_eom_output_info_get fail\n");
+ EOM_ERR("_e_eom_output_init fail\n");
goto err;
}
return EINA_FALSE;
}
-static Eina_Bool
-_e_eom_init()
+static void
+_e_eom_deinit()
{
- Eina_Bool ret = EINA_FALSE;
-
- EINA_SAFETY_ON_NULL_GOTO(e_comp_wl, err);
-
- g_eom = E_NEW(E_Eom, 1);
- EINA_SAFETY_ON_NULL_RETURN_VAL(g_eom, EINA_FALSE);
-
- g_eom->global = wl_global_create(e_comp_wl->wl.disp,
- &wl_eom_interface,
- 1,
- g_eom,
- _e_eom_wl_bind_cb);
-
- EINA_SAFETY_ON_NULL_GOTO(g_eom->global, err);
-
- ret = _e_eom_init_internal();
- GOTOIFTRUE(ret == EINA_FALSE, err, "failed init_internal()");
-
- E_LIST_HANDLER_APPEND(g_eom->handlers, ECORE_DRM_EVENT_ACTIVATE, _e_eom_ecore_drm_activate_cb, g_eom);
- E_LIST_HANDLER_APPEND(g_eom->handlers, ECORE_DRM_EVENT_OUTPUT, _e_eom_ecore_drm_output_cb, g_eom);
- E_LIST_HANDLER_APPEND(g_eom->handlers, E_EVENT_CLIENT_BUFFER_CHANGE, _e_eom_client_buffer_change, NULL);
+ Ecore_Event_Handler *h = NULL;
- g_eom->is_external_init = DOWN;
- g_eom->is_internal_grab = DOWN;
- g_eom->ext_output_name = NULL;
- g_eom->int_output_name = NULL;
+ if (g_eom == NULL) return;
- g_eom->current_client = NULL;
+ if (g_eom->handlers)
+ {
+ EINA_LIST_FREE(g_eom->handlers, h)
+ ecore_event_handler_del(h);
+ }
- _e_eom_set_eom_attribute_state(WL_EOM_ATTRIBUTE_STATE_NONE);
- _e_eom_set_eom_attribute(WL_EOM_ATTRIBUTE_NONE);
- _e_eom_set_eom_status(WL_EOM_STATUS_NONE);
- _e_eom_set_eom_mode(WL_EOM_MODE_NONE);
+ if (g_eom->dpy) tdm_display_deinit(g_eom->dpy);
+ if (g_eom->bufmgr) tbm_bufmgr_deinit(g_eom->bufmgr);
- return EINA_TRUE;
+ if (g_eom->global) wl_global_destroy(g_eom->global);
-err:
- _e_eom_deinit();
- return EINA_FALSE;
+ E_FREE(g_eom);
}
E_API void *
/* Save something to be kept */
return 1;
}
+