diff --git a/src/lib/ecore_drm2/ecore_drm2_atomic.c b/src/lib/ecore_drm2/ecore_drm2_atomic.c new file mode 100644 index 0000000000..d931ab869c --- /dev/null +++ b/src/lib/ecore_drm2/ecore_drm2_atomic.c @@ -0,0 +1,442 @@ +#include "ecore_drm2_private.h" + +static Eina_Bool +_ecore_drm2_atomic_state_crtc_fill(Ecore_Drm2_Crtc_State *cstate, int fd) +{ + drmModeObjectPropertiesPtr oprops; + unsigned int i = 0; + + DBG("Atomic State Crtc Fill"); + + /* try to get crtc object properties */ + oprops = + sym_drmModeObjectGetProperties(fd, cstate->obj_id, DRM_MODE_OBJECT_CRTC); + if (!oprops) return EINA_FALSE; + + DBG("\tCrtc %d", cstate->obj_id); + + for (; i < oprops->count_props; i++) + { + drmModePropertyPtr prop; + + /* try to get this property */ + prop = sym_drmModeGetProperty(fd, oprops->props[i]); + if (!prop) continue; + + DBG("\t\tProperty: %s %d", prop->name, i); + + /* find the properties we are interested in and fill in crtc state */ + if (!strcmp(prop->name, "MODE_ID")) + { + drmModePropertyBlobPtr bp; + + cstate->mode.id = prop->prop_id; + cstate->mode.value = oprops->prop_values[i]; + + DBG("\t\t\tValue: %d", cstate->mode.value); + + if (!cstate->mode.value) + { + cstate->mode.len = 0; + goto cont; + } + + bp = sym_drmModeGetPropertyBlob(fd, cstate->mode.value); + if (!bp) goto cont; + + if ((!cstate->mode.data) || + memcmp(cstate->mode.data, bp->data, bp->length) != 0) + cstate->mode.data = eina_memdup(bp->data, bp->length, 1); + + cstate->mode.len = bp->length; + + if (cstate->mode.value != 0) + sym_drmModeCreatePropertyBlob(fd, bp->data, bp->length, + &cstate->mode.value); + + sym_drmModeFreePropertyBlob(bp); + } + else if (!strcmp(prop->name, "ACTIVE")) + { + cstate->active.id = prop->prop_id; + cstate->active.value = oprops->prop_values[i]; + DBG("\t\t\tValue: %lu", (long)cstate->active.value); + } + /* else if (!strcmp(prop->name, "BACKGROUND_COLOR")) */ + /* { */ + /* cstate->background.id = prop->prop_id; */ + /* cstate->background.value = oprops->prop_values[i]; */ + /* } */ + +cont: + sym_drmModeFreeProperty(prop); + } + + /* free crtc object properties */ + sym_drmModeFreeObjectProperties(oprops); + + return EINA_TRUE; +} + +static Eina_Bool +_ecore_drm2_atomic_state_connector_fill(Ecore_Drm2_Connector_State *cstate, int fd) +{ + drmModeObjectPropertiesPtr oprops; + unsigned int i = 0; + + DBG("Atomic State Connector Fill"); + + /* try to get connector object properties */ + oprops = + sym_drmModeObjectGetProperties(fd, cstate->obj_id, + DRM_MODE_OBJECT_CONNECTOR); + if (!oprops) return EINA_FALSE; + + DBG("\tConnector %d", cstate->obj_id); + + for (; i < oprops->count_props; i++) + { + drmModePropertyPtr prop; + + /* try to get this property */ + prop = sym_drmModeGetProperty(fd, oprops->props[i]); + if (!prop) continue; + + DBG("\t\tProperty: %s %d", prop->name, i); + + /* find the properties we are interested in and fill in conn state */ + + if (!strcmp(prop->name, "CRTC_ID")) + { + cstate->crtc.id = prop->prop_id; + cstate->crtc.value = oprops->prop_values[i]; + DBG("\t\t\tValue: %lu", (long)cstate->crtc.value); + } + else if (!strcmp(prop->name, "DPMS")) + { + cstate->dpms.id = prop->prop_id; + cstate->dpms.value = oprops->prop_values[i]; + DBG("\t\t\tValue: %lu", (long)cstate->dpms.value); + } + else if (!strcmp(prop->name, "aspect ratio")) + { + cstate->aspect.id = prop->prop_id; + cstate->aspect.value = oprops->prop_values[i]; + DBG("\t\t\tValue: %lu", (long)cstate->aspect.value); + } + else if (!strcmp(prop->name, "scaling mode")) + { + cstate->scaling.id = prop->prop_id; + cstate->scaling.value = oprops->prop_values[i]; + DBG("\t\t\tValue: %lu", (long)cstate->scaling.value); + } + else if (!strcmp(prop->name, "EDID")) + { + drmModePropertyBlobPtr bp; + + cstate->edid.id = oprops->prop_values[i]; + if (!cstate->edid.id) + { + cstate->edid.len = 0; + goto cont; + } + + bp = sym_drmModeGetPropertyBlob(fd, cstate->edid.id); + if (!bp) goto cont; + + if ((!cstate->edid.data) || + memcmp(cstate->edid.data, bp->data, bp->length) != 0) + { + cstate->edid.data = + eina_memdup(bp->data, bp->length, 1); + } + + cstate->edid.len = bp->length; + + if (cstate->edid.id != 0) + sym_drmModeCreatePropertyBlob(fd, bp->data, bp->length, + &cstate->edid.id); + + sym_drmModeFreePropertyBlob(bp); + } +cont: + sym_drmModeFreeProperty(prop); + } + + /* free crtc object properties */ + sym_drmModeFreeObjectProperties(oprops); + + return EINA_TRUE; +} + +static Eina_Bool +_ecore_drm2_atomic_state_plane_fill(Ecore_Drm2_Plane_State *pstate, int fd) +{ + drmModeObjectPropertiesPtr oprops; + unsigned int i = 0; + + DBG("Atomic State Plane Fill"); + + /* try to get plane object properties */ + oprops = + sym_drmModeObjectGetProperties(fd, pstate->obj_id, DRM_MODE_OBJECT_PLANE); + if (!oprops) return EINA_FALSE; + + DBG("\tPlane %d", pstate->obj_id); + + for (; i < oprops->count_props; i++) + { + drmModePropertyPtr prop; + + /* try to get this property */ + prop = sym_drmModeGetProperty(fd, oprops->props[i]); + if (!prop) continue; + + DBG("\t\tProperty: %s %d", prop->name, i); + + /* find the properties we are interested in and fill in plane state */ + if (!strcmp(prop->name, "CRTC_ID")) + { + pstate->cid.id = prop->prop_id; + pstate->cid.value = oprops->prop_values[i]; + DBG("\t\t\tValue: %lu", (long)pstate->cid.value); + } + else if (!strcmp(prop->name, "FB_ID")) + { + pstate->fid.id = prop->prop_id; + pstate->fid.value = oprops->prop_values[i]; + DBG("\t\t\tValue: %lu", (long)pstate->fid.value); + } + else if (!strcmp(prop->name, "CRTC_X")) + { + pstate->cx.id = prop->prop_id; + pstate->cx.value = oprops->prop_values[i]; + } + else if (!strcmp(prop->name, "CRTC_Y")) + { + pstate->cy.id = prop->prop_id; + pstate->cy.value = oprops->prop_values[i]; + } + else if (!strcmp(prop->name, "CRTC_W")) + { + pstate->cw.id = prop->prop_id; + pstate->cw.value = oprops->prop_values[i]; + } + else if (!strcmp(prop->name, "CRTC_H")) + { + pstate->ch.id = prop->prop_id; + pstate->ch.value = oprops->prop_values[i]; + } + else if (!strcmp(prop->name, "SRC_X")) + { + pstate->sx.id = prop->prop_id; + pstate->sx.value = oprops->prop_values[i]; + } + else if (!strcmp(prop->name, "SRC_Y")) + { + pstate->sy.id = prop->prop_id; + pstate->sy.value = oprops->prop_values[i]; + } + else if (!strcmp(prop->name, "SRC_W")) + { + pstate->sw.id = prop->prop_id; + pstate->sw.value = oprops->prop_values[i]; + } + else if (!strcmp(prop->name, "SRC_H")) + { + pstate->sh.id = prop->prop_id; + pstate->sh.value = oprops->prop_values[i]; + } + else if (!strcmp(prop->name, "type")) + { + pstate->type.id = prop->prop_id; + pstate->type.value = oprops->prop_values[i]; + switch (pstate->type.value) + { + case DRM_PLANE_TYPE_OVERLAY: + DBG("\t\t\tOverlay Plane"); + break; + case DRM_PLANE_TYPE_PRIMARY: + DBG("\t\t\tPrimary Plane"); + break; + case DRM_PLANE_TYPE_CURSOR: + DBG("\t\t\tCursor Plane"); + break; + default: + DBG("\t\t\tValue: %lu", (long)pstate->type.value); + break; + } + } + else if (!strcmp(prop->name, "rotation")) + { + int k = 0; + + pstate->rotation.id = prop->prop_id; + pstate->rotation.value = oprops->prop_values[i]; + + for (k = 0; k < prop->count_enums; k++) + { + int r = -1; + + DBG("\t\t\tRotation: %s", prop->enums[k].name); + if (!strcmp(prop->enums[k].name, "rotate-0")) + r = ECORE_DRM2_ROTATION_NORMAL; + else if (!strcmp(prop->enums[k].name, "rotate-90")) + r = ECORE_DRM2_ROTATION_90; + else if (!strcmp(prop->enums[k].name, "rotate-180")) + r = ECORE_DRM2_ROTATION_180; + else if (!strcmp(prop->enums[k].name, "rotate-270")) + r = ECORE_DRM2_ROTATION_270; + else if (!strcmp(prop->enums[k].name, "reflect-x")) + r = ECORE_DRM2_ROTATION_REFLECT_X; + else if (!strcmp(prop->enums[k].name, "reflect-y")) + r = ECORE_DRM2_ROTATION_REFLECT_Y; + + if (r != -1) + { + pstate->supported_rotations |= r; + pstate->rotation_map[ffs(r)] = + 1ULL << prop->enums[k].value; + } + } + } + + sym_drmModeFreeProperty(prop); + } + + /* free plane object properties */ + sym_drmModeFreeObjectProperties(oprops); + + return EINA_TRUE; +} + +Eina_Bool +_ecore_drm2_atomic_state_fill(Ecore_Drm2_Atomic_State *state, int fd) +{ + int i = 0; + drmModeResPtr res; + drmModePlaneResPtr pres; + + /* try to get drm resources */ + res = sym_drmModeGetResources(fd); + if (!res) return EINA_FALSE; + + state->crtcs = res->count_crtcs; + + /* try to allocate space for crtc states */ + state->crtc_states = calloc(state->crtcs, sizeof(Ecore_Drm2_Crtc_State)); + if (!state->crtc_states) + { + ERR("Could not allocate space for CRTC states"); + goto crtc_err; + } + + /* try to fill atomic state for each crtc */ + for (i = 0; i < state->crtcs; i++) + { + Ecore_Drm2_Crtc_State *cstate; + + cstate = &state->crtc_states[i]; + cstate->obj_id = res->crtcs[i]; + cstate->index = i; + + /* try fill atomic state for this crtc */ + if (!_ecore_drm2_atomic_state_crtc_fill(cstate, fd)) + { + WRN("Failed to fill atomic crtc state for CRTC %d", + cstate->obj_id); + continue; + } + } + + /* try to allocate space for connector states */ + state->conns = res->count_connectors; + state->conn_states = calloc(state->conns, sizeof(Ecore_Drm2_Connector_State)); + if (!state->conn_states) + { + ERR("Could not allocate space for CONN states"); + goto conn_err; + } + + /* try to fill atomic state for each connector */ + for (i = 0; i < state->conns; i++) + { + Ecore_Drm2_Connector_State *cstate; + + cstate = &state->conn_states[i]; + cstate->obj_id = res->connectors[i]; + + /* try to fill atomic state for this connector */ + if (!_ecore_drm2_atomic_state_connector_fill(cstate, fd)) + { + WRN("Failed to fill atomic connector state for CONN %d", + cstate->obj_id); + continue; + } + } + + /* try to get plane resources */ + pres = sym_drmModeGetPlaneResources(fd); + if (!pres) goto plane_res_err; + + /* try to allocate space for plane states */ + state->planes = pres->count_planes; + state->plane_states = calloc(state->planes, sizeof(Ecore_Drm2_Plane_State)); + if (!state->plane_states) + { + ERR("Could not allocate space for PLANE states"); + goto plane_err; + } + + /* try to fill atomic state for each plane */ + for (i = 0; i < state->planes; i++) + { + unsigned int f = 0; + drmModePlanePtr plane; + Ecore_Drm2_Plane_State *pstate; + + /* try to get this plane */ + plane = sym_drmModeGetPlane(fd, pres->planes[i]); + if (!plane) continue; + + pstate = &state->plane_states[i]; + + pstate->obj_id = pres->planes[i]; + pstate->mask = plane->possible_crtcs; + + /* try to get the formats supported on this plane */ + pstate->num_formats = plane->count_formats; + pstate->formats = calloc(plane->count_formats, sizeof(uint32_t)); + for (; f < plane->count_formats; f++) + pstate->formats[f] = plane->formats[f]; + + /* free drm plane */ + sym_drmModeFreePlane(plane); + + /* try to fill atomic state for this plane */ + if (!_ecore_drm2_atomic_state_plane_fill(pstate, fd)) + { + WRN("Failed to fill atomic plane state for PLANE %d", + pstate->obj_id); + continue; + } + } + + /* free drm plane resources */ + sym_drmModeFreePlaneResources(pres); + + /* free drm resources */ + sym_drmModeFreeResources(res); + + return EINA_TRUE; + +plane_err: + sym_drmModeFreePlaneResources(pres); +plane_res_err: + free(state->conn_states); +conn_err: + free(state->crtc_states); +crtc_err: + sym_drmModeFreeResources(res); + return EINA_FALSE; +} diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index b4e6edbfcd..279bb68b23 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -115,7 +115,7 @@ ecore_drm2_device_open(const char *seat, unsigned int tty) const char *path; Ecore_Drm2_Device *dev; - /* try to allocate space for return structure */ + /* try to allocate space for device structure */ dev = calloc(1, sizeof(Ecore_Drm2_Device)); if (!dev) return NULL; @@ -143,6 +143,8 @@ ecore_drm2_device_open(const char *seat, unsigned int tty) goto open_err; } + DBG("Opened DRM Device: %s", path); + /* try to enable elput input */ if (!elput_input_init(dev->em)) { @@ -150,7 +152,7 @@ ecore_drm2_device_open(const char *seat, unsigned int tty) goto input_err; } - /* NB: For now, we will ONLY support Atomic */ + /* test if this device can do Atomic Modesetting */ _ecore_drm2_atomic_use = _ecore_drm2_device_atomic_capable_get(dev->fd); if (!_ecore_drm2_atomic_use) { @@ -158,17 +160,30 @@ ecore_drm2_device_open(const char *seat, unsigned int tty) goto atomic_err; } - /* TODO: Fill atomic state */ + /* try to allocate space for Atomic State */ + dev->atomic_state = calloc(1, sizeof(Ecore_Drm2_Atomic_State)); + if (!dev->atomic_state) + { + ERR("Failed to allocate device atomic state"); + goto atomic_err; + } + + /* try to fill atomic state */ + if (!_ecore_drm2_atomic_state_fill(dev->atomic_state, dev->fd)) + { + ERR("Failed to fill Atomic State"); + goto atomic_fill_err; + } /* TODO: event handlers for session_active & device_change */ - DBG("Opened DRM Device: %s", path); - /* cleanup path variable */ eina_stringshare_del(path); return dev; +atomic_fill_err: + free(dev->atomic_state); atomic_err: elput_input_shutdown(dev->em); input_err: diff --git a/src/lib/ecore_drm2/meson.build b/src/lib/ecore_drm2/meson.build index 7ebe1cda76..dc672dc4ba 100644 --- a/src/lib/ecore_drm2/meson.build +++ b/src/lib/ecore_drm2/meson.build @@ -7,6 +7,7 @@ ecore_drm2_header_src = [ ] ecore_drm2_src = files([ + 'ecore_drm2_atomic.c', 'ecore_drm2_device.c', 'ecore_drm2.c', 'ecore_drm2_private.h'