summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Foreman <derekf@osg.samsung.com>2017-05-12 14:41:03 -0500
committerDerek Foreman <derekf@osg.samsung.com>2017-05-12 17:51:34 -0500
commitedcbff59b72ef8b26af99c1cb3c38f4ffb48282a (patch)
tree3715fc4cdd8906b55969edf4214fdc3f1e7da9d6
parent69b941f018a5e289f4eb34adcfdc774c0d9a2409 (diff)
downloadefl-edcbff59b72ef8b26af99c1cb3c38f4ffb48282a.tar.gz
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.
-rw-r--r--src/lib/ecore_drm2/Ecore_Drm2.h33
-rw-r--r--src/lib/ecore_drm2/ecore_drm2_fb.c65
-rw-r--r--src/lib/ecore_drm2/ecore_drm2_plane.c17
-rw-r--r--src/lib/ecore_drm2/ecore_drm2_private.h9
-rw-r--r--src/modules/evas/engines/drm/evas_outbuf.c2
-rw-r--r--src/modules/evas/engines/gl_drm/evas_outbuf.c2
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 af2f396442..7d52d3aa00 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 1570895294..b5161c67c2 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 2bf1917545..a75173bcfc 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 b73add3667..2be6069b69 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 f45e45c119..f890854bb9 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 efc9977195..89eef8c06a 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 *