derekf pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=edcbff59b72ef8b26af99c1cb3c38f4ffb48282a
commit edcbff59b72ef8b26af99c1cb3c38f4ffb48282a Author: Derek Foreman <der...@osg.samsung.com> Date: Fri May 12 14:41:03 2017 -0500 ecore_drm2: refcount fbs Removes the previous "busy" flag, as now we might have an fb attached to multiple outputs at once, and need to be careful to destroy them only after they've been removed from all outputs. Removed the old "busy_set" API which nothing used, and renames fb_destroy to fb_discard to make it more clear that it's not immediately destroyed. It's all beta api, so I can do this. --- src/lib/ecore_drm2/Ecore_Drm2.h | 33 +++++--------- src/lib/ecore_drm2/ecore_drm2_fb.c | 65 ++++++++++++++++++--------- src/lib/ecore_drm2/ecore_drm2_plane.c | 17 +++++-- src/lib/ecore_drm2/ecore_drm2_private.h | 9 ++-- src/modules/evas/engines/drm/evas_outbuf.c | 2 +- src/modules/evas/engines/gl_drm/evas_outbuf.c | 2 +- 6 files changed, 76 insertions(+), 52 deletions(-) diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index af2f396..7d52d3a 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -803,16 +803,6 @@ EAPI Ecore_Drm2_Fb *ecore_drm2_fb_create(int fd, int width, int height, int dept EAPI Ecore_Drm2_Fb *ecore_drm2_fb_gbm_create(int fd, int width, int height, int depth, int bpp, unsigned int format, unsigned int handle, unsigned int stride, void *bo); /** - * Destroy a framebuffer object - * - * @param fb - * - * @ingroup Ecore_Drm2_Fb_Group - * @since 1.18 - */ -EAPI void ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb); - -/** * Get a framebuffer's mmap'd data * * @param fb @@ -901,17 +891,6 @@ EAPI Eina_Bool ecore_drm2_fb_flip_complete(Ecore_Drm2_Output *output); EAPI Eina_Bool ecore_drm2_fb_busy_get(Ecore_Drm2_Fb *fb); /** - * Change the Ecore_Drm2_Fb's busy status - * - * @param fb - * @param busy The new busy status - * - * @ingroup Ecore_Drm2_Fb_Group - * @since 1.19 - */ -EAPI void ecore_drm2_fb_busy_set(Ecore_Drm2_Fb *fb, Eina_Bool busy); - -/** * Try to force a framebuffer release for an output * * This tries to release the next or optionally pending, or current @@ -1045,6 +1024,18 @@ EAPI void ecore_drm2_plane_destination_set(Ecore_Drm2_Plane *plane, int x, int y */ EAPI Eina_Bool ecore_drm2_plane_fb_set(Ecore_Drm2_Plane *plane, Ecore_Drm2_Fb *fb); +/** + * Discard a framebuffer object + * + * Decreases the refcount on a fb object. It will be destroyed when it's + * no longer attached to scanout or otherwise in use. + * + * @param fb + * + * @ingroup Ecore_Drm2_Fb_Group + * @since 1.20 + */ +EAPI void ecore_drm2_fb_discard(Ecore_Drm2_Fb *fb); # endif diff --git a/src/lib/ecore_drm2/ecore_drm2_fb.c b/src/lib/ecore_drm2/ecore_drm2_fb.c index 1570895..b5161c6 100644 --- a/src/lib/ecore_drm2/ecore_drm2_fb.c +++ b/src/lib/ecore_drm2/ecore_drm2_fb.c @@ -142,11 +142,13 @@ err: return NULL; } -EAPI void -ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb) +static void +_ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb) { EINA_SAFETY_ON_NULL_RETURN(fb); + if (!fb->dead) ERR("Destroying an fb that hasn't been discarded"); + if (fb->mmap) munmap(fb->mmap, fb->sizes[0]); if (fb->id) sym_drmModeRmFB(fb->fd, fb->id); @@ -163,6 +165,32 @@ ecore_drm2_fb_destroy(Ecore_Drm2_Fb *fb) free(fb); } +void +_ecore_drm2_fb_ref(Ecore_Drm2_Fb *fb) +{ + fb->ref++; +} + +void +_ecore_drm2_fb_deref(Ecore_Drm2_Fb *fb) +{ + fb->ref--; + if (fb->ref) return; + + _ecore_drm2_fb_destroy(fb); +} + + +EAPI void +ecore_drm2_fb_discard(Ecore_Drm2_Fb *fb) +{ + EINA_SAFETY_ON_NULL_RETURN(fb); + EINA_SAFETY_ON_TRUE_RETURN(fb->ref < 1); + + fb->dead = EINA_TRUE; + _ecore_drm2_fb_deref(fb); +} + EAPI void * ecore_drm2_fb_data_get(Ecore_Drm2_Fb *fb) { @@ -213,8 +241,8 @@ ecore_drm2_fb_dirty(Ecore_Drm2_Fb *fb, Eina_Rectangle *rects, unsigned int count static void _release_buffer(Ecore_Drm2_Output *output, Ecore_Drm2_Output_State *s) { - s->fb->busy = EINA_FALSE; if (output->release_cb) output->release_cb(output->release_data, s->fb); + _ecore_drm2_fb_deref(s->fb); s->fb = NULL; #ifdef HAVE_ATOMIC_DRM if (s->atomic_req) @@ -226,6 +254,8 @@ _release_buffer(Ecore_Drm2_Output *output, Ecore_Drm2_Output_State *s) EAPI Eina_Bool ecore_drm2_fb_flip_complete(Ecore_Drm2_Output *output) { + Ecore_Drm2_Fb *fb; + EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE); if (output->current.fb && (output->current.fb != output->pending.fb)) @@ -249,6 +279,10 @@ ecore_drm2_fb_flip_complete(Ecore_Drm2_Output *output) } #endif + EINA_LIST_FREE(output->fbs, fb) + _ecore_drm2_fb_deref(fb); + output->fbs = NULL; + return !!output->next.fb; } @@ -427,7 +461,7 @@ _fb_flip(Ecore_Drm2_Output *output) if (output->current.fb) _release_buffer(output, &output->current); output->current.fb = fb; - output->current.fb->busy = EINA_TRUE; + _ecore_drm2_fb_ref(output->current.fb); output->next.fb = NULL; /* We used to return here, but now that the ticker is fixed this * can leave us hanging waiting for a tick to happen forever. @@ -484,7 +518,7 @@ _fb_flip(Ecore_Drm2_Output *output) else if (ret < 0) { output->next.fb = fb; - output->next.fb->busy = EINA_TRUE; + _ecore_drm2_fb_ref(output->next.fb); return 0; } @@ -501,11 +535,12 @@ ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output) if (!output->enabled) return -1; + if (fb) _ecore_drm2_fb_ref(fb); + if (output->pending.fb) { if (output->next.fb) _release_buffer(output, &output->next); output->next.fb = fb; - if (output->next.fb) output->next.fb->busy = EINA_TRUE; return 0; } if (!fb) fb = output->next.fb; @@ -513,14 +548,7 @@ ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output) /* So we can generate a tick by flipping to the current fb */ if (!fb) fb = output->current.fb; - if (output->next.fb) - { - output->next.fb->busy = EINA_FALSE; - output->next.fb = NULL; -#ifdef HAVE_ATOMIC_DRM - output->next.atomic_req = NULL; -#endif - } + if (output->next.fb) _release_buffer(output, &output->next); /* If we don't have an fb to set by now, BAIL! */ if (!fb) return -1; @@ -533,7 +561,6 @@ ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output) ret = _fb_flip(output); output->pending.fb = output->prep.fb; - output->pending.fb->busy = EINA_TRUE; output->prep.fb = NULL; #ifdef HAVE_ATOMIC_DRM output->pending.atomic_req = output->prep.atomic_req; @@ -546,14 +573,8 @@ EAPI Eina_Bool ecore_drm2_fb_busy_get(Ecore_Drm2_Fb *fb) { EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE); - return fb->busy; -} -EAPI void -ecore_drm2_fb_busy_set(Ecore_Drm2_Fb *fb, Eina_Bool busy) -{ - EINA_SAFETY_ON_NULL_RETURN(fb); - fb->busy = busy; + return !!(fb->ref - 1); } EAPI Eina_Bool diff --git a/src/lib/ecore_drm2/ecore_drm2_plane.c b/src/lib/ecore_drm2/ecore_drm2_plane.c index 2bf1917..a75173b 100644 --- a/src/lib/ecore_drm2/ecore_drm2_plane.c +++ b/src/lib/ecore_drm2/ecore_drm2_plane.c @@ -96,6 +96,7 @@ out: pstate->in_use = EINA_TRUE; pstate->cid.value = output->crtc_id; pstate->fid.value = fb->id; + pstate->fb = fb; pstate->sx.value = 0; pstate->sy.value = 0; @@ -119,8 +120,7 @@ out: return NULL; } - fb->ref++; - + _ecore_drm2_fb_ref(fb); DBG("FB %d assigned to Plane %d", fb->id, pstate->obj_id); output->planes = eina_list_append(output->planes, plane); @@ -133,7 +133,10 @@ ecore_drm2_plane_release(Ecore_Drm2_Plane *plane) EINA_SAFETY_ON_NULL_RETURN(plane); EINA_SAFETY_ON_TRUE_RETURN(plane->dead); + plane->output->fbs = eina_list_append(plane->output->fbs, + plane->state->fb); plane->dead = EINA_TRUE; + plane->state->fb = NULL; plane->state->in_use = EINA_FALSE; _fb_atomic_flip_test(plane->output); } @@ -163,8 +166,14 @@ ecore_drm2_plane_fb_set(Ecore_Drm2_Plane *plane, Ecore_Drm2_Fb *fb) fallback_id = plane->state->fid.value; plane->state->fid.value = fb->id; - if (_fb_atomic_flip_test(plane->output)) return EINA_TRUE; - + if (_fb_atomic_flip_test(plane->output)) + { + _ecore_drm2_fb_ref(fb); + plane->output->fbs = eina_list_append(plane->output->fbs, + plane->state->fb); + plane->state->fb = fb; + return EINA_TRUE; + } plane->state->fid.value = fallback_id; return EINA_FALSE; } diff --git a/src/lib/ecore_drm2/ecore_drm2_private.h b/src/lib/ecore_drm2/ecore_drm2_private.h index b73add3..2be6069 100644 --- a/src/lib/ecore_drm2/ecore_drm2_private.h +++ b/src/lib/ecore_drm2/ecore_drm2_private.h @@ -646,6 +646,7 @@ typedef struct _Ecore_Drm2_Plane_State /* these are not part of an atomic state, but we store these here * so that we do not have to refetch properties when iterating planes */ + Ecore_Drm2_Fb *fb; uint32_t rotation_map[6]; uint32_t supported_rotations; @@ -701,12 +702,11 @@ struct _Ecore_Drm2_Fb uint32_t format; void *gbm_bo; + void *mmap; Eina_Bool gbm : 1; Eina_Bool dmabuf : 1; - Eina_Bool busy : 1; - - void *mmap; + Eina_Bool dead : 1; }; struct _Ecore_Drm2_Plane @@ -795,6 +795,7 @@ struct _Ecore_Drm2_Output Eina_List *plane_states; Eina_List *planes; + Eina_List *fbs; Eina_Bool connected : 1; Eina_Bool primary : 1; @@ -837,6 +838,8 @@ struct _Ecore_Drm2_Device }; Eina_Bool _fb_atomic_flip_test(Ecore_Drm2_Output *output); +void _ecore_drm2_fb_ref(Ecore_Drm2_Fb *); +void _ecore_drm2_fb_deref(Ecore_Drm2_Fb *); /* extern int (*sym_drmClose)(int fd); */ /* extern int (*sym_drmWaitVBlank)(int fd, drmVBlank *vbl); */ diff --git a/src/modules/evas/engines/drm/evas_outbuf.c b/src/modules/evas/engines/drm/evas_outbuf.c index f45e45c..f890854 100644 --- a/src/modules/evas/engines/drm/evas_outbuf.c +++ b/src/modules/evas/engines/drm/evas_outbuf.c @@ -81,7 +81,7 @@ _outbuf_fb_create(Outbuf *ob, Outbuf_Fb *ofb) static void _outbuf_fb_destroy(Outbuf_Fb *ofb) { - ecore_drm2_fb_destroy(ofb->fb); + ecore_drm2_fb_discard(ofb->fb); memset(ofb, 0, sizeof(*ofb)); ofb->valid = EINA_FALSE; diff --git a/src/modules/evas/engines/gl_drm/evas_outbuf.c b/src/modules/evas/engines/gl_drm/evas_outbuf.c index efc9977..89eef8c 100644 --- a/src/modules/evas/engines/gl_drm/evas_outbuf.c +++ b/src/modules/evas/engines/gl_drm/evas_outbuf.c @@ -41,7 +41,7 @@ _evas_outbuf_fb_cb_destroy(struct gbm_bo *bo EINA_UNUSED, void *data) Ecore_Drm2_Fb *fb; fb = data; - if (fb) ecore_drm2_fb_destroy(fb); + if (fb) ecore_drm2_fb_discard(fb); } static Ecore_Drm2_Fb * --