--- /dev/null
+#include "e_display_intern.h"
+#include "e_hwc_intern.h"
+#include "e_hwc_windows_intern.h"
+#include "e_hwc_planes_intern.h"
+#include "e_utils_intern.h"
+#include "e_scale_intern.h"
+#include "e_comp_screen_intern.h"
+#include "e_comp_intern.h"
+
+#include <device/board-internal.h>
+#include <tbm_drm_helper.h>
+#include <gbm.h>
+
+#define NUM_SW_FORMAT (sizeof(sw_formats) / sizeof(sw_formats[0]))
+
+typedef struct _E_Display E_Display;
+
+struct _E_Display
+{
+ tdm_display *tdisplay;
+ int fd;
+
+ void *gdevice;
+ int gdevice_fd;
+
+ Eina_Bool pp_enabled;
+ Eina_List *available_pp_formats;
+
+ Ecore_Fd_Handler *hdlr;
+
+ int num_outputs;
+ Eina_List *outputs; // available screens
+};
+
+static E_Display *g_display = NULL; // global e_display
+
+static tbm_format sw_formats[] = {
+ TBM_FORMAT_ARGB8888,
+ TBM_FORMAT_XRGB8888,
+ TBM_FORMAT_YUV420,
+ TBM_FORMAT_YVU420,
+};
+
+static char *
+_e_display_dpms_to_string(E_OUTPUT_DPMS dpms)
+{
+ switch (dpms)
+ {
+ case E_OUTPUT_DPMS_ON:
+ return "DPMS_ON";
+ break;
+ case E_OUTPUT_DPMS_STANDBY:
+ return "DPMS_STANDBY";
+ break;
+ case E_OUTPUT_DPMS_SUSPEND:
+ return "DPMS_SUSPEND";
+ break;
+ case E_OUTPUT_DPMS_OFF:
+ return "DPMS_OFF";
+ break;
+ default:
+ return "Unknown";
+ }
+}
+
+static tdm_layer *
+_e_display_video_tdm_layer_get(tdm_output *output)
+{
+ int i, count = 0;
+#ifdef CHECKING_PRIMARY_ZPOS
+ int primary_idx = 0, primary_zpos = 0;
+ tdm_layer *primary_layer;
+#endif
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
+
+ tdm_output_get_layer_count(output, &count);
+ for (i = 0; i < count; i++)
+ {
+ tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
+ tdm_layer_capability capabilities = 0;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
+
+ tdm_layer_get_capabilities(layer, &capabilities);
+ if (capabilities & TDM_LAYER_CAPABILITY_VIDEO)
+ return layer;
+ }
+
+#ifdef CHECKING_PRIMARY_ZPOS
+ tdm_output_get_primary_index(output, &primary_idx);
+ primary_layer = tdm_output_get_layer(output, primary_idx, NULL);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(primary_layer, NULL);
+ tdm_layer_get_zpos(primary_layer, &primary_zpos);
+#endif
+
+ for (i = 0; i < count; i++)
+ {
+ tdm_layer *layer = tdm_output_get_layer(output, i, NULL);
+ tdm_layer_capability capabilities = 0;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(layer, NULL);
+
+ tdm_layer_get_capabilities(layer, &capabilities);
+ if (capabilities & TDM_LAYER_CAPABILITY_OVERLAY)
+ {
+#ifdef CHECKING_PRIMARY_ZPOS
+ int zpos = 0;
+ tdm_layer_get_zpos(layer, &zpos);
+ if (zpos >= primary_zpos) continue;
+#endif
+ return layer;
+ }
+ }
+
+ return NULL;
+}
+
+static E_Output *
+_e_display_eoutput_get_by_toutput(tdm_output *output)
+{
+ Eina_List *l;
+ E_Output *eo;
+
+ EINA_LIST_FOREACH(e_display_outputs_get(), l, eo)
+ if (eo->toutput == output)
+ return eo;
+
+ return NULL;
+}
+
+static char *
+_layer_cap_to_str(tdm_layer_capability caps, tdm_layer_capability cap)
+{
+ if (caps & cap)
+ {
+ if (cap == TDM_LAYER_CAPABILITY_CURSOR) return "cursor ";
+ else if (cap == TDM_LAYER_CAPABILITY_PRIMARY) return "primary ";
+ else if (cap == TDM_LAYER_CAPABILITY_OVERLAY) return "overlay ";
+ else if (cap == TDM_LAYER_CAPABILITY_GRAPHIC) return "graphics ";
+ else if (cap == TDM_LAYER_CAPABILITY_VIDEO) return "video ";
+ else if (cap == TDM_LAYER_CAPABILITY_TRANSFORM) return "transform ";
+ else if (cap == TDM_LAYER_CAPABILITY_RESEVED_MEMORY) return "reserved_memory ";
+ else if (cap == TDM_LAYER_CAPABILITY_NO_CROP) return "no_crop ";
+ else return "unkown";
+ }
+ return "";
+}
+
+static void
+_display_output_mode_change_cb(tdm_output *toutput, unsigned int index, void *user_data)
+{
+ E_Display *display = user_data;
+ E_Output *output = NULL;
+ Eina_Bool find = EINA_FALSE;
+ int count, num;
+ E_Output_Mode *set_emode = NULL, *current_emode = NULL;
+ E_Output_Mode *emode = NULL;
+ Eina_List *modelist = NULL, *l, *ll;
+
+ EINA_SAFETY_ON_NULL_RETURN(display);
+
+ EINA_LIST_FOREACH_SAFE(display->outputs, l, ll, output)
+ {
+ if (output->toutput == toutput)
+ {
+ find = EINA_TRUE;
+ break;
+ }
+ }
+ EINA_SAFETY_ON_FALSE_RETURN(find == EINA_TRUE);
+
+ current_emode = e_output_current_mode_get(output);
+ EINA_SAFETY_ON_NULL_RETURN(current_emode);
+
+ modelist = e_output_mode_list_get(output);
+ if (modelist)
+ {
+ num = eina_list_count(modelist);
+ EINA_SAFETY_ON_FALSE_RETURN(index < num);
+
+ count = 0;
+ EINA_LIST_FOREACH(modelist, l, emode)
+ {
+ if (count == index)
+ {
+ set_emode = emode;
+ break;
+ }
+ count++;
+ }
+
+ if (set_emode)
+ {
+ EINA_SAFETY_ON_TRUE_RETURN(current_emode == set_emode);
+
+ ELOGF("COMP_SCREEN","request mode change(%d) (%dx%d, %lf) -> (%dx%d, %lf)\n",
+ NULL, index, current_emode->w, current_emode->h, current_emode->refresh,
+ set_emode->w, set_emode->h, set_emode->refresh);
+
+ e_output_external_mode_change(output, set_emode);
+ }
+ }
+}
+
+static void
+_display_output_destroy_cb(tdm_output *toutput, void *user_data)
+{
+ E_Display *display = user_data;
+ E_Output *output = NULL;
+ Eina_List *l, *ll;
+
+ EINA_SAFETY_ON_NULL_RETURN(display);
+
+ tdm_output_remove_destroy_handler(toutput, _display_output_destroy_cb, display);
+
+ EINA_LIST_FOREACH_SAFE(display->outputs, l, ll, output)
+ {
+ if (output->toutput == toutput)
+ {
+ display->num_outputs--;
+ display->outputs = eina_list_remove_list(display->outputs, l);
+ e_output_del(output);
+ }
+ }
+}
+
+static void
+_e_display_cb_output_created(tdm_display *dpy, tdm_output *toutput, void *user_data)
+{
+ E_Display *display = user_data;
+ E_Output *output = NULL;
+ tdm_error ret = TDM_ERROR_NONE;
+
+ EINA_SAFETY_ON_NULL_RETURN(display);
+
+ TRACE_DS_BEGIN(OUTPUT:NEW);
+ output = e_output_new1(display->num_outputs);
+ EINA_SAFETY_ON_NULL_GOTO(output, fail);
+ if (output->toutput != toutput) goto fail;
+ TRACE_DS_END();
+
+ TRACE_DS_BEGIN(OUTPUT:UPDATE);
+ if (!e_output_update(output))
+ {
+ ERR("fail to e_output_update.");
+ e_output_del(output);
+ goto fail;
+ }
+ TRACE_DS_END();
+
+ /* todo : add tdm_output_add_mode_change_request_handler()*/
+ ret = tdm_output_add_mode_change_request_handler(toutput, _display_output_mode_change_cb, display);
+ if (ret != TDM_ERROR_NONE)
+ {
+ ERR("fail to add output mode change handler.");
+ e_output_del(output);
+ return;
+ }
+
+ ret = tdm_output_add_destroy_handler(toutput, _display_output_destroy_cb, display);
+ if (ret != TDM_ERROR_NONE)
+ {
+ ERR("fail to add output destroy handler.");
+ e_output_del(output);
+ return;
+ }
+
+ display->outputs = eina_list_append(display->outputs, output);
+ display->num_outputs++;
+
+ return;
+
+fail:
+ TRACE_DS_END();
+}
+
+static Eina_Bool
+_display_fake_output_set(E_Display *display)
+{
+ E_Output *primary_output = NULL;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(display, EINA_FALSE);
+
+ primary_output = e_display_primary_output_get();
+ EINA_SAFETY_ON_NULL_RETURN_VAL(primary_output, EINA_FALSE);
+
+ if (!e_output_hwc_setup(primary_output))
+ {
+ ERR("fail to e_output_hwc_setup.");
+ return EINA_FALSE;
+ }
+
+ if (!e_output_fake_config_set(primary_output, 2, 1))
+ {
+ ERR("Fail to set the fake output config!");
+ return EINA_FALSE;
+ }
+
+ return EINA_TRUE;
+}
+
+static void
+_display_deinit_outputs(E_Display *display)
+{
+ E_Output *output;
+ Eina_List *l, *ll;
+
+ tdm_display_remove_output_create_handler(display->tdisplay, _e_display_cb_output_created, display);
+
+ // free up e_outputs
+ EINA_LIST_FOREACH_SAFE(display->outputs, l, ll, output)
+ {
+ display->outputs = eina_list_remove_list(display->outputs, l);
+ e_output_del(output);
+ }
+
+ e_hwc_ecore_evas_deinit();
+ e_hwc_deinit();
+ e_hwc_windows_deinit();
+ e_hwc_planes_deinit();
+
+ e_output_shutdown();
+}
+
+static Eina_Bool
+_e_display_init_outputs(E_Display *display)
+{
+ E_Output *output = NULL;
+ E_Output_Mode *mode = NULL;
+ tdm_display *tdisplay = display->tdisplay;
+ int num_outputs;
+ int i;
+ Eina_Bool scale_updated = EINA_FALSE;
+ Eina_Bool connection_check = EINA_FALSE;
+ tdm_error err = TDM_ERROR_NONE;
+ char bootmode[32];
+ int ret;
+
+ /* init e_output */
+ if (!e_output_init())
+ {
+ ERR("fail to e_output_init.");
+ return EINA_FALSE;
+ }
+
+ /* get the num of outputs */
+ err = tdm_display_get_output_count(tdisplay, &num_outputs);
+ if ((err != TDM_ERROR_NONE) ||
+ (num_outputs < 1))
+ {
+ ERR("fail to get tdm_display_get_output_count\n");
+ return EINA_FALSE;
+ }
+ display->num_outputs = num_outputs;
+
+ ELOGF("COMP_SCREEN","num_outputs = %i", NULL, display->num_outputs);
+
+ if (!e_hwc_init())
+ {
+ ERR("e_hwc_init failed");
+ goto fail;
+ }
+
+ if (!e_hwc_planes_init())
+ {
+ ERR("e_hwc_planes_init failed");
+ goto fail;
+ }
+
+ if (!e_hwc_windows_init())
+ {
+ ERR("e_hwc_windows_init failed");
+ goto fail;
+ }
+
+ for (i = 0; i < num_outputs; i++)
+ {
+ e_main_ts_begin("\tE_Output New");
+ output = e_output_new1(i);
+ if (!output)
+ {
+ e_main_ts_end("\tE_Output New Failed");
+ goto fail;
+ }
+
+ e_main_ts_begin("\tE_Output Update");
+ if (!e_output_update(output))
+ {
+ e_main_ts_end("\tE_Output Update Failed");
+ ERR("fail to e_output_update.");
+ goto fail;
+ }
+ e_main_ts_end("\tE_Output Update Done");
+
+ display->outputs = eina_list_append(display->outputs, output);
+
+ if (!e_output_connected(output)) continue;
+
+ connection_check = EINA_TRUE;
+
+ /* setting with the best mode and enable the output */
+ e_main_ts_begin("\tE_Output Find Best Mode");
+ mode = e_output_best_mode_find(output);
+ if (!mode)
+ {
+ e_main_ts_end("\tE_Output Find Best Mode Failed");
+ ERR("fail to get best mode.");
+ goto fail;
+ }
+ e_main_ts_end("\tE_Output Find Best Mode Done");
+
+ e_main_ts_begin("\tE_Output Mode Apply");
+ if (!e_output_mode_apply(output, mode))
+ {
+ e_main_ts_end("\tE_Output Mode Apply Failed");
+ ERR("fail to e_output_mode_apply.");
+ goto fail;
+ }
+ e_main_ts_end("\tE_Output Mode Apply Done");
+
+ e_main_ts_begin("\tE_Output Set DPMS ON");
+ ret = device_board_get_boot_mode(bootmode, sizeof(bootmode));
+ if (!ret && !e_util_strcmp(bootmode, "silent"))
+ {
+ INF("silent reboot. do not set dpms");
+ }
+ else
+ {
+ if (!e_output_dpms_set(output, E_OUTPUT_DPMS_ON))
+ {
+ e_main_ts_end("\tE_Output Set DPMS ON Failed");
+ ERR("fail to e_output_dpms.");
+ goto fail;
+ }
+ }
+
+ e_main_ts_end("\tE_Output Set DPMS ON Done");
+
+ e_main_ts_begin("\tE_Output Hwc Setup");
+ if (!e_output_hwc_setup(output))
+ {
+ e_main_ts_end("\tE_Output Hwc Setup Failed");
+ ERR("fail to e_output_hwc_setup.");
+ goto fail;
+ }
+ e_main_ts_end("\tE_Output Hwc Setup Done");
+
+ /* update e_scale with first available output size */
+ if ((e_config->scale.for_tdm) && (!scale_updated))
+ {
+ double target_inch;
+ int dpi;
+
+ target_inch = (round((sqrt(output->info.size.w * output->info.size.w + output->info.size.h * output->info.size.h) / 25.4) * 10) / 10);
+ dpi = (round((sqrt(mode->w * mode->w + mode->h * mode->h) / target_inch) * 10) / 10);
+
+ e_scale_manual_update(dpi);
+ scale_updated = EINA_TRUE;
+ }
+ }
+
+ //TODO: if there is no output connected, make the fake output which is connected.
+ if (!connection_check)
+ {
+ if (!_display_fake_output_set(display))
+ goto fail;
+ }
+
+ // FIXME: donot call e_comp_screen function at e_display. move this function to other plane, need refactoring
+ e_comp_screen_size_update(e_comp->e_comp_screen);
+
+ e_main_ts_begin("\tE_Hwc Ecore_Evas Init");
+ if (!e_hwc_ecore_evas_init())
+ {
+ e_main_ts_end("\ttE_Hwc Ecore_Evas Init Failed");
+ ERR("fail to e_hwc_ecore_evas_init");
+ goto fail;
+ }
+ e_main_ts_end("\tE_Hwc Ecore_Evas Init Done");
+
+ if (tdm_display_add_output_create_handler(tdisplay, _e_display_cb_output_created, display))
+ goto fail;
+
+ return EINA_TRUE;
+
+fail:
+ _display_deinit_outputs(display);
+
+ return EINA_FALSE;
+}
+
+static Eina_Bool
+_e_display_cb_tdm_display_interrupt(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
+{
+ E_Display *display;
+ tdm_error ret;
+
+ if (!(display = data)) return ECORE_CALLBACK_RENEW;
+
+ ret = tdm_display_handle_events(display->tdisplay);
+ if (ret != TDM_ERROR_NONE)
+ ERR("tdm_display_handle_events failed");
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+EINTERN Eina_Bool
+e_display_init(void)
+{
+ E_Display *display;
+ tdm_display_capability capabilities;
+ const tbm_format *pp_formats;
+ tdm_error error = TDM_ERROR_NONE;
+ int count, i;
+ int fd;
+
+ if (g_display) return EINA_TRUE;
+
+ display = E_NEW(E_Display, 1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(display, EINA_FALSE);
+
+ g_display = display;
+
+ display->tdisplay = tdm_display_init(&error);
+ if (!display->tdisplay)
+ {
+ ERR("fail to tdm_display_init");
+ goto fail;
+ }
+
+ display->gdevice_fd = -1;
+ display->fd = -1;
+
+ tdm_display_get_fd(display->tdisplay, &fd);
+ if (fd < 0)
+ {
+ ERR("fail to get tdm_display fd");
+ goto fail;
+ }
+
+ display->fd = dup(fd);
+
+ error = tdm_display_get_capabilities(display->tdisplay, &capabilities);
+ if (error != TDM_ERROR_NONE)
+ {
+ ERR("tdm get_capabilities failed");
+ goto fail;
+ }
+
+ /* check the pp_support */
+ if (capabilities & TDM_DISPLAY_CAPABILITY_PP)
+ {
+ error = tdm_display_get_pp_available_formats(display->tdisplay,
+ &pp_formats, &count);
+ if (error != TDM_ERROR_NONE)
+ ERR("fail to get available pp formats");
+ else
+ {
+ display->pp_enabled = EINA_TRUE;
+ for (i = 0 ; i < count ; i++)
+ {
+ display->available_pp_formats =
+ eina_list_append(display->available_pp_formats,
+ &pp_formats[i]);
+ }
+ }
+ }
+
+ display->hdlr = ecore_main_fd_handler_add(display->fd, ECORE_FD_READ,
+ _e_display_cb_tdm_display_interrupt, display, NULL, NULL);
+
+ if (e_comp_socket_init("tdm-socket"))
+ PRCTL("[Winsys] change permission and create sym link for %s", "tdm-socket");
+
+ if (!_e_display_init_outputs(display))
+ {
+ ERR("tdm get_capabilities failed");
+ goto fail;
+ }
+
+ return EINA_TRUE;
+
+fail:
+ if (display->hdlr) ecore_main_fd_handler_del(display->hdlr);
+ if (display->fd >= 0) close(display->fd);
+ if (display->tdisplay) tdm_display_deinit(display->tdisplay);
+
+ E_FREE(display);
+ g_display = NULL;
+
+ return EINA_FALSE;
+}
+
+
+EINTERN void
+e_display_shutdown(void)
+{
+ Eina_List *l, *ll;
+ tbm_format *formats;
+
+ if (!g_display) return;
+
+ _display_deinit_outputs(g_display);
+
+ if (g_display->pp_enabled)
+ {
+ EINA_LIST_FOREACH_SAFE(g_display->available_pp_formats, l, ll, formats)
+ {
+ if (!formats) continue;
+ g_display->available_pp_formats = eina_list_remove(g_display->available_pp_formats, l);
+ }
+ }
+ if (g_display->gdevice) gbm_device_destroy(g_display->gdevice);
+ if (g_display->gdevice_fd >= 0) close(g_display->gdevice_fd);
+ if (g_display->fd >= 0) close(g_display->fd);
+ if (g_display->hdlr) ecore_main_fd_handler_del(g_display->hdlr);
+ if (g_display->tdisplay) tdm_display_deinit(g_display->tdisplay);
+
+ E_FREE(g_display);
+ g_display = NULL;
+}
+
+
+EINTERN E_Output *
+e_display_primary_output_get(void)
+{
+ E_Output *output = NULL, *o;
+ const Eina_List *l;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(g_display, NULL);
+
+ EINA_LIST_FOREACH(g_display->outputs, l, o)
+ {
+ unsigned int pipe = 0;
+ tdm_error error;
+
+ error = tdm_output_get_pipe(o->toutput, &pipe);
+ if (error != TDM_ERROR_NONE || pipe != 0)
+ continue;
+
+ output = o;
+ break;
+ }
+
+ if (!output)
+ {
+ ERR("couldn't find the primary output");
+ return NULL;
+ }
+
+ return output;
+}
+
+EINTERN void *
+e_display_tdm_display_get(void)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(g_display, NULL);
+
+ return (void *)g_display->tdisplay;
+}
+
+EINTERN void *
+e_display_gbm_device_get(void)
+{
+ int fd;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(g_display, NULL);
+
+ if (g_display->gdevice) return g_display->gdevice;
+
+ fd = tbm_drm_helper_get_master_fd();
+ EINA_SAFETY_ON_FALSE_RETURN_VAL(fd >= 0, NULL);
+
+ g_display->gdevice = gbm_create_device(fd);
+ if (!g_display->gdevice)
+ {
+ ERR("fail to create gbm device");
+ close(fd);
+ return NULL;
+ }
+
+ g_display->gdevice_fd = fd;
+
+ return g_display->gdevice;
+}
+
+EINTERN Eina_List *
+e_display_outputs_get(void)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(g_display, NULL);
+
+ return g_display->outputs;
+}
+
+EINTERN int
+e_display_num_outputs_get(void)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(g_display, -1);
+
+ return g_display->num_outputs;
+}
+
+EINTERN Eina_Bool
+e_display_pp_support(void)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(g_display, EINA_TRUE);
+
+ return g_display->pp_enabled;
+}
+
+EINTERN Eina_Bool
+e_display_available_video_formats_get(const tbm_format **formats, int *count)
+{
+ E_Output *output;
+ tdm_output *toutput;
+ tdm_layer *layer;
+ tdm_error error;
+
+ *count = 0;
+
+ if (e_display_pp_support())
+ {
+ error = tdm_display_get_pp_available_formats(g_display->tdisplay, formats, count);
+ if (error == TDM_ERROR_NONE)
+ return EINA_TRUE;
+ }
+
+ /* get the first output */
+ toutput = tdm_display_get_output(g_display->tdisplay, 0, NULL);
+ if (!toutput)
+ return EINA_FALSE;
+
+ output = _e_display_eoutput_get_by_toutput(toutput);
+ if (!output)
+ return EINA_FALSE;
+
+ if (e_hwc_policy_get(output->hwc) != E_HWC_POLICY_WINDOWS)
+ {
+ /* get the first suitable layer */
+ layer = _e_display_video_tdm_layer_get(toutput);
+ if (layer)
+ {
+ tdm_layer_get_available_formats(layer, formats, count);
+ }
+ else
+ {
+ *formats = sw_formats;
+ *count = NUM_SW_FORMAT;
+ }
+ }
+ else
+ {
+ error = tdm_hwc_get_video_supported_formats(output->hwc->thwc, formats, count);
+ if (error != TDM_ERROR_NONE)
+ {
+ *formats = sw_formats;
+ *count = NUM_SW_FORMAT;
+ }
+ }
+
+ return EINA_TRUE;
+}
+
+
+EINTERN Eina_List *
+e_display_pp_available_formats_get(void)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(g_display, EINA_FALSE);
+
+ if (!g_display->pp_enabled)
+ {
+ ERR("pp does not support.");
+ return NULL;
+ }
+
+ return g_display->available_pp_formats;
+}
+
+EINTERN void
+e_display_pp_available_size_get(int *minw, int *minh, int *maxw, int *maxh, int *align)
+{
+ EINA_SAFETY_ON_NULL_RETURN(g_display);
+
+ tdm_display_get_pp_available_size(g_display->tdisplay,
+ minw, minh, maxw, maxh, align);
+}
+
+EINTERN void
+e_display_hwc_info_debug(void)
+{
+ EINA_SAFETY_ON_NULL_RETURN(g_display);
+
+ E_Display *display = g_display;
+ E_Output *output = NULL;
+ E_Plane *plane = NULL;
+ Eina_List *l_o, *ll_o;
+ Eina_List *l_l, *ll_l;
+ tdm_output_conn_status conn_status;
+ int output_idx = 0;
+ tdm_layer_capability layer_capabilities;
+ char layer_cap[4096] = {0, };
+ int i;
+ const tdm_prop *tprops;
+ int count;
+
+ INF("HWC: HWC Information ==========================================================");
+ EINA_LIST_FOREACH_SAFE(display->outputs, l_o, ll_o, output)
+ {
+ tdm_error err = TDM_ERROR_NONE;
+
+ if (!output) continue;
+
+ if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
+ {
+ err = tdm_output_get_conn_status(output->toutput, &conn_status);
+ if (err != TDM_ERROR_NONE) continue;
+ if (conn_status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) continue;
+
+ INF("HWC: HWC Output(%d):(x, y, w, h)=(%d, %d, %d, %d) Information.",
+ ++output_idx,
+ output->config.geom.x, output->config.geom.y, output->config.geom.w, output->config.geom.h);
+ INF("HWC: num_layers=%d", output->plane_count);
+ EINA_LIST_FOREACH_SAFE(output->planes, l_l, ll_l, plane)
+ {
+ if (!plane) continue;
+ /* FIXME: hwc extension doesn't provide thing like layer */
+ tdm_layer_get_capabilities(plane->tlayer, &layer_capabilities);
+ snprintf(layer_cap, sizeof(layer_cap), "%s%s%s%s%s%s%s%s",
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_CURSOR),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_PRIMARY),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_OVERLAY),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_GRAPHIC),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_VIDEO),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_TRANSFORM),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_RESEVED_MEMORY),
+ _layer_cap_to_str(layer_capabilities, TDM_LAYER_CAPABILITY_NO_CROP));
+ INF("HWC: index=%d zpos=%d ec=%p %s",
+ plane->index, plane->zpos,
+ plane->ec?plane->ec:NULL,
+ layer_cap);
+ }
+ }
+ else
+ {
+ /* TODO: construct debug info for outputs managed by the hwc-wins */
+ INF("HWC: HWC Output(%d) managed by hwc-wins.", ++output_idx);
+
+ if (!e_hwc_windows_get_available_properties(output->hwc, &tprops, &count))
+ {
+ ERR("e_hwc_windows_get_video_available_properties failed");
+ return;
+ }
+ INF(">>>>>>>> Available UI props : count = %d", count);
+ for (i = 0; i < count; i++)
+ INF(" [%d] %s, %u", i, tprops[i].name, tprops[i].id);
+
+ if (!e_hwc_windows_get_video_available_properties(output->hwc, &tprops, &count))
+ {
+ ERR("e_hwc_windows_get_video_available_properties failed");
+ return;
+ }
+ INF(">>>>>>>> Available VIDEO props : count = %d", count);
+ for (i = 0; i < count; i++)
+ INF(" [%d] %s, %u", i, tprops[i].name, tprops[i].id);
+ }
+ }
+ INF("HWC: =========================================================================");
+}
+
+EINTERN void
+e_display_debug_info_get(Eldbus_Message_Iter *iter)
+{
+ Eldbus_Message_Iter *line_array;
+ E_Output *output = NULL;
+ E_Hwc *hwc = NULL;
+ Eina_List *l;
+ char info_str[1024];
+
+ eldbus_message_iter_arguments_append(iter, "as", &line_array);
+
+ eldbus_message_iter_basic_append(line_array, 's',
+ "===========================================================================================");
+ eldbus_message_iter_basic_append(line_array, 's',
+ " idx id status dpms ( x , y ) ( w x h ) ");
+ eldbus_message_iter_basic_append(line_array, 's',
+ "===========================================================================================");
+
+
+#ifdef E_DISPLAY
+ EINA_LIST_FOREACH(e_display_outputs_get(), l, output)
+#else
+ E_Comp_Screen *e_comp_screen = NULL;
+ e_comp_screen = e_comp->e_comp_screen;
+ EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
+#endif
+ {
+ if (!output) continue;
+ hwc = output->hwc;
+ if (!output->hwc) continue;
+ if (e_hwc_policy_get(hwc) == E_HWC_POLICY_NONE) continue;
+
+ snprintf(info_str, sizeof(info_str), "%2d %12s %15s %10s (%5d , %5d) (%5d x %5d)",
+ output->index, output->id,
+ output->info.connected ? "connected" : "disconnected",
+ _e_display_dpms_to_string(output->dpms),
+ output->config.geom.x, output->config.geom.y,
+ output->config.geom.w, output->config.geom.h);
+
+ eldbus_message_iter_basic_append(line_array, 's', info_str);
+ }
+
+ eldbus_message_iter_basic_append(line_array, 's',
+ "===========================================================================================");
+
+ eldbus_message_iter_container_close(iter, line_array);
+}