diff --git a/src/modules/wl_drm/e_mod_main.c b/src/modules/wl_drm/e_mod_main.c index 809633171..67bbe99b2 100644 --- a/src/modules/wl_drm/e_mod_main.c +++ b/src/modules/wl_drm/e_mod_main.c @@ -8,6 +8,56 @@ static Ecore_Event_Handler *activate_handler; static Ecore_Event_Handler *output_handler; static Eina_Bool session_state = EINA_FALSE; +#if EFL_VERSION_MINOR == 14 +/* keeping this here temporarily to make the check for backlight device + * 1 line instead of 50-100 + */ +struct _Ecore_Drm_Output +{ + Ecore_Drm_Device *dev; + unsigned int crtc_id; + unsigned int conn_id; + drmModeCrtcPtr crtc; + drmModePropertyPtr dpms; + + int x, y, phys_width, phys_height; + + int pipe; + const char *make, *model, *name; + unsigned int subpixel; + uint16_t gamma; + + Ecore_Drm_Output_Mode *current_mode; + Eina_List *modes; + + struct + { + char eisa[13]; + char monitor[13]; + char pnp[5]; + char serial[13]; + } edid; + + void *backlight; + + Eina_Bool enabled : 1; + Eina_Bool cloned : 1; + Eina_Bool need_repaint : 1; + Eina_Bool repaint_scheduled : 1; + Eina_Bool pending_destroy : 1; + Eina_Bool pending_flip : 1; + Eina_Bool pending_vblank : 1; +}; + +struct _Ecore_Drm_Output_Mode +{ + unsigned int flags; + int width, height; + unsigned int refresh; + drmModeModeInfo info; +}; +#endif + static Eina_Bool _e_mod_drm_cb_activate(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) { @@ -76,6 +126,8 @@ _e_mod_drm_cb_output(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) } end: + if (!e_randr2_cfg->ignore_hotplug_events) + e_randr2_screen_refresh_queue(EINA_TRUE); return ECORE_CALLBACK_PASS_ON; } @@ -85,6 +137,171 @@ _e_mod_drm_cb_ee_resize(Ecore_Evas *ee EINA_UNUSED) e_comp_canvas_update(); } +static E_Randr2_Mode * +_mode_get(drmModeModeInfo *info) +{ + E_Randr2_Mode *mode; + uint64_t refresh; + + mode = malloc(sizeof(E_Randr2_Mode)); + + mode->w = info->hdisplay; + mode->h = info->vdisplay; + + refresh = (info->clock * 1000000LL / info->htotal + info->vtotal / 2) / info->vtotal; + if (info->flags & DRM_MODE_FLAG_INTERLACE) + refresh *= 2; + if (info->flags & DRM_MODE_FLAG_DBLSCAN) + refresh /= 2; + if (info->vscan > 1) + refresh /= info->vscan; + + mode->refresh = refresh; + mode->preferred = (info->type & DRM_MODE_TYPE_PREFERRED); + + return mode; +} + +static char * +_get_edid(Ecore_Drm_Device *dev, drmModeConnector *conn) +{ + int i; + drmModePropertyBlobPtr blob = NULL; + drmModePropertyPtr prop; + char *ret; + + for (i = 0; i < conn->count_props; i++) + { + if (!(prop = drmModeGetProperty(dev->drm.fd, conn->props[i]))) + continue; + if ((prop->flags & DRM_MODE_PROP_BLOB) && + (!strcmp(prop->name, "EDID"))) + { + blob = drmModeGetPropertyBlob(dev->drm.fd, + conn->prop_values[i]); + drmModeFreeProperty(prop); + break; + } + drmModeFreeProperty(prop); + } + ret = (char*)eina_memdup(blob->data, blob->length, 1); + drmModeFreePropertyBlob(blob); + return ret; +} + +static E_Randr2 * +_drm_randr_create(void) +{ + Ecore_Drm_Device *dev; + const Eina_List *l; + E_Randr2 *r; + + r = E_NEW(E_Randr2, 1); + EINA_LIST_FOREACH(ecore_drm_devices_get(), l, dev) + { + Ecore_Drm_Output *output; + const Eina_List *ll; + + EINA_LIST_FOREACH(dev->outputs, ll, output) + { + E_Randr2_Screen *s; + size_t n, e; + int i; + drmModeConnector *conn; + const char *conn_types[] = + { + "None", "VGA", "DVI-I", "DVI-D", "DVI-A", + "Composite", "S-Video", "LVDS", "Component", "DIN", + "DisplayPort", "HDMI-A", "HDMI-B", "TV", "eDP", "Virtual", + "DSI", "UNKNOWN" + }; + E_Randr2_Connector rtype[] = + { + E_RANDR2_CONNECTOR_UNDEFINED, + E_RANDR2_CONNECTOR_UNDEFINED, + E_RANDR2_CONNECTOR_DVI, + E_RANDR2_CONNECTOR_DVI, + E_RANDR2_CONNECTOR_DVI, + E_RANDR2_CONNECTOR_UNDEFINED, + E_RANDR2_CONNECTOR_UNDEFINED, + E_RANDR2_CONNECTOR_UNDEFINED, + E_RANDR2_CONNECTOR_UNDEFINED, + E_RANDR2_CONNECTOR_UNDEFINED, + E_RANDR2_CONNECTOR_DISPLAY_PORT, + E_RANDR2_CONNECTOR_HDMI_A, + E_RANDR2_CONNECTOR_HDMI_B, + E_RANDR2_CONNECTOR_UNDEFINED, + E_RANDR2_CONNECTOR_DISPLAY_PORT, + E_RANDR2_CONNECTOR_UNDEFINED, + E_RANDR2_CONNECTOR_UNDEFINED, + E_RANDR2_CONNECTOR_UNDEFINED, + }; + char buf[4096]; + unsigned int type; + + /* FIXME: it's insane to have this code here instead of in ecore-drm. */ + conn = drmModeGetConnector(dev->drm.fd, ecore_drm_output_connector_id_get(output)); + if (!conn) continue; + s = E_NEW(E_Randr2_Screen, 1); + type = MIN(conn->connector_type, EINA_C_ARRAY_LENGTH(conn_types) - 1); + + snprintf(buf, sizeof(buf), "%s-%d", conn_types[type], conn->connector_type_id); + s->info.name = strdup(buf); + s->info.edid = _get_edid(dev, conn); + n = strlen(s->info.name); + e = strlen(s->info.edid); + s->id = malloc(n + e + 2); + eina_str_join_len(s->id, n + e + 2, '/', s->info.name, n, s->info.edid, e); + s->id[n + e + 1] = 0; + s->info.connector = rtype[type]; + s->info.connected = 1; + s->info.is_lid = type == DRM_MODE_CONNECTOR_LVDS; +#if EFL_VERSION_MINOR == 14 + s->info.backlight = !!output->backlight; +#endif + for (i = 0; i < conn->count_modes; i++) + { + E_Randr2_Mode *mode; + + mode = _mode_get(conn->modes + i); + if (mode) + s->info.modes = eina_list_append(s->info.modes, mode); + } + ecore_drm_output_physical_size_get(output, &s->info.size.w, &s->info.size.h); + + r->screens = eina_list_append(r->screens, s); + + drmModeFreeConnector(conn); + } + } + return r; +} + +static Eina_Bool +_drm_randr_available(void) +{ + return EINA_TRUE; +} + +static void +_drm_randr_stub(void) +{} + +static void +_drm_randr_apply(void) +{ + /* TODO: what the actual fuck */ +} + +static E_Comp_Screen_Iface drmiface = +{ + .available = _drm_randr_available, + .init = _drm_randr_stub, + .shutdown = _drm_randr_stub, + .create = _drm_randr_create, + .apply = _drm_randr_apply +}; + EAPI void * e_modapi_init(E_Module *m) { @@ -130,18 +347,7 @@ e_modapi_init(E_Module *m) ecore_evas_callback_resize_set(e_comp->ee, _e_mod_drm_cb_ee_resize); - if (!e_xinerama_fake_screens_exist()) - { - E_Screen *screen; - - screen = E_NEW(E_Screen, 1); - screen->escreen = screen->screen = 0; - screen->x = 0; - screen->y = 0; - screen->w = w; - screen->h = h; - e_xinerama_screens_set(eina_list_append(NULL, screen)); - } + e_comp->screen = &drmiface; if (!e_comp_wl_init()) return NULL; if (!e_comp_canvas_init(w, h)) return NULL;