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
*/
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);
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)
{
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,
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;
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;
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
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;
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;
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;
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 =