From 345fefd3ef841381a6a0206297a24df88afd311a Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Mon, 27 Mar 2017 13:56:03 -0400 Subject: [PATCH] ecore-drm2: Add API functions for atomic commit test and commit This patch adds 2 new API functions, one which we can use to test atomic commits before actually applying them, and another which does the actual Atomic commit. @feature Signed-off-by: Chris Michael --- src/lib/ecore_drm2/Ecore_Drm2.h | 6 + src/lib/ecore_drm2/ecore_drm2_device.c | 158 ++++++++++++++++++++++++- 2 files changed, 163 insertions(+), 1 deletion(-) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 6f1296d204..106c50757d 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -370,6 +370,12 @@ EAPI Eina_Bool ecore_drm2_device_vt_set(Ecore_Drm2_Device *device, int vt); */ EAPI Eina_Bool ecore_drm2_device_prefer_shadow(Ecore_Drm2_Device *device); +/* TODO: doxy */ +EAPI Eina_Bool ecore_drm2_atomic_commit_test(Ecore_Drm2_Device *device); + +/* TODO: doxy */ +EAPI Eina_Bool ecore_drm2_atomic_commit(Ecore_Drm2_Device *device); + /** * @defgroup Ecore_Drm2_Output_Group Drm output functions * diff --git a/src/lib/ecore_drm2/ecore_drm2_device.c b/src/lib/ecore_drm2/ecore_drm2_device.c index fcd639eb7e..cb659ad4a5 100644 --- a/src/lib/ecore_drm2/ecore_drm2_device.c +++ b/src/lib/ecore_drm2/ecore_drm2_device.c @@ -676,7 +676,11 @@ ecore_drm2_device_free(Ecore_Drm2_Device *device) #ifdef HAVE_ATOMIC_DRM if (_ecore_drm2_use_atomic) - _drm2_atomic_state_free(device->state); + { + _drm2_atomic_state_free(device->state); + if (device->atomic_req) + sym_drmModeAtomicFree(device->atomic_req); + } #endif ecore_event_handler_del(device->active_hdlr); @@ -848,3 +852,155 @@ ecore_drm2_device_prefer_shadow(Ecore_Drm2_Device *device) else return EINA_FALSE; } + +EAPI Eina_Bool +ecore_drm2_atomic_commit_test(Ecore_Drm2_Device *device) +{ + Eina_Bool res = EINA_FALSE; +#ifdef HAVE_ATOMIC_DRM + int ret = 0; + Eina_List *l, *ll; + Ecore_Drm2_Output *output; + Ecore_Drm2_Plane *plane; + Ecore_Drm2_Plane_State *pstate; + Ecore_Drm2_Crtc_State *cstate; + drmModeAtomicReq *req = NULL; + uint32_t flags = DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_ATOMIC_ALLOW_MODESET | + DRM_MODE_ATOMIC_TEST_ONLY; +#endif + + EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL((device->fd < 0), EINA_FALSE); + +#ifdef HAVE_ATOMIC_DRM + req = sym_drmModeAtomicAlloc(); + if (!req) return EINA_FALSE; + + sym_drmModeAtomicSetCursor(req, 0); + + EINA_LIST_FOREACH(device->outputs, l, output) + { + cstate = output->crtc_state; + + ret = + sym_drmModeAtomicAddProperty(req, cstate->obj_id, cstate->mode.id, + cstate->mode.value); + if (ret < 0) goto err; + + ret = + sym_drmModeAtomicAddProperty(req, cstate->obj_id, cstate->active.id, + cstate->active.value); + if (ret < 0) goto err; + + EINA_LIST_FOREACH(output->planes, ll, plane) + { + pstate = plane->state; + + ret = + sym_drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->cid.id, pstate->cid.value); + if (ret < 0) goto err; + + ret = + sym_drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->fid.id, pstate->fid.value); + if (ret < 0) goto err; + + ret = + sym_drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->sx.id, pstate->sx.value); + if (ret < 0) goto err; + + ret = + sym_drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->sy.id, pstate->sy.value); + if (ret < 0) goto err; + + ret = + sym_drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->sw.id, pstate->sw.value); + if (ret < 0) goto err; + + ret = + sym_drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->sh.id, pstate->sh.value); + if (ret < 0) goto err; + + ret = + sym_drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->cx.id, pstate->cx.value); + if (ret < 0) goto err; + + ret = + sym_drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->cy.id, pstate->cy.value); + if (ret < 0) goto err; + + ret = + sym_drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->cw.id, pstate->cw.value); + if (ret < 0) goto err; + + ret = + sym_drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->ch.id, pstate->ch.value); + if (ret < 0) goto err; + } + } + + ret = + sym_drmModeAtomicCommit(device->fd, req, flags, NULL); + if (ret < 0) ERR("Failed Atomic Commit Test: %m"); + else res = EINA_TRUE; + + if (res) + { + if (device->atomic_req) + { + /* merge this test commit with previous */ + ret = sym_drmModeAtomicMerge(device->atomic_req, req); + if (ret < 0) + { + /* we failed to merge for some reason. just use this req */ + device->atomic_req = req; + } + } + else + device->atomic_req = req; + } + + return res; + +err: + sym_drmModeAtomicFree(req); +#endif + + return res; +} + +EAPI Eina_Bool +ecore_drm2_atomic_commit(Ecore_Drm2_Device *device) +{ +#ifdef HAVE_ATOMIC_DRM + int res = 0; + uint32_t flags = + DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT | + DRM_MODE_ATOMIC_ALLOW_MODESET; +#endif + + EINA_SAFETY_ON_NULL_RETURN_VAL(device, EINA_FALSE); + EINA_SAFETY_ON_TRUE_RETURN_VAL((device->fd < 0), EINA_FALSE); + +#ifdef HAVE_ATOMIC_DRM + if (!device->atomic_req) return EINA_FALSE; + + res = + sym_drmModeAtomicCommit(device->fd, device->atomic_req, flags, NULL); + if (res < 0) + ERR("Failed Atomic Commit Test: %m"); + else + return EINA_TRUE; +#endif + + return EINA_FALSE; +}