+ tdm_pp_private_buffer *pp_buffer;
+
+ PP_FUNC_ENTRY();
+
+ TDM_RETURN_VAL_IF_FAIL(src != NULL, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(dst != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+ _pthread_mutex_lock(&private_display->lock);
+
+ if (!func_pp->pp_attach) {
+ /* LCOV_EXCL_START */
+ _pthread_mutex_unlock(&private_display->lock);
+ TDM_DBG("failed: not implemented!!");
+ return TDM_ERROR_NOT_IMPLEMENTED;
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (tdm_display_check_module_abi(private_display, 1, 2) &&
+ private_display->caps_pp.max_attach_count > 0) {
+ /* LCOV_EXCL_START */
+ int length = LIST_LENGTH(&private_pp->pending_buffer_list) +
+ LIST_LENGTH(&private_pp->buffer_list);
+ if (length >= private_display->caps_pp.max_attach_count) {
+ _pthread_mutex_unlock(&private_display->lock);
+ TDM_DBG("failed: too many attached!! max_attach_count(%d)",
+ private_display->caps_pp.max_attach_count);
+ return TDM_ERROR_BAD_REQUEST;
+ }
+ /* LCOV_EXCL_STOP */
+ }
+
+ if (tdm_debug_dump & TDM_DUMP_FLAG_PP) {
+ /* LCOV_EXCL_START */
+ char str[TDM_PATH_LEN];
+ static int i;
+ snprintf(str, TDM_PATH_LEN, "pp_src_%03d", i++);
+ tdm_helper_dump_buffer_str(src, tdm_debug_dump_dir, str);
+ /* LCOV_EXCL_STOP */
+ }
+
+ pp_buffer = calloc(1, sizeof * pp_buffer);
+ if (!pp_buffer) {
+ /* LCOV_EXCL_START */
+ _pthread_mutex_unlock(&private_display->lock);
+ TDM_ERR("alloc failed");
+ return TDM_ERROR_OUT_OF_MEMORY;
+ /* LCOV_EXCL_STOP */
+ }
+
+ ret = func_pp->pp_attach(private_pp->pp_backend, src, dst);
+ TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
+
+ if (ret != TDM_ERROR_NONE) {
+ /* LCOV_EXCL_START */
+ free(pp_buffer);
+ _pthread_mutex_unlock(&private_display->lock);
+ TDM_ERR("attach failed");
+ return ret;
+ /* LCOV_EXCL_STOP */
+ }
+
+ LIST_ADDTAIL(&pp_buffer->link, &private_pp->pending_buffer_list);
+ pp_buffer->src = tdm_buffer_ref_backend(src);
+ pp_buffer->dst = tdm_buffer_ref_backend(dst);
+
+ if (tdm_debug_module & TDM_DEBUG_BUFFER) {
+ TDM_INFO("pp(%p) attached:", private_pp);
+ _tdm_pp_print_list(&private_pp->pending_buffer_list);
+ }
+
+ if (tdm_ttrace_module & TDM_TTRACE_PP) {
+ tbm_bo bo = tbm_surface_internal_get_bo(dst, 0);
+ TDM_TRACE_ASYNC_BEGIN((int)pp, "[PP] %d", tbm_bo_export(bo));
+ }
+
+ _pthread_mutex_unlock(&private_display->lock);
+
+ return ret;
+}