+ ch_info = calloc(1, sizeof *ch_info);
+ if (!ch_info) {
+ TDM_ERR("alloc failed: %m");
+ pthread_mutex_unlock(&valid_list_lock);
+ return TDM_ERROR_OUT_OF_MEMORY;
+ }
+
+ tdm_display_lock(dpy);
+ ret = tdm_thread_cb_add(dpy, TDM_THREAD_CB_VBLANK_CREATE, NULL, _tdm_vblank_thread_cb_create, ch_info);
+ tdm_display_unlock(dpy);
+
+ if (ret != TDM_ERROR_NONE) {
+ TDM_ERR("tdm_thread_cb_add failed");
+ free(ch_info);
+ pthread_mutex_unlock(&valid_list_lock);
+ return ret;
+ }
+
+ 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);