support the asynchronous DPMS operation 69/83269/1
authorBoram Park <boram1288.park@samsung.com>
Wed, 10 Aug 2016 01:33:58 +0000 (10:33 +0900)
committerBoram Park <boram1288.park@samsung.com>
Wed, 10 Aug 2016 01:33:58 +0000 (10:33 +0900)
Change-Id: Ie7f43fc8abb8f93d3fa6472b34525ca2c7f34982

include/tdm_backend.h
src/tdm_display.c
src/tdm_private.h
src/tdm_thread.c

index d455d1d..c7328ec 100644 (file)
@@ -72,6 +72,15 @@ typedef void (*tdm_output_status_handler)(tdm_output *output,
                                                                                  void *user_data);
 
 /**
+ * @brief The output dpms handler
+ * @details This handler will be called when the dpms of a output object is
+ * changed in runtime.
+ */
+typedef void (*tdm_output_dpms_handler)(tdm_output *output,
+                                                                               tdm_output_dpms dpms,
+                                                                               void *user_data);
+
+/**
  * @brief The display capabilities structure of a backend module
  * @see The display_get_capability() function of #tdm_func_display
  */
@@ -501,7 +510,19 @@ typedef struct _tdm_func_output {
                                                                                   tdm_output_status_handler func,
                                                                                   void *user_data);
 
-       void (*reserved1)(void);
+       /**
+        * @brief Set a output dpms handler
+        * @details A backend module needs to call the output dpms handler when the
+        * output DPMS has been changed to let the TDM frontend know the change.
+        * @param[in] output A output object
+        * @param[in] func A output dpms handler
+        * @param[in] user_data The user data
+        * @return #TDM_ERROR_NONE if success. Otherwise, error value.
+        * @since 1.4.0
+        */
+       tdm_error (*output_set_dpms_handler)(tdm_output *output,
+                                                                                tdm_output_dpms_handler func,
+                                                                                void *user_data);
        void (*reserved2)(void);
        void (*reserved3)(void);
        void (*reserved4)(void);
index e31b563..38cec19 100644 (file)
@@ -1130,6 +1130,51 @@ _tdm_output_dpms_changed_timeout(void *user_data)
        return TDM_ERROR_NONE;
 }
 
+INTERN void
+tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms, void *user_data)
+{
+       tdm_private_display *private_display;
+       tdm_private_output *private_output = user_data;
+       tdm_value value;
+
+       TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
+       TDM_RETURN_IF_FAIL(private_output);
+
+       private_display = private_output->private_display;
+
+       if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) {
+               tdm_thread_cb_output_dpms output_dpms;
+               tdm_error ret;
+
+               _tdm_output_update(output_backend, user_data);
+
+               output_dpms.base.type = TDM_THREAD_CB_OUTPUT_DPMS;
+               output_dpms.base.length = sizeof output_dpms;
+               output_dpms.output_stamp = private_output->stamp;
+               output_dpms.dpms = dpms;
+               output_dpms.user_data = user_data;
+
+               value.u32 = dpms;
+               tdm_output_call_change_handler_internal(private_output,
+                                                                                               &private_output->change_handler_list_sub,
+                                                                                               TDM_OUTPUT_CHANGE_DPMS,
+                                                                                               value, 0);
+
+               ret = tdm_thread_send_cb(private_display->private_loop, &output_dpms.base);
+               TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
+
+               return;
+       }
+
+       private_output->current_dpms_value = dpms;
+
+       value.u32 = dpms;
+       tdm_output_call_change_handler_internal(private_output,
+                                                                                       &private_output->change_handler_list_main,
+                                                                                       TDM_OUTPUT_CHANGE_DPMS,
+                                                                                       value, 0);
+}
+
 EXTERN tdm_error
 tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
 {
@@ -1146,6 +1191,12 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
                return TDM_ERROR_NONE;
        }
 
+       /** Use timer to call the output change callback of the sub-thread.
+        * The output change callback of tdm_server and tdm_vblank was called
+        * in the main thread. And it made the multi thread issue. If we use
+        * the timer, we can call the sub-thread's output change callback in
+        * sub-thread.
+        */
        if (!private_output->dpms_changed_timer) {
                private_output->dpms_changed_timer =
                        tdm_event_loop_add_timer_handler(private_output->private_display,
@@ -1166,8 +1217,17 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
                return TDM_ERROR_NONE;
        }
 
+       if (func_output->output_set_dpms_handler) {
+               if (!private_output->regist_dpms_cb) {
+                       private_output->regist_dpms_cb = 1;
+                       ret = func_output->output_set_dpms_handler(private_output->output_backend,
+                                                                                                          tdm_output_cb_dpms, private_output);
+               }
+       }
+
        ret = func_output->output_set_dpms(private_output->output_backend, dpms_value);
-       if (ret == TDM_ERROR_NONE) {
+
+       if (ret == TDM_ERROR_NONE && !func_output->output_set_dpms_handler) {
                tdm_value value;
 
                private_output->current_dpms_value = dpms_value;
index 186ac14..e56a19a 100644 (file)
@@ -176,6 +176,7 @@ struct _tdm_private_output {
        int regist_vblank_cb;
        int regist_commit_cb;
        int regist_change_cb;
+       int regist_dpms_cb;
 
        struct list_head layer_list;
        struct list_head capture_list;
@@ -359,6 +360,9 @@ void
 tdm_output_cb_status(tdm_output *output_backend, tdm_output_conn_status status,
                                         void *user_data);
 void
+tdm_output_cb_dpms(tdm_output *output_backend, tdm_output_dpms dpms,
+                                  void *user_data);
+void
 tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst,
                           void *user_data);
 void
@@ -416,6 +420,7 @@ typedef enum {
        TDM_THREAD_CB_OUTPUT_COMMIT,
        TDM_THREAD_CB_OUTPUT_VBLANK,
        TDM_THREAD_CB_OUTPUT_STATUS,
+       TDM_THREAD_CB_OUTPUT_DPMS,
        TDM_THREAD_CB_PP_DONE,
        TDM_THREAD_CB_CAPTURE_DONE,
 } tdm_thread_cb_type;
@@ -424,6 +429,7 @@ typedef struct _tdm_thread_cb_base tdm_thread_cb_base;
 typedef struct _tdm_thread_cb_output_vblank tdm_thread_cb_output_commit;
 typedef struct _tdm_thread_cb_output_vblank tdm_thread_cb_output_vblank;
 typedef struct _tdm_thread_cb_output_status tdm_thread_cb_output_status;
+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;
 
@@ -448,6 +454,13 @@ struct _tdm_thread_cb_output_status {
        void *user_data;
 };
 
+struct _tdm_thread_cb_output_dpms {
+       tdm_thread_cb_base base;
+       unsigned long output_stamp;
+       tdm_output_dpms dpms;
+       void *user_data;
+};
+
 struct _tdm_thread_cb_pp_done {
        tdm_thread_cb_base base;
        unsigned long pp_stamp;
index 03ce03a..7c1067c 100644 (file)
@@ -318,6 +318,17 @@ tdm_thread_handle_cb(tdm_private_loop *private_loop)
                                                                 output_status->user_data);
                        break;
                }
+               case TDM_THREAD_CB_OUTPUT_DPMS: {
+                       tdm_thread_cb_output_dpms *output_dpms = (tdm_thread_cb_output_dpms*)base;
+                       tdm_output *output_backend =
+                               tdm_display_find_output_stamp(private_loop->dpy, output_dpms->output_stamp);
+                       if (!output_backend) {
+                               TDM_WRN("no output(%ld)", output_dpms->output_stamp);
+                               break;
+                       }
+                       tdm_output_cb_dpms(output_backend, output_dpms->dpms, output_dpms->user_data);
+                       break;
+               }
                case TDM_THREAD_CB_PP_DONE: {
                        tdm_thread_cb_pp_done *pp_done = (tdm_thread_cb_pp_done*)base;
                        tdm_pp *pp_backend =