From 3c243c3ebb95d229c3eaa48fb7bc42f60b1388e8 Mon Sep 17 00:00:00 2001 From: Chris Michael Date: Thu, 22 Sep 2016 13:30:49 -0400 Subject: [PATCH] ecore-drm2: Add support for Atomic Pageflips This patch modifies our ecore_drm2_fb_flip code to use Atomic/Nuclear pageflips. NB: Works perfectly under software drm engine .. some flickering with the gl_drm engine that needs investigating. Signed-off-by: Chris Michael --- src/lib/ecore_drm2/ecore_drm2_fb.c | 204 +++++++++++++++++++++++++++++++------ 1 file changed, 173 insertions(+), 31 deletions(-) diff --git a/src/lib/ecore_drm2/ecore_drm2_fb.c b/src/lib/ecore_drm2/ecore_drm2_fb.c index fc40a8e..94c6fa3 100644 --- a/src/lib/ecore_drm2/ecore_drm2_fb.c +++ b/src/lib/ecore_drm2/ecore_drm2_fb.c @@ -31,6 +31,83 @@ _fb2_create(Ecore_Drm2_Fb *fb) return EINA_TRUE; } +#ifdef HAVE_ATOMIC_DRM +static int +_fb_atomic_flip(Ecore_Drm2_Output *output, Ecore_Drm2_Plane_State *pstate, uint32_t flags) +{ + int ret = 0; + drmModeAtomicReq *req = NULL; + + req = drmModeAtomicAlloc(); + if (!req) return -1; + + drmModeAtomicSetCursor(req, 0); + + if (flags & DRM_MODE_ATOMIC_ALLOW_MODESET) + { + Ecore_Drm2_Crtc_State *cstate; + + cstate = output->crtc_state; + + ret = drmModeAtomicAddProperty(req, cstate->obj_id, cstate->mode.id, + cstate->mode.value); + if (ret < 0) goto err; + + ret = drmModeAtomicAddProperty(req, cstate->obj_id, cstate->active.id, + cstate->active.value); + if (ret < 0) goto err; + } + + ret = drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->cid.id, pstate->cid.value); + if (ret < 0) goto err; + + ret = drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->fid.id, pstate->fid.value); + if (ret < 0) goto err; + + ret = drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->sx.id, pstate->sx.value); + if (ret < 0) goto err; + + ret = drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->sy.id, pstate->sy.value); + if (ret < 0) goto err; + + ret = drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->sw.id, pstate->sw.value); + if (ret < 0) goto err; + + ret = drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->sh.id, pstate->sh.value); + if (ret < 0) goto err; + + ret = drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->cx.id, pstate->cx.value); + if (ret < 0) goto err; + + ret = drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->cy.id, pstate->cy.value); + if (ret < 0) goto err; + + ret = drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->cw.id, pstate->cw.value); + if (ret < 0) goto err; + + ret = drmModeAtomicAddProperty(req, pstate->obj_id, + pstate->ch.id, pstate->ch.value); + if (ret < 0) goto err; + + ret = drmModeAtomicCommit(output->fd, req, flags, output->user_data); + if (ret < 0) ERR("Failed to commit Atomic FB Flip: %m"); + else ret = 0; + +err: + drmModeAtomicFree(req); + return ret; +} +#endif + EAPI Ecore_Drm2_Fb * ecore_drm2_fb_create(int fd, int width, int height, int depth, int bpp, unsigned int format) { @@ -275,48 +352,113 @@ ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output) /* If we don't have an fb to set by now, BAIL! */ if (!fb) return -1; - if ((!output->current) || - (output->current->stride != fb->stride)) +#ifdef HAVE_ATOMIC_DRM + if (_ecore_drm2_use_atomic) { - ret = - drmModeSetCrtc(fb->fd, output->crtc_id, fb->id, - output->x, output->y, &output->conn_id, 1, - &output->current_mode->info); - if (ret) + Ecore_Drm2_Plane_State *pstate; + uint32_t flags = + DRM_MODE_ATOMIC_NONBLOCK | DRM_MODE_PAGE_FLIP_EVENT; + + pstate = output->plane_state; + + pstate->cid.value = output->crtc_id; + pstate->fid.value = fb->id; + + pstate->sx.value = 0; + pstate->sy.value = 0; + pstate->sw.value = fb->w << 16; + pstate->sh.value = fb->h << 16; + pstate->cx.value = output->x; + pstate->cy.value = output->y; + pstate->cw.value = output->current_mode->width; + pstate->ch.value = output->current_mode->height; + + if ((!output->current) || + (output->current->stride != fb->stride)) + { + flags |= DRM_MODE_ATOMIC_ALLOW_MODESET; + + ret = _fb_atomic_flip(output, pstate, flags); + if (ret < 0) + { + ERR("\tCrtc: %d FB: %d", output->crtc_id, fb->id); + return ret; + } + + if (output->current) _release_buffer(output, output->current); + output->current = fb; + output->current->busy = EINA_TRUE; + output->next = NULL; + + return 0; + } + + ret = _fb_atomic_flip(output, pstate, flags); + if ((ret < 0) && (errno != EBUSY)) { - ERR("Failed to set Mode %dx%d for Output %s: %m", - output->current_mode->width, output->current_mode->height, - output->name); + ERR("Atomic Pageflip Failed for Crtc %u on Connector %u: %m", + output->crtc_id, output->conn_id); return ret; } + else if (ret < 0) + { + output->next = fb; + if (output->next) output->next->busy = EINA_TRUE; - if (output->current) _release_buffer(output, output->current); - output->current = fb; - output->current->busy = EINA_TRUE; - output->next = NULL; + return 0; + } - return 0; - } + output->pending = fb; + output->pending->busy = EINA_TRUE; - ret = - drmModePageFlip(fb->fd, output->crtc_id, fb->id, - DRM_MODE_PAGE_FLIP_EVENT, output->user_data); - if ((ret < 0) && (errno != EBUSY)) - { - DBG("Pageflip Failed for Crtc %u on Connector %u: %m", - output->crtc_id, output->conn_id); - return ret; + return 0; } - else if (ret < 0) + else +#endif { - output->next = fb; - output->next->busy = EINA_TRUE; + if ((!output->current) || + (output->current->stride != fb->stride)) + { + ret = + drmModeSetCrtc(fb->fd, output->crtc_id, fb->id, + output->x, output->y, &output->conn_id, 1, + &output->current_mode->info); + if (ret) + { + ERR("Failed to set Mode %dx%d for Output %s: %m", + output->current_mode->width, output->current_mode->height, + output->name); + return ret; + } + + if (output->current) _release_buffer(output, output->current); + output->current = fb; + output->current->busy = EINA_TRUE; + output->next = NULL; + + return 0; + } + + ret = + drmModePageFlip(fb->fd, output->crtc_id, fb->id, + DRM_MODE_PAGE_FLIP_EVENT, output->user_data); + if ((ret < 0) && (errno != EBUSY)) + { + DBG("Pageflip Failed for Crtc %u on Connector %u: %m", + output->crtc_id, output->conn_id); + return ret; + } + else if (ret < 0) + { + output->next = fb; + output->next->busy = EINA_TRUE; + return 0; + } + + output->pending = fb; + output->pending->busy = EINA_TRUE; return 0; } - - output->pending = fb; - output->pending->busy = EINA_TRUE; - return 0; } EAPI Eina_Bool -- 2.7.4