+/* LCOV_EXCL_START */
+INTERN tdm_private_capture *
+tdm_capture_create_layer_internal(tdm_private_layer *private_layer,
+ tdm_error *error)
+{
+ tdm_private_output *private_output = private_layer->private_output;
+ tdm_private_module *private_module = private_layer->private_module;
+ tdm_private_display *private_display = private_output->private_display;
+ tdm_func_layer *func_layer = &private_module->func_layer;
+ tdm_func_capture *func_capture = &private_module->func_capture;
+ tdm_private_capture *private_capture = NULL;
+ tdm_capture *capture_module = NULL;
+ tdm_error ret = TDM_ERROR_NONE;
+
+ TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
+
+ if (!(private_module->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
+ TDM_ERR("backend(%s) no capture capability", private_module->module_data->name);
+ if (error)
+ *error = TDM_ERROR_NO_CAPABILITY;
+ return NULL;
+ }
+
+ if (!(private_module->caps_capture.capabilities & TDM_CAPTURE_CAPABILITY_LAYER)) {
+ TDM_ERR("backend(%s) no layer capture capability", private_module->module_data->name);
+ if (error)
+ *error = TDM_ERROR_NO_CAPABILITY;
+ return NULL;
+ }
+
+ capture_module = func_layer->layer_create_capture(private_layer->layer_backend,
+ &ret);
+ if (ret != TDM_ERROR_NONE)
+ return NULL;
+
+ private_capture = calloc(1, sizeof(tdm_private_capture));
+ if (!private_capture) {
+ TDM_ERR("failed: alloc memory");
+ func_capture->capture_destroy(capture_module);
+ if (error)
+ *error = TDM_ERROR_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+ private_capture->stamp = tdm_helper_get_time();
+ while (_tdm_capture_find_object(private_display, private_capture->stamp))
+ private_capture->stamp++;
+
+ LIST_ADD(&private_capture->link, &private_layer->capture_list);
+ LIST_ADD(&private_capture->display_link, &private_module->capture_list);
+
+ private_capture->private_module = private_module;
+
+ private_capture->target = TDM_CAPTURE_TARGET_LAYER;
+ private_capture->private_display = private_display;
+ private_capture->private_output = private_output;
+ private_capture->private_layer = private_layer;
+ private_capture->capture_module = capture_module;
+ private_capture->owner_tid = syscall(SYS_gettid);
+
+ LIST_INITHEAD(&private_capture->pending_buffer_list);
+ LIST_INITHEAD(&private_capture->buffer_list);
+
+ TDM_DBG("capture(%p) create", private_capture);
+
+ if (error)
+ *error = TDM_ERROR_NONE;
+
+ return private_capture;
+}
+/* LCOV_EXCL_STOP */
+
+INTERN void
+tdm_capture_destroy_internal(tdm_private_capture *private_capture)
+{
+ tdm_private_display *private_display;
+ tdm_private_module *private_module;
+ tdm_func_capture *func_capture;
+ tdm_capture_private_buffer *b = NULL, *bb = NULL;
+ struct list_head clone_list;
+
+ TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
+
+ if (!private_capture)
+ return;
+
+ private_display = private_capture->private_display;
+
+ tdm_thread_cb_remove(private_capture, TDM_THREAD_CB_CAPTURE_DONE, NULL, _tdm_capture_thread_cb_done, NULL);
+
+ LIST_DEL(&private_capture->link);
+ LIST_DEL(&private_capture->display_link);
+
+ private_module = private_capture->private_module;
+ func_capture = &private_module->func_capture;
+ func_capture->capture_destroy(private_capture->capture_module);
+
+ if (!LIST_IS_EMPTY(&private_capture->pending_buffer_list)) {
+ TDM_WRN("capture(%p) not finished:", private_capture);
+ _tdm_capture_print_list(&private_capture->pending_buffer_list);
+
+ LIST_INITHEAD(&clone_list);
+ LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->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_CAPTURE) {
+ tbm_bo bo = tbm_surface_internal_get_bo(b->buffer, 0);
+ TDM_TRACE_ASYNC_END((intptr_t)private_capture, "[CAPTURE] %d", tbm_bo_export(bo));
+ }
+
+ tdm_buffer_unref_backend(b->buffer);
+ free(b);
+ }
+ _pthread_mutex_lock(&private_display->lock);
+ }
+
+ if (!LIST_IS_EMPTY(&private_capture->buffer_list)) {
+ TDM_WRN("capture(%p) not finished:", private_capture);
+ _tdm_capture_print_list(&private_capture->buffer_list);
+
+ LIST_INITHEAD(&clone_list);
+ LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->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_CAPTURE) {
+ tbm_bo bo = tbm_surface_internal_get_bo(b->buffer, 0);
+ TDM_TRACE_ASYNC_END((intptr_t)private_capture, "[CAPTURE] %d", tbm_bo_export(bo));
+ }
+
+ tdm_buffer_unref_backend(b->buffer);
+ free(b);
+ }
+ _pthread_mutex_lock(&private_display->lock);
+ }
+
+ private_capture->stamp = 0;
+ free(private_capture);