evas-drm: Add vsync/non-vsync support to evas_drm code

@feature: Add ability to render software buffers using vsync or not
@bugfix: Fix drmModeAddFB to use proper depth & bpp when adding FB
@bugfix: Fix mmap to use NULL (not 0) so that kernel assigns memory
address.

Signed-off-by: Chris Michael <cp.michael@samsung.com>
This commit is contained in:
Chris Michael 2014-02-28 12:36:11 +00:00
parent 09b69d567e
commit 7ca6837084
1 changed files with 69 additions and 48 deletions

View File

@ -190,6 +190,18 @@ _evas_drm_crtc_find(int fd, drmModeRes *res, drmModeConnector *conn)
return crtc;
}
static unsigned int
_evas_drm_crtc_buffer_get(int fd, int crtc_id)
{
drmModeCrtc *crtc;
unsigned int id;
if (!(crtc = drmModeGetCrtc(fd, crtc_id))) return 0;
id = crtc->buffer_id;
drmModeFreeCrtc(crtc);
return id;
}
static void
_evas_drm_tty_sigusr1(int x EINA_UNUSED, siginfo_t *info, void *data EINA_UNUSED)
{
@ -525,6 +537,9 @@ evas_drm_outbuf_setup(Outbuf *ob)
/* record the crtc id */
ob->priv.crtc = crtc;
/* record the current framebuffer */
ob->priv.fb = _evas_drm_crtc_buffer_get(ob->priv.fd, crtc);
/* spew out connector properties for testing */
/* drmModePropertyPtr props; */
/* for (m = 0; m < conn->count_props; m++) */
@ -536,14 +551,12 @@ evas_drm_outbuf_setup(Outbuf *ob)
/* record the current mode */
memcpy(&ob->priv.mode, &conn->modes[0], sizeof(ob->priv.mode));
DBG("Output Current Mode: %d: %d %d", ob->priv.conn,
conn->modes[0].hdisplay, conn->modes[0].vdisplay);
for (m = 0; m < conn->count_modes; m++)
{
/* DBG("Output Available Mode: %d: %d %d %d", ob->priv.conn, */
/* conn->modes[m].hdisplay, conn->modes[m].vdisplay, */
/* conn->modes[m].vrefresh); */
DBG("Output Available Mode: %d: %d %d %d", ob->priv.conn,
conn->modes[m].hdisplay, conn->modes[m].vdisplay,
conn->modes[m].vrefresh);
/* try to find a mode which matches the requested size */
if ((conn->modes[m].hdisplay == ob->w) &&
@ -555,6 +568,17 @@ evas_drm_outbuf_setup(Outbuf *ob)
}
}
DBG("Output Current Mode: %d: %d %d", ob->priv.conn,
ob->priv.mode.hdisplay, ob->priv.mode.vdisplay);
if ((ob->priv.mode.hdisplay != conn->modes[0].hdisplay) ||
(ob->priv.mode.vdisplay != conn->modes[0].vdisplay))
{
/* set new crtc mode */
drmModeSetCrtc(ob->priv.fd, ob->priv.crtc, ob->priv.fb, 0, 0,
&ob->priv.conn, 1, &ob->priv.mode);
}
/* free connector resources */
drmModeFreeConnector(conn);
@ -588,6 +612,8 @@ evas_drm_outbuf_framebuffer_set(Outbuf *ob, Buffer *buffer)
/* validate params */
if ((!ob) || (!buffer)) return;
/* DBG("Drm Framebuffer Set: %d", buffer->fb); */
buffer->valid = EINA_FALSE;
ret = drmModeSetCrtc(ob->priv.fd, ob->priv.crtc, buffer->fb, 0, 0,
&ob->priv.conn, 1, &ob->priv.mode);
@ -611,6 +637,7 @@ evas_drm_framebuffer_create(int fd, Buffer *buffer, int depth)
carg.width = buffer->w;
carg.height = buffer->h;
carg.bpp = depth;
if (drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &carg) < 0)
{
ERR("Could not create dumb buffer: %m");
@ -621,13 +648,13 @@ evas_drm_framebuffer_create(int fd, Buffer *buffer, int depth)
buffer->size = carg.size;
buffer->handle = carg.handle;
/* DBG("Buffer: %d %d", buffer->w, buffer->h); */
/* DBG("Buffer Stride: %d", buffer->stride); */
/* DBG("Buffer Size: %d", buffer->size); */
DBG("Buffer: %d %d", buffer->w, buffer->h);
DBG("Buffer Stride: %d", buffer->stride);
DBG("Buffer Size: %d", buffer->size);
/* try to create a framebuffer object */
/* FIXME: Hardcoded bpp */
if (drmModeAddFB(fd, buffer->w, buffer->h, 32, depth, buffer->stride,
if (drmModeAddFB(fd, buffer->w, buffer->h, 24, depth, buffer->stride,
buffer->handle, &buffer->fb))
{
ERR("Could not create framebuffer object: %m");
@ -648,7 +675,7 @@ evas_drm_framebuffer_create(int fd, Buffer *buffer, int depth)
/* do actual mmap of memory */
buffer->data =
mmap(0, buffer->size, (PROT_READ | PROT_WRITE),
mmap(NULL, buffer->size, (PROT_READ | PROT_WRITE),
MAP_SHARED, fd, marg.offset);
if (buffer->data == MAP_FAILED)
{
@ -695,56 +722,50 @@ evas_drm_framebuffer_destroy(int fd, Buffer *buffer)
}
Eina_Bool
evas_drm_framebuffer_send(Outbuf *ob, Buffer *buffer, Eina_Rectangle *rects, unsigned int count)
evas_drm_framebuffer_send(Outbuf *ob, Buffer *buffer)
{
int ret;
unsigned int flags = 0;
/* check for valid Output buffer */
if ((!ob) || (ob->priv.fd < 0)) return EINA_FALSE;
/* check for valid buffer */
if ((!buffer) || (!buffer->valid)) return EINA_FALSE;
if (!buffer) return EINA_FALSE;
#ifdef DRM_MODE_FEATURE_DIRTYFB
drmModeClip *clip;
unsigned int i = 0;
/* WRN("drmModeDirtyFB is experimental"); */
/* NB: alloca automatically frees memory */
clip = alloca(count * sizeof(drmModeClip));
for (i = 0; i < count; i++)
if (ob->vsync)
{
clip[i].x1 = rects[i].x;
clip[i].y1 = rects[i].y;
clip[i].x2 = rects[i].w;
clip[i].y2 = rects[i].h;
}
unsigned int flags = 0;
ret = drmModeDirtyFB(ob->priv.fd, buffer->fb, clip, count);
if (ret)
if (!buffer->valid) evas_drm_outbuf_framebuffer_set(ob, buffer);
flags = DRM_MODE_PAGE_FLIP_EVENT;
if (ob->priv.use_async_page_flip) flags |= DRM_MODE_PAGE_FLIP_ASYNC;
ret = drmModePageFlip(ob->priv.fd, ob->priv.crtc,
buffer->fb, flags, ob);
if (ret)
{
ERR("Cannot flip crtc for connector %u: %m", ob->priv.conn);
return EINA_FALSE;
}
ob->priv.pending_flip = EINA_TRUE;
while (ob->priv.pending_flip)
drmHandleEvent(ob->priv.fd, &ob->priv.ctx);
}
else
{
if (ret == -EINVAL)
ERR("Could not set FB Dirty: %m");
/* NB: We don't actually need to do this if we are not vsync
* because we are drawing directly to the buffer anyway.
* If we enable the sending of buffer to crtc, it causes vsync */
/* send this buffer to the crtc */
/* evas_drm_outbuf_framebuffer_set(ob, buffer); */
/* increment buffer we are using */
ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num;
}
#endif
flags = DRM_MODE_PAGE_FLIP_EVENT;
if (ob->priv.use_async_page_flip) flags |= DRM_MODE_PAGE_FLIP_ASYNC;
ret = drmModePageFlip(ob->priv.fd, ob->priv.crtc, buffer->fb, flags, ob);
if (ret)
{
ERR("Cannot flip crtc for connector %u: %m", ob->priv.conn);
return EINA_FALSE;
}
/* ob->priv.sent = buffer; */
ob->priv.pending_flip = EINA_TRUE;
/* while (ob->priv.pending_flip) */
/* drmHandleEvent(ob->priv.fd, &ob->priv.ctx); */
return EINA_TRUE;
}