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.
This commit is contained in:
Derek Foreman 2017-05-12 14:41:03 -05:00
parent 69b941f018
commit edcbff59b7
6 changed files with 76 additions and 52 deletions

View File

@ -802,16 +802,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
*
@ -900,17 +890,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
*
@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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); */

View File

@ -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;

View File

@ -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 *