private_output = (tdm_private_output*)output; \
private_display = private_output->private_display
+#define OUTPUT_FUNC_ENTRY_VOID() \
+ tdm_private_display *private_display; \
+ tdm_private_output *private_output; \
+ TDM_RETURN_IF_FAIL(tdm_output_is_valid(output)); \
+ private_output = (tdm_private_output*)output; \
+ private_display = private_output->private_display
+
static void
_tdm_output_vblank_timeout_update(tdm_private_output *private_output, int ms_delay);
INTERN tdm_error
tdm_output_init(tdm_private_display *private_display)
{
+ tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_DESTROY, tdm_display_find_output_stamp);
tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_COMMIT, tdm_display_find_output_stamp);
tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_VBLANK, tdm_display_find_output_stamp);
tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_STATUS, tdm_display_find_output_stamp);
tdm_thread_cb_set_find_func(TDM_THREAD_CB_OUTPUT_DPMS, tdm_display_find_output_stamp);
+ return TDM_ERROR_NONE;
+}
+
+INTERN tdm_error
+tdm_output_call_thread_cb_destroy(tdm_private_output *private_output)
+{
+ tdm_thread_cb_output_destroy output_destroy;
+ tdm_error ret;
+
+ memset(&output_destroy, 0, sizeof output_destroy);
+ output_destroy.base.type = TDM_THREAD_CB_OUTPUT_DESTROY;
+ output_destroy.base.length = sizeof output_destroy;
+ output_destroy.base.object_stamp = private_output->stamp;
+ output_destroy.base.data = NULL;
+ output_destroy.base.sync = 1;
+
+ ret = tdm_thread_cb_call(private_output, &output_destroy.base, 1);
+ TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
return TDM_ERROR_NONE;
}
+INTERN void
+tdm_output_thread_cb_destroy(tdm_private_display *private_display, void *object, tdm_thread_cb_base *cb_base, void *user_data)
+{
+ tdm_private_output *private_output = object;
+ tdm_private_output_destroy_handler *destroy_handler = user_data;
+
+ TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
+
+ assert(destroy_handler->owner_tid == syscall(SYS_gettid));
+
+ _pthread_mutex_unlock(&private_display->lock);
+ destroy_handler->func(private_output, destroy_handler->user_data);
+ _pthread_mutex_lock(&private_display->lock);
+}
+
+EXTERN tdm_error
+tdm_output_add_destroy_handler(tdm_output *output,
+ tdm_output_destroy_handler func,
+ void *user_data)
+{
+ tdm_private_output_destroy_handler *destroy_handler = NULL;
+ OUTPUT_FUNC_ENTRY();
+
+ TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ _pthread_mutex_lock(&private_display->lock);
+
+ LIST_FOR_EACH_ENTRY(destroy_handler, &private_output->destroy_handler_list, link) {
+ if (destroy_handler->func == func && destroy_handler->user_data == user_data) {
+ TDM_ERR("can't add twice");
+ _pthread_mutex_unlock(&private_display->lock);
+ return TDM_ERROR_BAD_REQUEST;
+ }
+ }
+
+ destroy_handler = calloc(1, sizeof(tdm_private_output_destroy_handler));
+ if (!destroy_handler) {
+ TDM_ERR("failed: alloc memory");
+ _pthread_mutex_unlock(&private_display->lock);
+ return TDM_ERROR_OUT_OF_MEMORY;
+ }
+
+ ret = tdm_thread_cb_add(private_output, TDM_THREAD_CB_OUTPUT_DESTROY, NULL, tdm_output_thread_cb_destroy, destroy_handler);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("tdm_thread_cb_add failed");
+ free(destroy_handler);
+ _pthread_mutex_unlock(&private_display->lock);
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+
+ destroy_handler->private_output = private_output;
+ destroy_handler->func = func;
+ destroy_handler->user_data = user_data;
+ destroy_handler->owner_tid = syscall(SYS_gettid);
+
+ LIST_ADDTAIL(&destroy_handler->link, &private_output->destroy_handler_list);
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ return ret;
+}
+
+
+EXTERN void
+tdm_output_remove_destroy_handler(tdm_output *output,
+ tdm_output_destroy_handler func,
+ void *user_data)
+{
+ tdm_private_display *private_display;
+ tdm_private_output *private_output;
+ tdm_private_output_destroy_handler *destroy_handler = NULL, *hh = NULL;
+
+ TDM_RETURN_IF_FAIL(output != NULL);
+ TDM_RETURN_IF_FAIL(func != NULL);
+
+ private_output = (tdm_private_output*)output;
+ private_display = private_output->private_display;
+
+ _pthread_mutex_lock(&private_display->lock);
+
+ LIST_FOR_EACH_ENTRY_SAFE(destroy_handler, hh, &private_output->destroy_handler_list, link) {
+ if (destroy_handler->func != func || destroy_handler->user_data != user_data)
+ continue;
+
+ tdm_thread_cb_remove(private_output, TDM_THREAD_CB_OUTPUT_DESTROY, NULL, tdm_output_thread_cb_destroy, destroy_handler);
+
+ LIST_DEL(&destroy_handler->link);
+ free(destroy_handler);
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ return;
+ }
+
+ _pthread_mutex_unlock(&private_display->lock);
+}
+
EXTERN tdm_module *
tdm_output_get_backend_module(tdm_output *output, tdm_error *error)
{
if ((private_output->caps.status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED && status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED) ||
(private_output->caps.status != TDM_OUTPUT_CONN_STATUS_DISCONNECTED && status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)) {
- ret = tdm_display_update_output(private_output->private_module, output_backend, private_output->pipe, 1);
+ ret = tdm_display_update_output(private_output->private_module, output_backend);
TDM_RETURN_IF_FAIL(ret == TDM_ERROR_NONE);
} else {
private_output->caps.status = status;
return ret;
}
+EXTERN tdm_error
+tdm_output_add_mode_change_request_handler(tdm_output *output,
+ tdm_output_mode_change_request_handler func,
+ void *user_data)
+{
+ tdm_private_display *private_display;
+ tdm_private_output *private_output;
+ tdm_private_output_mode_change_handler *mode_change_handler = NULL;
+
+ TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ private_output = (tdm_private_output*)output;
+ private_display = private_output->private_display;
+
+ _pthread_mutex_lock(&private_display->lock);
+
+ LIST_FOR_EACH_ENTRY(mode_change_handler, &private_output->mode_change_request_handler_list, link) {
+ if (mode_change_handler->func == func && mode_change_handler->user_data == user_data) {
+ TDM_ERR("can't add twice");
+ _pthread_mutex_unlock(&private_display->lock);
+ return TDM_ERROR_BAD_REQUEST;
+ }
+ }
+
+ mode_change_handler = calloc(1, sizeof(tdm_private_output_change_handler));
+ if (!mode_change_handler) {
+ /* LCOV_EXCL_START */
+ TDM_ERR("failed: alloc memory");
+ _pthread_mutex_unlock(&private_display->lock);
+ return TDM_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ mode_change_handler->private_output = private_output;
+ mode_change_handler->func = func;
+ mode_change_handler->user_data = user_data;
+
+ LIST_ADDTAIL(&mode_change_handler->link, &private_output->mode_change_request_handler_list);
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ return TDM_ERROR_NONE;
+}
+
+EXTERN tdm_error
+tdm_output_remove_mode_change_request_handler(tdm_output *output,
+ tdm_output_mode_change_request_handler func,
+ void *user_data)
+{
+ tdm_private_display *private_display;
+ tdm_private_output *private_output;
+ tdm_private_output_mode_change_handler *mode_change_handler = NULL, *hh = NULL;
+
+ TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ private_output = (tdm_private_output*)output;
+ private_display = private_output->private_display;
+
+ _pthread_mutex_lock(&private_display->lock);
+
+ LIST_FOR_EACH_ENTRY_SAFE(mode_change_handler, hh, &private_output->mode_change_request_handler_list, link) {
+ if (mode_change_handler->func != func || mode_change_handler->user_data != user_data)
+ continue;
+
+ LIST_DEL(&mode_change_handler->link);
+ free(mode_change_handler);
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ return TDM_ERROR_NONE;
+ }
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ return TDM_ERROR_INVALID_PARAMETER;
+}
+
EXTERN void
tdm_output_remove_change_handler(tdm_output *output,
tdm_output_change_handler func,
*count = 0;
LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link)
- (*count)++;
+ (*count)++;
if (*count == 0) {
_pthread_mutex_unlock(&private_display->lock);
return TDM_ERROR_NONE;
return ret;
}
+INTERN void
+tdm_output_call_mode_set_request(tdm_output *output, unsigned int index)
+{
+ tdm_private_output *private_output = (tdm_private_output*)output;
+ tdm_private_output_mode_change_handler *mode_change_handler = NULL;
+
+ TDM_RETURN_IF_FAIL(private_output != NULL);
+ TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
+
+ if (LIST_IS_EMPTY(&private_output->mode_change_request_handler_list))
+ return;
+
+ LIST_FOR_EACH_ENTRY(mode_change_handler, &private_output->mode_change_request_handler_list, link) {
+ mode_change_handler->func(mode_change_handler->private_output, index, mode_change_handler->user_data);
+ }
+}
+
+tdm_error
+_tdm_output_commit_virtual(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data)
+{
+ tdm_private_output *private_output;
+ tdm_private_output_commit_handler *output_commit_handler = NULL;
+ tdm_private_layer *private_layer = NULL;
+ tdm_private_display *private_display;
+ tbm_surface_h buffer;
+ tdm_error ret = TDM_ERROR_NONE;
+
+ TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ private_output = (tdm_private_output*)output;
+ private_display = private_output->private_display;
+
+ if (!LIST_IS_EMPTY(&private_output->output_commit_handler_list)) {
+ /* support only 1 commit */
+ TDM_ERR("voutput canot commit while commiting");
+ return TDM_ERROR_OPERATION_FAILED;
+ }
+
+ output_commit_handler = calloc(1, sizeof(tdm_private_output_commit_handler));
+ if (!output_commit_handler) {
+ /* LCOV_EXCL_START */
+ TDM_ERR("failed: alloc memory");
+ return TDM_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ LIST_ADDTAIL(&output_commit_handler->link, &private_output->output_commit_handler_list);
+ output_commit_handler->private_output = private_output;
+ output_commit_handler->func = func;
+ output_commit_handler->user_data = user_data;
+ output_commit_handler->owner_tid = syscall(SYS_gettid);
+
+ /* voutput use only 1 layer */
+ LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
+ if (private_layer) break;
+ }
+ TDM_GOTO_IF_FAIL(private_layer, commit_failed);
+
+ buffer = private_layer->commiting_buffer;
+ TDM_GOTO_IF_FAIL(buffer != NULL, commit_failed);
+
+ _pthread_mutex_unlock(&private_display->lock);
+ ret = tdm_output_attach_buffer(private_output, buffer);
+ TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
+ ret = tdm_output_commit_buffer(private_output);
+ TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);
+ _pthread_mutex_lock(&private_display->lock);
+
+ return ret;
+
+commit_failed:
+ /* LCOV_EXCL_START */
+ if (output_commit_handler) {
+ LIST_DEL(&output_commit_handler->link);
+ free(output_commit_handler);
+ }
+ return ret;
+/* LCOV_EXCL_STOP */
+}
+
INTERN tdm_error
tdm_output_commit_internal(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data)
{
+ tdm_private_display *private_display;
tdm_private_output *private_output;
tdm_private_module *private_module;
tdm_func_output *func_output;
private_output = (tdm_private_output*)output;
private_module = private_output->private_module;
+ private_display = private_module->private_display;
func_output = &private_module->func_output;
+ if (private_module == private_display->virtual_module)
+ return _tdm_output_commit_virtual(output, sync, func, user_data);
+
if (!func_output->output_commit) {
/* LCOV_EXCL_START */
TDM_WRN("not implemented!!");
return TDM_ERROR_NONE;
}
+
+INTERN tdm_error
+tdm_output_set_available_mode(tdm_output *output, const tdm_output_mode *modes, int count)
+{
+ tdm_private_module *private_module = NULL;
+ tdm_func_output *func_output = NULL;
+
+ OUTPUT_FUNC_ENTRY();
+
+ TDM_RETURN_VAL_IF_FAIL(modes != NULL, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(count != 0, TDM_ERROR_INVALID_PARAMETER);
+
+ private_module = private_output->private_module;
+ TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE);
+
+ _pthread_mutex_lock(&private_display->lock);
+
+ func_output = &private_module->func_output;
+ if (func_output->output_set_available_mode)
+ ret = func_output->output_set_available_mode(private_output->output_backend, modes, count);
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ return ret;
+}
+
+INTERN tdm_error
+tdm_output_set_physical_size(tdm_output *output, unsigned int mmwidth, unsigned int mmheight)
+{
+ tdm_private_module *private_module = NULL;
+ tdm_func_output *func_output = NULL;
+
+ OUTPUT_FUNC_ENTRY();
+
+ TDM_RETURN_VAL_IF_FAIL(mmwidth != 0, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(mmheight != 0, TDM_ERROR_INVALID_PARAMETER);
+
+ private_module = private_output->private_module;
+ TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE);
+
+ _pthread_mutex_lock(&private_display->lock);
+
+ func_output = &private_module->func_output;
+ if (func_output->output_set_physical_size)
+ ret = func_output->output_set_physical_size(private_output->output_backend, mmwidth, mmheight);
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ return ret;
+}
+
+INTERN tdm_error
+tdm_output_set_connect(tdm_output *output)
+{
+ tdm_private_module *private_module = NULL;
+ tdm_func_output *func_output = NULL;
+
+ OUTPUT_FUNC_ENTRY();
+
+ private_module = private_output->private_module;
+ TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE);
+
+ _pthread_mutex_lock(&private_display->lock);
+
+ func_output = &private_module->func_output;
+ if (func_output->output_set_connect)
+ ret = func_output->output_set_connect(private_output->output_backend);
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ return ret;
+}
+
+INTERN tdm_error
+tdm_output_set_disconnect(tdm_output *output)
+{
+ tdm_private_module *private_module = NULL;
+ tdm_func_output *func_output = NULL;
+
+ OUTPUT_FUNC_ENTRY();
+
+ private_module = private_output->private_module;
+ TDM_RETURN_VAL_IF_FAIL(private_module == private_display->virtual_module, TDM_ERROR_BAD_MODULE);
+
+ _pthread_mutex_lock(&private_display->lock);
+
+ func_output = &private_module->func_output;
+ if (func_output->output_set_disconnect)
+ ret = func_output->output_set_disconnect(private_output->output_backend);
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ return ret;
+}
+
+INTERN tdm_error
+tdm_output_commit_done(tdm_output *output, tbm_surface_h buffer)
+{
+ tdm_private_layer *private_layer = NULL;
+ tdm_private_output_commit_handler *output_commit_handler = NULL;
+ static int sequence = 0;
+ tdm_private_output *private_output;
+ TDM_RETURN_VAL_IF_FAIL(output != NULL, TDM_ERROR_INVALID_PARAMETER); \
+ private_output = (tdm_private_output*)output;
+
+ LIST_FOR_EACH_ENTRY(private_layer, &private_output->layer_list, link) {
+ if (private_layer) break;
+ }
+
+ private_layer->commiting_buffer = NULL;
+
+ LIST_FOR_EACH_ENTRY(output_commit_handler, &private_output->output_commit_handler_list, link) {
+ if (output_commit_handler) break;
+ }
+ TDM_RETURN_VAL_IF_FAIL(output_commit_handler, TDM_ERROR_INVALID_PARAMETER);
+
+ LIST_DEL(&output_commit_handler->link);
+
+ output_commit_handler->func(private_output,
+ sequence++,
+ 0, 0,
+ output_commit_handler->user_data);
+ free(output_commit_handler);
+
+ return TDM_ERROR_NONE;
+}
/* LCOV_EXCL_STOP */