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().
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
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
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)
{
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)
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;
+}
}
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,
#include <poll.h>
#include <sys/syscall.h>
#include <sys/types.h>
+#include <sys/eventfd.h>
#include <math.h>
#include <grp.h>
/* 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 {
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;
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;
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
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;
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;
}