modify lock flow
[platform/core/uifw/libtbm.git] / src / tbm_surface_internal.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #include "config.h"
33 #include "tbm_bufmgr.h"
34 #include "tbm_bufmgr_int.h"
35 #include "tbm_surface_internal.h"
36 #include "list.h"
37
38 static tbm_bufmgr g_surface_bufmgr = NULL;
39 struct list_head g_surface_list; /* list of surfaces belonging to bufmgr */
40
41 static pthread_mutex_t tbm_surface_lock;
42
43 static bool
44 _tbm_surface_mutex_init (void)
45 {
46     static bool tbm_surface_mutex_init = false;
47
48     if (tbm_surface_mutex_init)
49         return true;
50
51     if (pthread_mutex_init (&tbm_surface_lock, NULL))
52     {
53         TBM_LOG ("[libtbm] fail: tbm_surface mutex init\n");
54         return false;
55     }
56
57     tbm_surface_mutex_init = true;
58
59     return true;
60 }
61
62 void
63 _tbm_surface_mutex_lock (void)
64 {
65     if (!_tbm_surface_mutex_init ())
66         return;
67
68     pthread_mutex_lock (&tbm_surface_lock);
69 }
70
71 void
72 _tbm_surface_mutex_unlock (void)
73 {
74     pthread_mutex_unlock (&tbm_surface_lock);
75 }
76
77 static void
78 _init_surface_bufmgr()
79 {
80     g_surface_bufmgr = tbm_bufmgr_init (-1);
81 }
82
83 static void
84 _deinit_surface_bufmgr()
85 {
86     if (!g_surface_bufmgr)
87         return;
88
89     tbm_bufmgr_deinit (g_surface_bufmgr);
90     g_surface_bufmgr = NULL;
91 }
92
93 static int
94 _tbm_surface_internal_query_size (tbm_surface_h surface)
95 {
96     TBM_RETURN_VAL_IF_FAIL (surface, 0);
97
98     struct _tbm_surface *surf = (struct _tbm_surface *) surface;
99     struct _tbm_bufmgr *mgr = surf->bufmgr;
100     int size = 0;
101
102     TBM_RETURN_VAL_IF_FAIL (mgr != NULL, 0);
103     TBM_RETURN_VAL_IF_FAIL (surf->info.width > 0, 0);
104     TBM_RETURN_VAL_IF_FAIL (surf->info.height > 0, 0);
105     TBM_RETURN_VAL_IF_FAIL (surf->info.format > 0, 0);
106
107     if (!mgr->backend->surface_get_size)
108         return 0;
109
110     size = mgr->backend->surface_get_size (surf, surf->info.width, surf->info.height, surf->info.format);
111
112     return size;
113 }
114
115 static int
116 _tbm_surface_internal_query_plane_data (tbm_surface_h surface, int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
117 {
118     TBM_RETURN_VAL_IF_FAIL (surface, 0);
119     TBM_RETURN_VAL_IF_FAIL (plane_idx > -1, 0);
120
121     struct _tbm_surface *surf = (struct _tbm_surface *) surface;
122     struct _tbm_bufmgr *mgr = surf->bufmgr;
123     int ret = 0;
124
125     TBM_RETURN_VAL_IF_FAIL (mgr != NULL, 0);
126     TBM_RETURN_VAL_IF_FAIL (surf->info.width > 0, 0);
127     TBM_RETURN_VAL_IF_FAIL (surf->info.height > 0, 0);
128     TBM_RETURN_VAL_IF_FAIL (surf->info.format > 0, 0);
129
130     if (!mgr->backend->surface_get_plane_data)
131         return 0;
132
133     ret = mgr->backend->surface_get_plane_data (surf, surf->info.width, surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
134     if (!ret)
135         return 0;
136
137     return 1;
138 }
139
140 static int
141 _tbm_surface_internal_query_num_bos (tbm_format format)
142 {
143     TBM_RETURN_VAL_IF_FAIL (format > 0, 0);
144     struct _tbm_bufmgr *mgr;
145     int ret = 0;
146
147     mgr = g_surface_bufmgr;
148
149     if (!mgr->backend->surface_get_num_bos)
150         return 0;
151
152     ret = mgr->backend->surface_get_num_bos (format);
153     if (!ret)
154         return 0;
155
156     return ret;
157 }
158
159 static void
160 _tbm_surface_internal_destroy (tbm_surface_h surface)
161 {
162     int i;
163
164     surface = (struct _tbm_surface *)surface;
165
166     for (i = 0; i < surface->num_bos; i++)
167     {
168         tbm_bo_unref (surface->bos[i]);
169         surface->bos[i] = NULL;
170     }
171
172     LIST_DEL (&surface->item_link);
173
174     free (surface);
175     surface = NULL;
176
177     if(LIST_IS_EMPTY (&g_surface_list))
178     {
179         _deinit_surface_bufmgr ();
180         LIST_DELINIT (&g_surface_list);
181     }
182
183 }
184
185
186 int
187 tbm_surface_internal_query_supported_formats (uint32_t **formats, uint32_t *num)
188 {
189     struct _tbm_bufmgr *mgr;
190     int ret = 0;
191
192     _tbm_surface_mutex_lock();
193
194     if (!g_surface_bufmgr)
195     {
196         _init_surface_bufmgr();
197         LIST_INITHEAD (&g_surface_list);
198     }
199
200     mgr = g_surface_bufmgr;
201
202     if (!mgr->backend->surface_supported_format)
203     {
204         _tbm_surface_mutex_unlock();
205         return 0;
206     }
207
208     ret = mgr->backend->surface_supported_format (formats, num);
209
210     _tbm_surface_mutex_unlock();
211
212     return ret;
213 }
214
215
216 int tbm_surface_internal_get_num_planes (tbm_format format)
217 {
218     int num_planes = 0;
219
220     switch (format)
221     {
222         case TBM_FORMAT_C8:
223         case TBM_FORMAT_RGB332:
224         case TBM_FORMAT_BGR233:
225         case TBM_FORMAT_XRGB4444:
226         case TBM_FORMAT_XBGR4444:
227         case TBM_FORMAT_RGBX4444:
228         case TBM_FORMAT_BGRX4444:
229         case TBM_FORMAT_ARGB4444:
230         case TBM_FORMAT_ABGR4444:
231         case TBM_FORMAT_RGBA4444:
232         case TBM_FORMAT_BGRA4444:
233         case TBM_FORMAT_XRGB1555:
234         case TBM_FORMAT_XBGR1555:
235         case TBM_FORMAT_RGBX5551:
236         case TBM_FORMAT_BGRX5551:
237         case TBM_FORMAT_ARGB1555:
238         case TBM_FORMAT_ABGR1555:
239         case TBM_FORMAT_RGBA5551:
240         case TBM_FORMAT_BGRA5551:
241         case TBM_FORMAT_RGB565:
242         case TBM_FORMAT_BGR565:
243         case TBM_FORMAT_RGB888:
244         case TBM_FORMAT_BGR888:
245         case TBM_FORMAT_XRGB8888:
246         case TBM_FORMAT_XBGR8888:
247         case TBM_FORMAT_RGBX8888:
248         case TBM_FORMAT_BGRX8888:
249         case TBM_FORMAT_ARGB8888:
250         case TBM_FORMAT_ABGR8888:
251         case TBM_FORMAT_RGBA8888:
252         case TBM_FORMAT_BGRA8888:
253         case TBM_FORMAT_XRGB2101010:
254         case TBM_FORMAT_XBGR2101010:
255         case TBM_FORMAT_RGBX1010102:
256         case TBM_FORMAT_BGRX1010102:
257         case TBM_FORMAT_ARGB2101010:
258         case TBM_FORMAT_ABGR2101010:
259         case TBM_FORMAT_RGBA1010102:
260         case TBM_FORMAT_BGRA1010102:
261         case TBM_FORMAT_YUYV:
262         case TBM_FORMAT_YVYU:
263         case TBM_FORMAT_UYVY:
264         case TBM_FORMAT_VYUY:
265         case TBM_FORMAT_AYUV:
266             num_planes = 1;
267             break;
268         case TBM_FORMAT_NV12:
269         case TBM_FORMAT_NV21:
270         case TBM_FORMAT_NV16:
271         case TBM_FORMAT_NV61:
272             num_planes = 2;
273             break;
274         case TBM_FORMAT_YUV410:
275         case TBM_FORMAT_YVU410:
276         case TBM_FORMAT_YUV411:
277         case TBM_FORMAT_YVU411:
278         case TBM_FORMAT_YUV420:
279         case TBM_FORMAT_YVU420:
280         case TBM_FORMAT_YUV422:
281         case TBM_FORMAT_YVU422:
282         case TBM_FORMAT_YUV444:
283         case TBM_FORMAT_YVU444:
284             num_planes = 3;
285             break;
286
287         default :
288             break;
289     }
290
291     return num_planes;
292 }
293
294 int tbm_surface_internal_get_bpp (tbm_format format)
295 {
296     int bpp = 0;
297
298     switch (format)
299     {
300         case TBM_FORMAT_C8:
301         case TBM_FORMAT_RGB332:
302         case TBM_FORMAT_BGR233:
303             bpp = 8;
304             break;
305         case TBM_FORMAT_XRGB4444:
306         case TBM_FORMAT_XBGR4444:
307         case TBM_FORMAT_RGBX4444:
308         case TBM_FORMAT_BGRX4444:
309         case TBM_FORMAT_ARGB4444:
310         case TBM_FORMAT_ABGR4444:
311         case TBM_FORMAT_RGBA4444:
312         case TBM_FORMAT_BGRA4444:
313         case TBM_FORMAT_XRGB1555:
314         case TBM_FORMAT_XBGR1555:
315         case TBM_FORMAT_RGBX5551:
316         case TBM_FORMAT_BGRX5551:
317         case TBM_FORMAT_ARGB1555:
318         case TBM_FORMAT_ABGR1555:
319         case TBM_FORMAT_RGBA5551:
320         case TBM_FORMAT_BGRA5551:
321         case TBM_FORMAT_RGB565:
322         case TBM_FORMAT_BGR565:
323             bpp = 16;
324             break;
325         case TBM_FORMAT_RGB888:
326         case TBM_FORMAT_BGR888:
327             bpp = 24;
328             break;
329         case TBM_FORMAT_XRGB8888:
330         case TBM_FORMAT_XBGR8888:
331         case TBM_FORMAT_RGBX8888:
332         case TBM_FORMAT_BGRX8888:
333         case TBM_FORMAT_ARGB8888:
334         case TBM_FORMAT_ABGR8888:
335         case TBM_FORMAT_RGBA8888:
336         case TBM_FORMAT_BGRA8888:
337         case TBM_FORMAT_XRGB2101010:
338         case TBM_FORMAT_XBGR2101010:
339         case TBM_FORMAT_RGBX1010102:
340         case TBM_FORMAT_BGRX1010102:
341         case TBM_FORMAT_ARGB2101010:
342         case TBM_FORMAT_ABGR2101010:
343         case TBM_FORMAT_RGBA1010102:
344         case TBM_FORMAT_BGRA1010102:
345         case TBM_FORMAT_YUYV:
346         case TBM_FORMAT_YVYU:
347         case TBM_FORMAT_UYVY:
348         case TBM_FORMAT_VYUY:
349         case TBM_FORMAT_AYUV:
350             bpp = 32;
351             break;
352         case TBM_FORMAT_NV12:
353         case TBM_FORMAT_NV21:
354             bpp = 12;
355             break;
356         case TBM_FORMAT_NV16:
357         case TBM_FORMAT_NV61:
358             bpp = 16;
359             break;
360         case TBM_FORMAT_YUV410:
361         case TBM_FORMAT_YVU410:
362             bpp = 9;
363             break;
364         case TBM_FORMAT_YUV411:
365         case TBM_FORMAT_YVU411:
366         case TBM_FORMAT_YUV420:
367         case TBM_FORMAT_YVU420:
368             bpp = 12;
369             break;
370         case TBM_FORMAT_YUV422:
371         case TBM_FORMAT_YVU422:
372             bpp = 16;
373             break;
374         case TBM_FORMAT_YUV444:
375         case TBM_FORMAT_YVU444:
376             bpp = 24;
377             break;
378         default :
379             break;
380     }
381
382     return bpp;
383 }
384
385 tbm_surface_h
386 tbm_surface_internal_create_with_flags (int width, int height, int format, int flags)
387 {
388     TBM_RETURN_VAL_IF_FAIL (width > 0, NULL);
389     TBM_RETURN_VAL_IF_FAIL (height > 0, NULL);
390
391     struct _tbm_bufmgr *mgr;
392     struct _tbm_surface *surf = NULL;
393     uint32_t size = 0;
394     uint32_t offset = 0;
395     uint32_t stride = 0;
396     uint32_t bo_size = 0;
397     int bo_idx;
398     int i, j;
399
400     _tbm_surface_mutex_lock();
401
402     if (!g_surface_bufmgr)
403     {
404         _init_surface_bufmgr();
405         LIST_INITHEAD (&g_surface_list);
406     }
407
408     mgr = g_surface_bufmgr;
409     if (!TBM_BUFMGR_IS_VALID(mgr))
410     {
411         _tbm_surface_mutex_unlock();
412         return NULL;
413     }
414     surf = calloc (1, sizeof(struct _tbm_surface));
415     if (!surf)
416     {
417         _tbm_surface_mutex_unlock();
418         return NULL;
419     }
420
421     surf->bufmgr = mgr;
422     surf->info.width = width;
423     surf->info.height = height;
424     surf->info.format = format;
425     surf->info.bpp = tbm_surface_internal_get_bpp (format);
426     surf->info.size = _tbm_surface_internal_query_size (surf);
427     surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
428     surf->num_bos = _tbm_surface_internal_query_num_bos(format);
429     surf->refcnt = 1;
430
431     /* get size, stride and offset bo_idx*/
432     for (i = 0; i < surf->info.num_planes; i++)
433     {
434         _tbm_surface_internal_query_plane_data (surf, i, &size, &offset, &stride, &bo_idx);
435         surf->info.planes[i].size = size;
436         surf->info.planes[i].offset = offset;
437         surf->info.planes[i].stride = stride;
438         surf->planes_bo_idx[i] = bo_idx;
439     }
440
441     surf->flags = flags;
442
443     for (i = 0; i < surf->num_bos; i++)
444     {
445         bo_size = 0;
446         for (j = 0; j < surf->info.num_planes; j++)
447         {
448             if (surf->planes_bo_idx[i] == i)
449                 bo_size += surf->info.planes[i].size;
450         }
451
452         surf->bos[i] = tbm_bo_alloc (mgr, bo_size, flags);
453         if (!surf->bos[i]) {
454             for (j = 0; j < i; j++)
455                 tbm_bo_unref (surf->bos[j]);
456
457             free (surf);
458             surf = NULL;
459
460             if(LIST_IS_EMPTY (&g_surface_list))
461             {
462                 _deinit_surface_bufmgr ();
463                 LIST_DELINIT (&g_surface_list);
464             }
465
466             _tbm_surface_mutex_unlock();
467             return NULL;
468         }
469     }
470
471     LIST_ADD (&surf->item_link, &g_surface_list);
472
473     _tbm_surface_mutex_unlock();
474
475     return surf;
476 }
477
478 tbm_surface_h
479 tbm_surface_internal_create_with_bos (tbm_surface_info_s *info, tbm_bo *bos, int num)
480 {
481     TBM_RETURN_VAL_IF_FAIL (bos, NULL);
482     TBM_RETURN_VAL_IF_FAIL (info, NULL);
483
484     struct _tbm_bufmgr *mgr;
485     struct _tbm_surface *surf = NULL;
486     int i;
487
488     _tbm_surface_mutex_lock();
489
490     if (!g_surface_bufmgr)
491     {
492         _init_surface_bufmgr();
493         LIST_INITHEAD (&g_surface_list);
494     }
495
496     mgr = g_surface_bufmgr;
497     if (!TBM_BUFMGR_IS_VALID(mgr))
498     {
499         _tbm_surface_mutex_unlock();
500         return NULL;
501     }
502     surf = calloc (1, sizeof(struct _tbm_surface));
503     if (!surf)
504     {
505         _tbm_surface_mutex_unlock();
506         return NULL;
507     }
508
509     surf->bufmgr = mgr;
510     surf->info.width = info->width;
511     surf->info.height = info->height;
512     surf->info.format = info->format;
513     surf->info.bpp = info->bpp;
514     surf->info.num_planes = info->num_planes;
515     surf->refcnt = 1;
516
517     /* get size, stride and offset */
518     for (i = 0; i < info->num_planes; i++)
519     {
520         surf->info.planes[i].offset = info->planes[i].offset;
521         surf->info.planes[i].stride = info->planes[i].stride;
522
523         if (info->planes[i].size > 0)
524             surf->info.planes[i].size = info->planes[i].size;
525         else
526             surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
527     }
528
529     if (info->size > 0)
530     {
531         surf->info.size = info->size;
532     }
533     else
534     {
535         surf->info.size = 0;
536         for (i = 0; i < info->num_planes; i++)
537         {
538             surf->info.size += surf->info.planes[i].size;
539         }
540     }
541
542     surf->flags = TBM_BO_DEFAULT;
543
544     /* create only one bo */
545     surf->num_bos = num;
546     for (i = 0; i < num; i++)
547     {
548         if (bos[i] == NULL)
549             goto bail1;
550
551         surf->bos[i] = tbm_bo_ref(bos[i]);
552     }
553
554     LIST_ADD (&surf->item_link, &g_surface_list);
555
556     _tbm_surface_mutex_unlock();
557
558     return surf;
559 bail1:
560     for (i = 0; i < num; i++)
561     {
562         if (surf->bos[i])
563         {
564             tbm_bo_unref (surf->bos[i]);
565             surf->bos[i] = NULL;
566         }
567     }
568
569     free (surf);
570     surf = NULL;
571
572     if(LIST_IS_EMPTY (&g_surface_list))
573     {
574         _deinit_surface_bufmgr ();
575         LIST_DELINIT (&g_surface_list);
576     }
577
578     _tbm_surface_mutex_unlock();
579
580     return NULL;
581 }
582
583
584 void
585 tbm_surface_internal_destroy (tbm_surface_h surface)
586 {
587     if (!surface)
588         return;
589
590     _tbm_surface_mutex_lock();
591
592     surface->refcnt--;
593
594     if (surface->refcnt > 0) {
595         _tbm_surface_mutex_unlock();
596         return;
597     }
598
599     if (surface->refcnt == 0)
600         _tbm_surface_internal_destroy(surface);
601
602     _tbm_surface_mutex_unlock();
603 }
604
605
606 void
607 tbm_surface_internal_ref (tbm_surface_h surface)
608 {
609     TBM_RETURN_IF_FAIL (surface);
610
611     _tbm_surface_mutex_lock();
612
613     surface->refcnt++;
614
615     _tbm_surface_mutex_unlock();
616 }
617
618 void
619 tbm_surface_internal_unref (tbm_surface_h surface)
620 {
621     TBM_RETURN_IF_FAIL (surface);
622
623     _tbm_surface_mutex_lock();
624
625     surface->refcnt--;
626
627     if (surface->refcnt > 0) {
628         _tbm_surface_mutex_unlock();
629         return;
630     }
631
632     if (surface->refcnt == 0)
633         _tbm_surface_internal_destroy(surface);
634
635     _tbm_surface_mutex_unlock();
636 }
637
638 int
639 tbm_surface_internal_get_num_bos (tbm_surface_h surface)
640 {
641     TBM_RETURN_VAL_IF_FAIL (surface, 0);
642
643     struct _tbm_surface *surf;
644     int num;
645
646     _tbm_surface_mutex_lock();
647
648     surf = (struct _tbm_surface *) surface;
649     num = surf->num_bos;
650
651     _tbm_surface_mutex_unlock();
652
653     return num;
654 }
655
656 tbm_bo
657 tbm_surface_internal_get_bo (tbm_surface_h surface, int bo_idx)
658 {
659     TBM_RETURN_VAL_IF_FAIL (surface, NULL);
660     TBM_RETURN_VAL_IF_FAIL (bo_idx > -1, NULL);
661
662     struct _tbm_surface *surf;
663     tbm_bo bo;
664
665     _tbm_surface_mutex_lock();
666
667     surf = (struct _tbm_surface *) surface;
668     bo = surf->bos[bo_idx];
669
670     _tbm_surface_mutex_unlock();
671
672     return bo;
673 }
674
675 int
676 tbm_surface_internal_get_size (tbm_surface_h surface)
677 {
678     TBM_RETURN_VAL_IF_FAIL (surface, 0);
679
680     struct _tbm_surface *surf;
681     unsigned int size;
682
683     _tbm_surface_mutex_lock();
684
685     surf = (struct _tbm_surface *) surface;
686     size = surf->info.size;
687
688     _tbm_surface_mutex_unlock();
689
690     return size;
691 }
692
693 int
694 tbm_surface_internal_get_plane_data (tbm_surface_h surface, int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch)
695 {
696     TBM_RETURN_VAL_IF_FAIL (surface, 0);
697     TBM_RETURN_VAL_IF_FAIL (plane_idx > -1, 0);
698
699     struct _tbm_surface *surf;
700
701     _tbm_surface_mutex_lock();
702
703     surf = (struct _tbm_surface *) surface;
704
705     if (plane_idx >= surf->info.num_planes)
706     {
707         _tbm_surface_mutex_unlock();
708         return 0;
709     }
710
711     *size = surf->info.planes[plane_idx].size;
712     *offset = surf->info.planes[plane_idx].offset;
713     *pitch = surf->info.planes[plane_idx].stride;
714
715     _tbm_surface_mutex_unlock();
716
717     return 1;
718 }
719
720 int
721 tbm_surface_internal_get_info (tbm_surface_h surface, int opt, tbm_surface_info_s *info, int map)
722 {
723     struct _tbm_surface *surf;
724     tbm_bo_handle bo_handles[4];
725     int i, j;
726
727     _tbm_surface_mutex_lock();
728
729     memset (bo_handles, 0, sizeof(tbm_bo_handle) * 4);
730
731     surf = (struct _tbm_surface *)surface;
732
733     info->width = surf->info.width;
734     info->height = surf->info.height;
735     info->format = surf->info.format;
736     info->bpp = surf->info.bpp;
737     info->size = surf->info.size;
738     info->num_planes = surf->info.num_planes;
739
740     if (map == 1)
741     {
742         for (i = 0; i < surf->num_bos; i++)
743         {
744             bo_handles[i] = tbm_bo_map (surf->bos[i], TBM_DEVICE_CPU, opt);
745             if (bo_handles[i].ptr == NULL)
746             {
747                 for (j = 0; j < i; j++)
748                     tbm_bo_unmap (surf->bos[j]);
749
750                 _tbm_surface_mutex_unlock();
751                 return 0;
752             }
753         }
754     }
755     else
756     {
757         for (i = 0; i < surf->num_bos; i++)
758         {
759             bo_handles[i] = tbm_bo_get_handle (surf->bos[i], TBM_DEVICE_CPU);
760             if (bo_handles[i].ptr == NULL)
761             {
762                 _tbm_surface_mutex_unlock();
763                 return 0;
764             }
765         }
766     }
767
768     for (i = 0; i < surf->info.num_planes; i++)
769     {
770         info->planes[i].size = surf->info.planes[i].size;
771         info->planes[i].offset = surf->info.planes[i].offset;
772         info->planes[i].stride = surf->info.planes[i].stride;
773         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr + surf->info.planes[i].offset;
774     }
775
776     _tbm_surface_mutex_unlock();
777
778     return 1;
779 }
780
781 void
782 tbm_surface_internal_unmap (tbm_surface_h surface)
783 {
784     struct _tbm_surface *surf;
785     int i;
786
787     _tbm_surface_mutex_lock();
788
789     surf = (struct _tbm_surface *)surface;
790
791     for (i = 0; i < surf->num_bos; i++)
792         tbm_bo_unmap (surf->bos[i]);
793
794     _tbm_surface_mutex_unlock();
795 }
796
797 unsigned int
798 tbm_surface_internal_get_width (tbm_surface_h surface)
799 {
800     struct _tbm_surface *surf;
801     unsigned int width;
802
803     _tbm_surface_mutex_lock();
804
805     surf = (struct _tbm_surface *)surface;
806     width = surf->info.width;
807
808     _tbm_surface_mutex_unlock();
809
810     return width;
811 }
812
813 unsigned int
814 tbm_surface_internal_get_height (tbm_surface_h surface)
815 {
816     struct _tbm_surface *surf;
817     unsigned int height;
818
819     _tbm_surface_mutex_lock();
820
821     surf = (struct _tbm_surface *)surface;
822     height = surf->info.height;
823
824     _tbm_surface_mutex_unlock();
825
826     return height;
827
828 }
829
830 tbm_format
831 tbm_surface_internal_get_format (tbm_surface_h surface)
832 {
833     struct _tbm_surface *surf;
834     tbm_format format;
835
836     _tbm_surface_mutex_lock();
837
838     surf = (struct _tbm_surface *)surface;
839     format = surf->info.format;
840
841     _tbm_surface_mutex_unlock();
842
843     return format;
844 }
845
846 int
847 tbm_surface_internal_get_plane_bo_idx (tbm_surface_h surface, int plane_idx)
848 {
849     TBM_RETURN_VAL_IF_FAIL (surface, 0);
850     TBM_RETURN_VAL_IF_FAIL (plane_idx > -1, 0);
851     struct _tbm_surface *surf;
852     int bo_idx;
853
854     _tbm_surface_mutex_lock();
855
856     surf = (struct _tbm_surface *)surface;
857     bo_idx = surf->planes_bo_idx[plane_idx];
858
859     _tbm_surface_mutex_unlock();
860
861     return bo_idx;
862 }
863