+ TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
+
+ LIST_FOR_EACH_ENTRY(private_module, &private_display->module_list, link) {
+ LIST_FOR_EACH_ENTRY(private_pp, &private_module->pp_list, link) {
+ if (private_pp->stamp == stamp)
+ return private_pp;
+ }
+ }
+
+ return NULL;
+}
+
+INTERN tdm_error
+tdm_pp_init(tdm_private_display *private_display)
+{
+ tdm_thread_cb_set_find_func(TDM_THREAD_CB_PP_DONE, _tdm_pp_find_object);
+
+ return TDM_ERROR_NONE;
+}
+
+INTERN tdm_private_pp *
+tdm_pp_create_internal(tdm_private_module *private_module, tdm_error *error)
+{
+ tdm_private_display *private_display;
+ tdm_func_display *func_display;
+ tdm_func_pp *func_pp;
+ tdm_private_pp *private_pp = NULL;
+ tdm_pp *pp_module = NULL;
+ tdm_error ret = TDM_ERROR_NONE;
+
+ TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
+ TDM_RETURN_VAL_IF_FAIL(private_module != NULL, NULL);
+
+ private_display = private_module->private_display;
+ func_display = &private_module->func_display;
+ func_pp = &private_module->func_pp;
+
+ if (!(private_module->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
+ /* LCOV_EXCL_START */
+ TDM_ERR("backedn(%s) no pp capability", private_module->module_data->name);
+ if (error)
+ *error = TDM_ERROR_NO_CAPABILITY;
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ pp_module = func_display->display_create_pp(private_module->bdata, &ret);
+ if (ret != TDM_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ if (error)
+ *error = ret;
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ private_pp = calloc(1, sizeof(tdm_private_pp));
+ if (!private_pp) {
+ /* LCOV_EXCL_START */
+ TDM_ERR("failed: alloc memory");
+ func_pp->pp_destroy(pp_module);
+ if (error)
+ *error = TDM_ERROR_OUT_OF_MEMORY;
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = tdm_thread_cb_add(private_pp, TDM_THREAD_CB_PP_DONE, NULL, _tdm_pp_thread_cb_done, NULL);
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("pp tdm_thread_cb_add failed");
+ func_pp->pp_destroy(pp_module);
+ free(private_pp);
+ if (error)
+ *error = ret;
+ return NULL;
+ }
+
+ ret = func_pp->pp_set_done_handler(pp_module, _tdm_pp_cb_done, private_pp);
+ if (ret != TDM_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ TDM_ERR("spp(%p) et pp_done_handler failed", private_pp);
+ func_pp->pp_destroy(pp_module);
+ free(private_pp);
+ if (error)
+ *error = ret;
+ return NULL;
+ /* LCOV_EXCL_STOP */
+ }
+
+ private_pp->stamp = tdm_helper_get_time();
+ while (_tdm_pp_find_object(private_display, private_pp->stamp))
+ private_pp->stamp++;
+
+ LIST_ADD(&private_pp->link, &private_module->pp_list);
+ private_pp->private_display = private_module->private_display;
+ private_pp->private_module = private_module;
+ private_pp->pp_module = pp_module;
+ private_pp->owner_tid = syscall(SYS_gettid);
+
+ LIST_INITHEAD(&private_pp->pending_buffer_list);
+ LIST_INITHEAD(&private_pp->buffer_list);
+
+ if (error)
+ *error = TDM_ERROR_NONE;
+
+ return private_pp;
+}
+
+INTERN void
+tdm_pp_destroy_internal(tdm_private_pp *private_pp)
+{
+ tdm_private_display *private_display;
+ tdm_private_module *private_module;
+ tdm_func_pp *func_pp;
+ tdm_pp_private_buffer *b = NULL, *bb = NULL;
+ struct list_head clone_list;
+
+ TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
+
+ if (!private_pp)
+ return;
+
+ tdm_thread_cb_remove(private_pp, TDM_THREAD_CB_PP_DONE, NULL, _tdm_pp_thread_cb_done, NULL);
+
+ private_display = private_pp->private_display;
+ private_module = private_pp->private_module;
+ func_pp = &private_module->func_pp;
+
+ LIST_DEL(&private_pp->link);
+
+ func_pp->pp_destroy(private_pp->pp_module);
+
+ if (!LIST_IS_EMPTY(&private_pp->pending_buffer_list)) {
+ TDM_WRN("pp(%p) not finished:", private_pp);
+ _tdm_pp_print_list(&private_pp->pending_buffer_list);
+
+ LIST_INITHEAD(&clone_list);
+ LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->pending_buffer_list, link) {
+ LIST_DEL(&b->link);
+ LIST_ADDTAIL(&b->link, &clone_list);
+ }
+
+ _pthread_mutex_unlock(&private_display->lock);
+ LIST_FOR_EACH_ENTRY_SAFE(b, bb, &clone_list, link) {
+ LIST_DEL(&b->link);
+
+ if (tdm_ttrace_module & TDM_TTRACE_PP) {
+ tbm_bo bo = tbm_surface_internal_get_bo(b->dst, 0);
+ TDM_TRACE_ASYNC_END((intptr_t)private_pp, "[PP] %d", tbm_bo_export(bo));
+ }
+
+ tdm_buffer_unref_backend(b->src);
+ tdm_buffer_unref_backend(b->dst);
+ free(b);
+ }
+ _pthread_mutex_lock(&private_display->lock);
+ }
+
+ if (!LIST_IS_EMPTY(&private_pp->buffer_list)) {
+ TDM_WRN("pp(%p) not finished:", private_pp);
+ _tdm_pp_print_list(&private_pp->buffer_list);
+
+ LIST_INITHEAD(&clone_list);
+ LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->buffer_list, link) {
+ LIST_DEL(&b->link);
+ LIST_ADDTAIL(&b->link, &clone_list);
+ }
+
+ _pthread_mutex_unlock(&private_display->lock);
+ LIST_FOR_EACH_ENTRY_SAFE(b, bb, &clone_list, link) {
+ LIST_DEL(&b->link);
+
+ if (tdm_ttrace_module & TDM_TTRACE_PP) {
+ tbm_bo bo = tbm_surface_internal_get_bo(b->dst, 0);
+ TDM_TRACE_ASYNC_END((intptr_t)private_pp, "[PP] %d", tbm_bo_export(bo));
+ }
+
+ tdm_buffer_unref_backend(b->src);
+ tdm_buffer_unref_backend(b->dst);
+ free(b);
+ }
+ _pthread_mutex_lock(&private_display->lock);
+ }
+
+ private_pp->stamp = 0;
+ free(private_pp);