[hwc] add the ability to ask a client(E20) about the revalidation 94/156894/1
authorSergey Sizonov <s.sizonov@samsung.com>
Fri, 20 Oct 2017 11:17:38 +0000 (14:17 +0300)
committerSergey Sizonov <s.sizonov@samsung.com>
Fri, 20 Oct 2017 11:26:14 +0000 (14:26 +0300)
The backends may need to ask E20 for revalidation
for some reason (power consumption, performance,...).

So we need some way to let backend do this.

The new TDM API function:
 tdm_output_set_need_validate_handler();

and TDM/backend interface API function:
 tdm_backend_trigger_need_validate_event();

have been added to let backend ask client(E20) for the
revalidation.

Change-Id: Ife266a55043cbf420702098b06223e46ef67c041
Signed-off-by: Sergey Sizonov <s.sizonov@samsung.com>
include/tdm.h
include/tdm_backend.h
include/tdm_types.h
src/tdm.c
src/tdm_backend.c
src/tdm_output.c
src/tdm_private.h
src/tdm_thread.c

index b7fb89e..50fe717 100644 (file)
@@ -635,6 +635,22 @@ tdm_error
 tdm_output_validate(tdm_output *output, uint32_t *num_types);
 
 /**
+ * @brief Set the 'need to validate' handler for the 'output'
+ *
+ * @details During backend's work it may need to ask for the revalidation
+ * (make client (E20) do tdm_output_validate() again), so a 'hndl' will
+ * be called as such need happen. Only one handler per output is supported.
+ *
+ * @param[in] output The output object a hndl is going to be registered for.
+ * @param[in] hndl The handler which will be called on the 'need to validate' event.
+ *
+ * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+ */
+tdm_error
+tdm_output_set_need_validate_handler(tdm_output *output,
+               tdm_output_need_validate_handler hndl);
+
+/**
  * @brief Get changed composition types
  * @details Retrieves the windows for which the device requires a different
  * composition type than had been set prior to the last call to tdm_output_validate().
index 6411f61..f78a3a7 100644 (file)
@@ -1317,6 +1317,15 @@ tdm_event_loop_source_timer_update(tdm_event_loop_source *source, unsigned int m
 void
 tdm_event_loop_source_remove(tdm_event_loop_source *source);
 
+/**
+ * @brief Trigger a 'need to validate' event.
+ * @param[in] output The output the event should be triggered for.
+ * @note The global display lock has to be locked before the call to this function.
+ * @see #tdm_output_set_need_validate_handler
+ */
+tdm_error
+tdm_backend_trigger_need_validate_event(tdm_output *output);
+
 #ifdef __cplusplus
 }
 #endif
index 7602b84..5b537c6 100644 (file)
@@ -293,6 +293,11 @@ typedef void (*tdm_pp_done_handler)(tdm_pp *pp, tbm_surface_h src,
 typedef void (*tdm_capture_done_handler)(tdm_capture *capture,
                                                                                 tbm_surface_h buffer, void *user_data);
 
+/**
+ * @brief The 'need to validate' handler of an output object
+ */
+typedef void (*tdm_output_need_validate_handler)(tdm_output *output);
+
 #ifdef __cplusplus
 }
 #endif
index 315b027..cb397b8 100644 (file)
--- a/src/tdm.c
+++ b/src/tdm.c
@@ -669,6 +669,70 @@ int tdm_debug_dump;
 static tdm_private_display *g_private_display;
 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
 
+/* gets called on behalf of the ecore-main-loop thread */
+INTERN tdm_error
+tdm_handle_need_validate_event(tdm_thread_cb_need_validate *ev)
+{
+       tdm_private_output *private_output;
+
+       TDM_RETURN_VAL_IF_FAIL(ev != NULL, TDM_ERROR_INVALID_PARAMETER);
+       TDM_RETURN_VAL_IF_FAIL(ev->o != NULL, TDM_ERROR_OPERATION_FAILED);
+
+       private_output = ev->o;
+
+       TDM_INFO("tdm-backend asks for revalidation for the output:%p.", private_output);
+
+       if (private_output->need_validate.hndl)
+               private_output->need_validate.hndl((tdm_output*)private_output);
+
+       return TDM_ERROR_NONE;
+}
+
+/* gets called on behalf of the tdm-thread */
+static tdm_error
+_need_validate_handler(int fd, tdm_event_loop_mask mask, void *user_data)
+{
+       tdm_thread_cb_need_validate ev;
+       tdm_private_output *private_output;
+       tdm_error ret;
+
+       private_output = (tdm_private_output *)user_data;
+
+       ev.base.type = TDM_THREAD_CB_NEED_VALIDATE;
+       ev.base.length = sizeof ev;
+       ev.o = private_output;
+
+       ret = tdm_thread_send_cb(private_output->private_display->private_loop, &ev.base);
+       TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
+
+       TDM_INFO("tdm-thread: get a 'need to revalidate' event for the ouptut:%p.", private_output);
+
+       /* who cares about this? */
+       return TDM_ERROR_NONE;
+}
+
+static void
+_tdm_backend_events_init(tdm_private_display *priv_dsp)
+{
+       tdm_private_output *o;
+       tdm_error err = TDM_ERROR_NONE;
+       int fd;
+
+       /* build in eventfd fds into event_loop listened & handled by the tdm-thread */
+       LIST_FOR_EACH_ENTRY(o, &priv_dsp->output_list, link) {
+               fd = eventfd(0, 0);
+               TDM_WARNING_IF_FAIL(fd >= 0);
+
+               tdm_event_loop_add_fd_handler(priv_dsp, fd,     TDM_EVENT_LOOP_READABLE,
+                               _need_validate_handler, o, &err);
+               TDM_WARNING_IF_FAIL(err == TDM_ERROR_NONE);
+
+               o->need_validate.event_fd = fd;
+
+               TDM_INFO("register an output:%p for the revalidation, event_fd:%d.", o, fd);
+       }
+}
+
 static tdm_error
 _tdm_display_check_module(tdm_backend_module *module)
 {
@@ -1008,6 +1072,9 @@ tdm_display_init(tdm_error *error)
        private_display->init_count = 1;
        private_display->commit_type = TDM_COMMIT_TYPE_NONE;
 
+       if (private_display->hwc_enable)
+               _tdm_backend_events_init(private_display);
+
        g_private_display = private_display;
 
        if (error)
index d25066f..94aca18 100644 (file)
@@ -181,3 +181,23 @@ tdm_backend_register_func_capture(tdm_display *dpy,
        return TDM_ERROR_NONE;
 }
 
+EXTERN tdm_error
+tdm_backend_trigger_need_validate_event(tdm_output *output)
+{
+       tdm_private_output *private_output;
+       uint64_t value;
+       int res;
+
+       TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       private_output = (tdm_private_output*)output;
+       value = 1;
+
+       /* do not lock the global display lock here */
+
+       res = write(private_output->need_validate.event_fd, &value, sizeof(value));
+       if (res < 0)
+               return TDM_ERROR_OPERATION_FAILED;
+
+       return TDM_ERROR_NONE;
+}
index dc8c87a..b7ae3be 100644 (file)
@@ -1397,6 +1397,30 @@ tdm_output_validate(tdm_output *output, uint32_t *num_types)
 }
 
 EXTERN tdm_error
+tdm_output_set_need_validate_handler(tdm_output *output,
+               tdm_output_need_validate_handler hndl)
+{
+       OUTPUT_FUNC_ENTRY();
+
+       TDM_RETURN_VAL_IF_FAIL(hndl != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       _pthread_mutex_lock(&private_display->lock);
+
+       /* there's no reason to allow this */
+       if (private_output->need_validate.hndl) {
+
+               _pthread_mutex_unlock(&private_display->lock);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       private_output->need_validate.hndl = hndl;
+
+       _pthread_mutex_unlock(&private_display->lock);
+
+       return ret;
+}
+
+EXTERN tdm_error
 tdm_output_get_changed_composition_types(tdm_output *output,
                                                                                 uint32_t *num_elements,
                                                                                 tdm_hwc_window **hwc_window,
index 691d4d9..01d2e48 100644 (file)
@@ -52,6 +52,7 @@
 #include <poll.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
+#include <sys/eventfd.h>
 #include <math.h>
 #include <grp.h>
 
@@ -226,6 +227,12 @@ struct _tdm_private_output {
 
        /* TODO: temp solution for handling DPMS things in sub-htread */
        tdm_event_loop_source *dpms_changed_timer;
+
+       struct {
+               /* look at the tdm_output_set_need_revalidate_handler() declaration for the details */
+               tdm_output_need_validate_handler hndl;
+               int event_fd;
+       } need_validate;
 };
 
 struct _tdm_private_layer {
@@ -539,6 +546,7 @@ typedef enum {
        TDM_THREAD_CB_PP_DONE,
        TDM_THREAD_CB_CAPTURE_DONE,
        TDM_THREAD_CB_VBLANK_SW,
+       TDM_THREAD_CB_NEED_VALIDATE,
 } tdm_thread_cb_type;
 
 typedef struct _tdm_thread_cb_base tdm_thread_cb_base;
@@ -549,6 +557,7 @@ typedef struct _tdm_thread_cb_output_dpms tdm_thread_cb_output_dpms;
 typedef struct _tdm_thread_cb_pp_done tdm_thread_cb_pp_done;
 typedef struct _tdm_thread_cb_capture_done tdm_thread_cb_capture_done;
 typedef struct _tdm_thread_cb_vblank_sw tdm_thread_cb_vblank_sw;
+typedef struct _tdm_thread_cb_need_validate tdm_thread_cb_need_validate;
 
 struct _tdm_thread_cb_base {
        tdm_thread_cb_type type;
@@ -598,6 +607,11 @@ struct _tdm_thread_cb_vblank_sw {
        double vblank_stamp;
 };
 
+struct _tdm_thread_cb_need_validate {
+       tdm_thread_cb_base base;
+       tdm_private_output *o;
+};
+
 tdm_error
 tdm_thread_init(tdm_private_loop *private_loop);
 void
@@ -722,6 +736,8 @@ tdm_display_enable_fps(tdm_private_display *private_display, int enable);
 void
 tdm_monitor_server_command(tdm_display *dpy, const char *options, char *reply, int *len);
 
+tdm_error
+tdm_handle_need_validate_event(tdm_thread_cb_need_validate *ev);
 
 struct argument_details {
        char type;
index 4659740..c6f3007 100644 (file)
@@ -356,6 +356,11 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop)
                        tdm_vblank_cb_vblank_SW(NULL, vblank_sw->vblank_stamp);
                        break;
                }
+               case TDM_THREAD_CB_NEED_VALIDATE: {
+                       tdm_thread_cb_need_validate *ev = (tdm_thread_cb_need_validate*)base;
+                       tdm_handle_need_validate_event(ev);
+                       break;
+               }
                default:
                        break;
                }