+ ch_info->func = func;
+ ch_info->user_data = user_data;
+
+ LIST_ADDTAIL(&ch_info->link, &create_handler_list);
+
+ pthread_mutex_unlock(&valid_list_lock);
+
+ return TDM_ERROR_NONE;
+}
+
+EXTERN void
+tdm_vblank_remove_create_handler(tdm_display *dpy, tdm_vblank_create_handler func, void *user_data)
+{
+ tdm_vblank_create_handler_info *ch_info = NULL, *hh = NULL;
+
+ TDM_RETURN_IF_FAIL(dpy != NULL);
+ TDM_RETURN_IF_FAIL(func != NULL);
+
+ tdm_display_lock(dpy);
+ pthread_mutex_lock(&valid_list_lock);
+ LIST_FOR_EACH_ENTRY_SAFE(ch_info, hh, &create_handler_list, link) {
+ if (ch_info->func != func || ch_info->user_data != user_data)
+ continue;
+
+ tdm_thread_cb_remove(dpy, TDM_THREAD_CB_VBLANK_CREATE, NULL, _tdm_vblank_thread_cb_create, ch_info);
+
+ LIST_DEL(&ch_info->link);
+ free(ch_info);
+ pthread_mutex_unlock(&valid_list_lock);
+ tdm_display_unlock(dpy);
+ return;
+ }
+ pthread_mutex_unlock(&valid_list_lock);
+ tdm_display_unlock(dpy);
+}
+
+static void*
+_tdm_vblank_find_display(tdm_private_display *private_display, double stamp)
+{
+ return private_display;
+}
+
+INTERN tdm_error
+tdm_vblank_init(tdm_display *dpy)
+{
+ if (vblank_list_inited)
+ return TDM_ERROR_NONE;
+
+ LIST_INITHEAD(&valid_vblank_list);
+ LIST_INITHEAD(&valid_wait_list);
+ LIST_INITHEAD(&create_handler_list);
+
+ tdm_thread_cb_set_find_func(TDM_THREAD_CB_VBLANK_SW, _tdm_vblank_find_object);
+ tdm_thread_cb_set_find_func(TDM_THREAD_CB_VBLANK_CREATE, _tdm_vblank_find_display);
+
+ vblank_list_inited = 1;
+
+ return TDM_ERROR_NONE;
+}
+
+INTERN void
+tdm_vblank_deinit(tdm_display *dpy)
+{
+ tdm_vblank_create_handler_info *ch_info = NULL, *hh = NULL;
+
+ if (!vblank_list_inited)
+ return;
+
+ if (!LIST_IS_EMPTY(&valid_vblank_list))
+ TDM_NEVER_GET_HERE();
+
+ if (!LIST_IS_EMPTY(&valid_wait_list))
+ TDM_NEVER_GET_HERE();
+
+ LIST_FOR_EACH_ENTRY_SAFE(ch_info, hh, &create_handler_list, link) {
+ LIST_DEL(&ch_info->link);
+ free(ch_info);
+ }
+
+ vblank_list_inited = 0;
+}
+
+EXTERN tdm_vblank *
+tdm_vblank_create(tdm_display *dpy, tdm_output *output, tdm_error *error)
+{
+ tdm_private_vblank *private_vblank;
+ tdm_error ret;
+
+ TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(tdm_display_is_valid(dpy), TDM_ERROR_INVALID_PARAMETER, NULL);
+ TDM_RETURN_VAL_IF_FAIL_WITH_ERROR(tdm_output_is_valid(output), TDM_ERROR_INVALID_PARAMETER, NULL);
+
+ if (error)
+ *error = TDM_ERROR_NONE;