+ return NULL;
+}
+
+tdm_server_voutput_buffer *
+_tdm_output_get_voutput_buffer(tdm_server_voutput_info *voutput_info, tbm_surface_h buffer)
+{
+ tdm_server_voutput_buffer *voutput_buffer = NULL, *vb = NULL;
+
+ LIST_FOR_EACH_ENTRY(vb, &voutput_info->buffer_list, link) {
+ if (vb && vb->buffer == buffer) {
+ tbm_surface_internal_ref(vb->buffer);
+ return vb;
+ }
+ }
+
+ tbm_surface_internal_ref(buffer);
+ voutput_buffer = calloc(1, sizeof *voutput_buffer);
+ if (!voutput_buffer) {
+ /* LCOV_EXCL_START */
+
+ TDM_ERR("fail calloc");
+ tbm_surface_internal_unref(buffer);
+ return NULL;
+
+ /* LCOV_EXCL_STOP */
+ }
+
+ voutput_buffer->wl_buffer = _tdm_voutput_export_buffer(voutput_info, buffer);
+ if (!voutput_buffer->wl_buffer) {
+ /* LCOV_EXCL_START */
+
+ TDM_ERR("fail export buffer");
+ free(voutput_buffer);
+ tbm_surface_internal_unref(buffer);
+ return NULL;
+
+ /* LCOV_EXCL_STOP */
+ }
+
+ voutput_buffer->buffer = buffer;
+ LIST_ADDTAIL(&voutput_buffer->link, &voutput_info->buffer_list);
+
+ return voutput_buffer;
+}
+
+tdm_error
+tdm_voutput_attach_buffer(tdm_voutput *voutput, tbm_surface_h buffer)
+{
+ tdm_private_server *private_server = keep_private_server;
+ tdm_server_voutput_info *voutput_info = NULL, *vo = NULL;
+ tdm_server_voutput_buffer *voutput_buffer = NULL;
+
+ TDM_RETURN_VAL_IF_FAIL(keep_private_server != NULL, TDM_ERROR_OPERATION_FAILED);
+
+ LIST_FOR_EACH_ENTRY(vo, &private_server->voutput_list, link) {
+ if (vo && vo->voutput == voutput) {
+ voutput_info = vo;
+ break;
+ }
+ }
+ TDM_RETURN_VAL_IF_FAIL(voutput_info != NULL, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(voutput_info->attach_buffer == NULL, TDM_ERROR_OPERATION_FAILED);
+
+ voutput_buffer = _tdm_output_get_voutput_buffer(voutput_info, buffer);
+ TDM_RETURN_VAL_IF_FAIL(voutput_buffer != NULL, TDM_ERROR_OUT_OF_MEMORY);
+
+ voutput_info->attach_buffer = voutput_buffer;
+
+ wl_tdm_voutput_send_attach_buffer(voutput_info->resource, voutput_buffer->wl_buffer);
+
+ return TDM_ERROR_NONE;
+}
+
+tdm_error
+tdm_voutput_commit_buffer(tdm_voutput *voutput)
+{
+ tdm_private_server *private_server = keep_private_server;
+ tdm_server_voutput_info *voutput_info = NULL, *vo = NULL;
+
+ TDM_RETURN_VAL_IF_FAIL(keep_private_server != NULL, TDM_ERROR_OPERATION_FAILED);
+
+ LIST_FOR_EACH_ENTRY(vo, &private_server->voutput_list, link) {
+ if (vo && vo->voutput == voutput) {
+ voutput_info = vo;
+ break;
+ }
+ }
+ TDM_RETURN_VAL_IF_FAIL(voutput_info != NULL, TDM_ERROR_INVALID_PARAMETER);
+ TDM_RETURN_VAL_IF_FAIL(voutput_info->attach_buffer != NULL, TDM_ERROR_OPERATION_FAILED);
+ TDM_RETURN_VAL_IF_FAIL(voutput_info->committing == 0, TDM_ERROR_OPERATION_FAILED);
+
+ voutput_info->committing = 1;
+
+ wl_tdm_voutput_send_commit(voutput_info->resource);
+
+ return TDM_ERROR_NONE;
+}
+
+void
+tdm_voutput_cb_resource_destroy(struct wl_resource *resource)
+{
+ tdm_server_voutput_info *voutput_info = wl_resource_get_user_data(resource);
+ tdm_server_voutput_buffer *vb = NULL;
+ tdm_voutput *voutput;
+ tdm_error ret = TDM_ERROR_NONE;
+
+ TDM_RETURN_IF_FAIL(voutput_info != NULL);
+
+ voutput = voutput_info->voutput;
+
+ if (voutput_info->request_commit)
+ tdm_output_unset_voutput_commit(voutput_info->voutput);
+
+ if (voutput) {
+ if (voutput_info->request_commit == 1) {
+ tdm_output_unset_voutput_commit(voutput_info->voutput);
+ voutput_info->request_commit = 0;
+ tdm_voutput_disconnect(voutput_info->voutput);
+ }
+
+ ret = tdm_voutput_destroy(voutput);
+ if (ret != TDM_ERROR_NONE)
+ TDM_ERR("_tdm_voutput_cb_destroy fail");
+ }
+
+ if (voutput_info->attach_buffer) {
+ tbm_surface_h buffer = voutput_info->attach_buffer->buffer;
+ tbm_surface_internal_unref(buffer);
+ voutput_info->committing = 0;
+ voutput_info->attach_buffer = NULL;
+ }
+
+ LIST_FOR_EACH_ENTRY(vb, &voutput_info->buffer_list, link) {
+ if (vb->wl_buffer)
+ wl_resource_destroy(vb->wl_buffer);
+ }
+
+ LIST_DEL(&voutput_info->link);
+
+ /* Do free your own resource */
+ free(voutput_info);