diff --git a/src/lib/ecore_drm2/Ecore_Drm2.h b/src/lib/ecore_drm2/Ecore_Drm2.h index 99a2e9a278..587f17fe6e 100644 --- a/src/lib/ecore_drm2/Ecore_Drm2.h +++ b/src/lib/ecore_drm2/Ecore_Drm2.h @@ -61,6 +61,8 @@ typedef struct _Ecore_Drm2_Event_Activate EAPI extern int ECORE_DRM2_EVENT_OUTPUT_CHANGED; EAPI extern int ECORE_DRM2_EVENT_ACTIVATE; +typedef void (*Ecore_Drm2_Release_Handler)(void *data, Ecore_Drm2_Fb *b); + /** * @file * @brief Ecore functions for dealing with drm, virtual terminals @@ -808,6 +810,20 @@ EAPI void ecore_drm2_fb_busy_set(Ecore_Drm2_Fb *fb, Eina_Bool busy); */ EAPI void ecore_drm2_output_user_data_set(Ecore_Drm2_Output *o, void *data); +/** + * Register a callback for the buffer release handler + * + * When a flip completes ecore_drm2 may release a buffer. Use this callback + * if you need to do bookkeeping or locking on buffer release. + * + * @param output The output to register the callback on + * @param handler The function to handle the callback + * @param data The user data to pass to the callback + * @ingroup Ecore_Drm2_Output_Group + * @since 1.19 + */ +EAPI void ecore_drm2_output_release_handler_set(Ecore_Drm2_Output *output, Ecore_Drm2_Release_Handler handler, void *data); + /** * Get the Framebuffer's gbm buffer object * diff --git a/src/lib/ecore_drm2/ecore_drm2_fb.c b/src/lib/ecore_drm2/ecore_drm2_fb.c index d7727689f6..aedef9f0d5 100644 --- a/src/lib/ecore_drm2/ecore_drm2_fb.c +++ b/src/lib/ecore_drm2/ecore_drm2_fb.c @@ -224,16 +224,20 @@ ecore_drm2_fb_dirty(Ecore_Drm2_Fb *fb, Eina_Rectangle *rects, unsigned int count #endif } +static void _release_buffer(Ecore_Drm2_Output *output, Ecore_Drm2_Fb *b) +{ + b->busy = EINA_FALSE; + if (output->release_cb) output->release_cb(output->release_data, b); +} + EAPI Eina_Bool ecore_drm2_fb_flip_complete(Ecore_Drm2_Output *output) { - if (output->current) output->current->busy = EINA_FALSE; + if (output->current && (output->current != output->pending)) + _release_buffer(output, output->current); output->current = output->pending; output->pending = NULL; - /* In case they were the same buffer... */ - if (output->current) output->current->busy = EINA_TRUE; - return !!output->next; } @@ -249,7 +253,7 @@ ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output) if (output->pending) { - if (output->next) output->next->busy = EINA_FALSE; + if (output->next) _release_buffer(output, output->next); output->next = fb; if (output->next) output->next->busy = EINA_TRUE; return 0; @@ -283,7 +287,7 @@ ecore_drm2_fb_flip(Ecore_Drm2_Fb *fb, Ecore_Drm2_Output *output) return ret; } - if (output->current) output->current->busy = EINA_FALSE; + if (output->current) _release_buffer(output, output->current); output->current = fb; output->current->busy = EINA_TRUE; output->next = NULL; diff --git a/src/lib/ecore_drm2/ecore_drm2_outputs.c b/src/lib/ecore_drm2/ecore_drm2_outputs.c index 3f32092abc..dff74616be 100644 --- a/src/lib/ecore_drm2/ecore_drm2_outputs.c +++ b/src/lib/ecore_drm2/ecore_drm2_outputs.c @@ -1202,3 +1202,10 @@ ecore_drm2_output_user_data_set(Ecore_Drm2_Output *o, void *data) { o->user_data = data; } + +EAPI void +ecore_drm2_output_release_handler_set(Ecore_Drm2_Output *o, Ecore_Drm2_Release_Handler cb, void *data) +{ + o->release_data = data; + o->release_cb = cb; +} diff --git a/src/lib/ecore_drm2/ecore_drm2_private.h b/src/lib/ecore_drm2/ecore_drm2_private.h index d78d011f13..bce5edec89 100644 --- a/src/lib/ecore_drm2/ecore_drm2_private.h +++ b/src/lib/ecore_drm2/ecore_drm2_private.h @@ -154,6 +154,8 @@ struct _Ecore_Drm2_Output Eina_List *planes; void *user_data; + Ecore_Drm2_Release_Handler release_cb; + void *release_data; Eina_Bool connected : 1; Eina_Bool primary : 1;