+static pthread_mutex_t tbm_surface_lock;
+
+static bool
+_tbm_surface_mutex_init (void)
+{
+ static bool tbm_surface_mutex_init = false;
+
+ if (tbm_surface_mutex_init)
+ return true;
+
+ if (pthread_mutex_init (&tbm_surface_lock, NULL))
+ {
+ TBM_LOG ("[libtbm] fail: tbm_surface mutex init\n");
+ return false;
+ }
+
+ tbm_surface_mutex_init = true;
+
+ return true;
+}
+
+void
+_tbm_surface_mutex_lock (void)
+{
+ if (!_tbm_surface_mutex_init ())
+ return;
+
+ pthread_mutex_lock (&tbm_surface_lock);
+}
+
+void
+_tbm_surface_mutex_unlock (void)
+{
+ pthread_mutex_unlock (&tbm_surface_lock);
+}
+
+static void
+_init_surface_bufmgr()
+{
+ g_surface_bufmgr = tbm_bufmgr_init (-1);
+}
+
+static void
+_deinit_surface_bufmgr()
+{
+ if (!g_surface_bufmgr)
+ return;
+
+ tbm_bufmgr_deinit (g_surface_bufmgr);
+ g_surface_bufmgr = NULL;
+}
+
+static int
+_tbm_surface_internal_query_size (tbm_surface_h surface)
+{
+ TBM_RETURN_VAL_IF_FAIL (surface, 0);
+
+ struct _tbm_surface *surf = (struct _tbm_surface *) surface;
+ struct _tbm_bufmgr *mgr = surf->bufmgr;
+ int size = 0;
+
+ TBM_RETURN_VAL_IF_FAIL (mgr != NULL, 0);
+ TBM_RETURN_VAL_IF_FAIL (surf->info.width > 0, 0);
+ TBM_RETURN_VAL_IF_FAIL (surf->info.height > 0, 0);
+ TBM_RETURN_VAL_IF_FAIL (surf->info.format > 0, 0);
+
+ size = mgr->backend->surface_get_size (surf, surf->info.width, surf->info.height, surf->info.format);
+
+ return size;
+}
+
+static int
+_tbm_surface_internal_query_plane_data (tbm_surface_h surface, int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch)
+{
+ TBM_RETURN_VAL_IF_FAIL (surface, 0);
+ TBM_RETURN_VAL_IF_FAIL (plane_idx > -1, 0);
+
+ struct _tbm_surface *surf = (struct _tbm_surface *) surface;
+ struct _tbm_bufmgr *mgr = surf->bufmgr;
+ int ret = 0;
+
+ TBM_RETURN_VAL_IF_FAIL (mgr != NULL, 0);
+ TBM_RETURN_VAL_IF_FAIL (surf->info.width > 0, 0);
+ TBM_RETURN_VAL_IF_FAIL (surf->info.height > 0, 0);
+ TBM_RETURN_VAL_IF_FAIL (surf->info.format > 0, 0);
+
+ ret = mgr->backend->surface_get_plane_data (surf, surf->info.width, surf->info.height, surf->info.format, plane_idx, size, offset, pitch);
+ if (!ret)
+ return 0;
+
+ return 1;
+}
+
+int
+tbm_surface_internal_query_supported_formats (uint32_t **formats, uint32_t *num)
+{
+ struct _tbm_bufmgr *mgr;
+ int ret = 0;
+
+ _tbm_surface_mutex_lock();
+
+ if (!g_surface_bufmgr)
+ {
+ _init_surface_bufmgr();
+ LIST_INITHEAD (&g_surface_list);
+ }
+
+ mgr = g_surface_bufmgr;
+ ret = mgr->backend->surface_supported_format (formats, num);
+
+ _tbm_surface_mutex_unlock();
+
+ return ret;
+}
+
+int tbm_surface_internal_get_num_planes (tbm_format format)