Fix bug of surface that has multiple bo
[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     for (i = 0; i < surface->num_bos; i++)
165     {
166         tbm_bo_unref (surface->bos[i]);
167         surface->bos[i] = NULL;
168     }
169
170     LIST_DEL (&surface->item_link);
171
172     free (surface);
173     surface = NULL;
174
175     if(LIST_IS_EMPTY (&g_surface_list))
176     {
177         _deinit_surface_bufmgr ();
178         LIST_DELINIT (&g_surface_list);
179     }
180
181 }
182
183
184 int
185 tbm_surface_internal_query_supported_formats (uint32_t **formats, uint32_t *num)
186 {
187     struct _tbm_bufmgr *mgr;
188     int ret = 0;
189
190     _tbm_surface_mutex_lock();
191
192     if (!g_surface_bufmgr)
193     {
194         _init_surface_bufmgr();
195         LIST_INITHEAD (&g_surface_list);
196     }
197
198     mgr = g_surface_bufmgr;
199
200     if (!mgr->backend->surface_supported_format)
201     {
202         _tbm_surface_mutex_unlock();
203         return 0;
204     }
205
206     ret = mgr->backend->surface_supported_format (formats, num);
207
208     _tbm_surface_mutex_unlock();
209
210     return ret;
211 }
212
213
214 int tbm_surface_internal_get_num_planes (tbm_format format)
215 {
216     int num_planes = 0;
217
218     switch (format)
219     {
220         case TBM_FORMAT_C8:
221         case TBM_FORMAT_RGB332:
222         case TBM_FORMAT_BGR233:
223         case TBM_FORMAT_XRGB4444:
224         case TBM_FORMAT_XBGR4444:
225         case TBM_FORMAT_RGBX4444:
226         case TBM_FORMAT_BGRX4444:
227         case TBM_FORMAT_ARGB4444:
228         case TBM_FORMAT_ABGR4444:
229         case TBM_FORMAT_RGBA4444:
230         case TBM_FORMAT_BGRA4444:
231         case TBM_FORMAT_XRGB1555:
232         case TBM_FORMAT_XBGR1555:
233         case TBM_FORMAT_RGBX5551:
234         case TBM_FORMAT_BGRX5551:
235         case TBM_FORMAT_ARGB1555:
236         case TBM_FORMAT_ABGR1555:
237         case TBM_FORMAT_RGBA5551:
238         case TBM_FORMAT_BGRA5551:
239         case TBM_FORMAT_RGB565:
240         case TBM_FORMAT_BGR565:
241         case TBM_FORMAT_RGB888:
242         case TBM_FORMAT_BGR888:
243         case TBM_FORMAT_XRGB8888:
244         case TBM_FORMAT_XBGR8888:
245         case TBM_FORMAT_RGBX8888:
246         case TBM_FORMAT_BGRX8888:
247         case TBM_FORMAT_ARGB8888:
248         case TBM_FORMAT_ABGR8888:
249         case TBM_FORMAT_RGBA8888:
250         case TBM_FORMAT_BGRA8888:
251         case TBM_FORMAT_XRGB2101010:
252         case TBM_FORMAT_XBGR2101010:
253         case TBM_FORMAT_RGBX1010102:
254         case TBM_FORMAT_BGRX1010102:
255         case TBM_FORMAT_ARGB2101010:
256         case TBM_FORMAT_ABGR2101010:
257         case TBM_FORMAT_RGBA1010102:
258         case TBM_FORMAT_BGRA1010102:
259         case TBM_FORMAT_YUYV:
260         case TBM_FORMAT_YVYU:
261         case TBM_FORMAT_UYVY:
262         case TBM_FORMAT_VYUY:
263         case TBM_FORMAT_AYUV:
264             num_planes = 1;
265             break;
266         case TBM_FORMAT_NV12:
267         case TBM_FORMAT_NV21:
268         case TBM_FORMAT_NV16:
269         case TBM_FORMAT_NV61:
270             num_planes = 2;
271             break;
272         case TBM_FORMAT_YUV410:
273         case TBM_FORMAT_YVU410:
274         case TBM_FORMAT_YUV411:
275         case TBM_FORMAT_YVU411:
276         case TBM_FORMAT_YUV420:
277         case TBM_FORMAT_YVU420:
278         case TBM_FORMAT_YUV422:
279         case TBM_FORMAT_YVU422:
280         case TBM_FORMAT_YUV444:
281         case TBM_FORMAT_YVU444:
282             num_planes = 3;
283             break;
284
285         default :
286             break;
287     }
288
289     return num_planes;
290 }
291
292 int tbm_surface_internal_get_bpp (tbm_format format)
293 {
294     int bpp = 0;
295
296     switch (format)
297     {
298         case TBM_FORMAT_C8:
299         case TBM_FORMAT_RGB332:
300         case TBM_FORMAT_BGR233:
301             bpp = 8;
302             break;
303         case TBM_FORMAT_XRGB4444:
304         case TBM_FORMAT_XBGR4444:
305         case TBM_FORMAT_RGBX4444:
306         case TBM_FORMAT_BGRX4444:
307         case TBM_FORMAT_ARGB4444:
308         case TBM_FORMAT_ABGR4444:
309         case TBM_FORMAT_RGBA4444:
310         case TBM_FORMAT_BGRA4444:
311         case TBM_FORMAT_XRGB1555:
312         case TBM_FORMAT_XBGR1555:
313         case TBM_FORMAT_RGBX5551:
314         case TBM_FORMAT_BGRX5551:
315         case TBM_FORMAT_ARGB1555:
316         case TBM_FORMAT_ABGR1555:
317         case TBM_FORMAT_RGBA5551:
318         case TBM_FORMAT_BGRA5551:
319         case TBM_FORMAT_RGB565:
320         case TBM_FORMAT_BGR565:
321             bpp = 16;
322             break;
323         case TBM_FORMAT_RGB888:
324         case TBM_FORMAT_BGR888:
325             bpp = 24;
326             break;
327         case TBM_FORMAT_XRGB8888:
328         case TBM_FORMAT_XBGR8888:
329         case TBM_FORMAT_RGBX8888:
330         case TBM_FORMAT_BGRX8888:
331         case TBM_FORMAT_ARGB8888:
332         case TBM_FORMAT_ABGR8888:
333         case TBM_FORMAT_RGBA8888:
334         case TBM_FORMAT_BGRA8888:
335         case TBM_FORMAT_XRGB2101010:
336         case TBM_FORMAT_XBGR2101010:
337         case TBM_FORMAT_RGBX1010102:
338         case TBM_FORMAT_BGRX1010102:
339         case TBM_FORMAT_ARGB2101010:
340         case TBM_FORMAT_ABGR2101010:
341         case TBM_FORMAT_RGBA1010102:
342         case TBM_FORMAT_BGRA1010102:
343         case TBM_FORMAT_YUYV:
344         case TBM_FORMAT_YVYU:
345         case TBM_FORMAT_UYVY:
346         case TBM_FORMAT_VYUY:
347         case TBM_FORMAT_AYUV:
348             bpp = 32;
349             break;
350         case TBM_FORMAT_NV12:
351         case TBM_FORMAT_NV21:
352             bpp = 12;
353             break;
354         case TBM_FORMAT_NV16:
355         case TBM_FORMAT_NV61:
356             bpp = 16;
357             break;
358         case TBM_FORMAT_YUV410:
359         case TBM_FORMAT_YVU410:
360             bpp = 9;
361             break;
362         case TBM_FORMAT_YUV411:
363         case TBM_FORMAT_YVU411:
364         case TBM_FORMAT_YUV420:
365         case TBM_FORMAT_YVU420:
366             bpp = 12;
367             break;
368         case TBM_FORMAT_YUV422:
369         case TBM_FORMAT_YVU422:
370             bpp = 16;
371             break;
372         case TBM_FORMAT_YUV444:
373         case TBM_FORMAT_YVU444:
374             bpp = 24;
375             break;
376         default :
377             break;
378     }
379
380     return bpp;
381 }
382
383 tbm_surface_h
384 tbm_surface_internal_create_with_flags (int width, int height, int format, int flags)
385 {
386     TBM_RETURN_VAL_IF_FAIL (width > 0, NULL);
387     TBM_RETURN_VAL_IF_FAIL (height > 0, NULL);
388
389     struct _tbm_bufmgr *mgr;
390     struct _tbm_surface *surf = NULL;
391     uint32_t size = 0;
392     uint32_t offset = 0;
393     uint32_t stride = 0;
394     uint32_t bo_size = 0;
395     int bo_idx;
396     int i, j;
397
398     _tbm_surface_mutex_lock();
399
400     if (!g_surface_bufmgr)
401     {
402         _init_surface_bufmgr();
403         LIST_INITHEAD (&g_surface_list);
404     }
405
406     mgr = g_surface_bufmgr;
407     if (!TBM_BUFMGR_IS_VALID(mgr))
408     {
409         _tbm_surface_mutex_unlock();
410         return NULL;
411     }
412     surf = calloc (1, sizeof(struct _tbm_surface));
413     if (!surf)
414     {
415         _tbm_surface_mutex_unlock();
416         return NULL;
417     }
418
419     surf->bufmgr = mgr;
420     surf->info.width = width;
421     surf->info.height = height;
422     surf->info.format = format;
423     surf->info.bpp = tbm_surface_internal_get_bpp (format);
424     surf->info.size = _tbm_surface_internal_query_size (surf);
425     surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
426     surf->num_bos = _tbm_surface_internal_query_num_bos(format);
427     surf->refcnt = 1;
428
429     /* get size, stride and offset bo_idx*/
430     for (i = 0; i < surf->info.num_planes; i++)
431     {
432         _tbm_surface_internal_query_plane_data (surf, i, &size, &offset, &stride, &bo_idx);
433         surf->info.planes[i].size = size;
434         surf->info.planes[i].offset = offset;
435         surf->info.planes[i].stride = stride;
436         surf->planes_bo_idx[i] = bo_idx;
437     }
438
439     surf->flags = flags;
440
441     for (i = 0; i < surf->num_bos; i++)
442     {
443         bo_size = 0;
444         for (j = 0; j < surf->info.num_planes; j++)
445         {
446             if (surf->planes_bo_idx[j] == i)
447                 bo_size += surf->info.planes[j].size;
448         }
449         surf->bos[i] = tbm_bo_alloc (mgr, bo_size, flags);
450         if (!surf->bos[i]) {
451             for (j = 0; j < i; j++)
452                 tbm_bo_unref (surf->bos[j]);
453
454             free (surf);
455             surf = NULL;
456
457             if(LIST_IS_EMPTY (&g_surface_list))
458             {
459                 _deinit_surface_bufmgr ();
460                 LIST_DELINIT (&g_surface_list);
461             }
462
463             _tbm_surface_mutex_unlock();
464             return NULL;
465         }
466     }
467
468     LIST_ADD (&surf->item_link, &g_surface_list);
469
470     _tbm_surface_mutex_unlock();
471
472     return surf;
473 }
474
475 tbm_surface_h
476 tbm_surface_internal_create_with_bos (tbm_surface_info_s *info, tbm_bo *bos, int num)
477 {
478     TBM_RETURN_VAL_IF_FAIL (bos, NULL);
479     TBM_RETURN_VAL_IF_FAIL (info, NULL);
480     TBM_RETURN_VAL_IF_FAIL (num == 1 || info->num_planes == num, NULL);
481
482     struct _tbm_bufmgr *mgr;
483     struct _tbm_surface *surf = NULL;
484     int i;
485
486     _tbm_surface_mutex_lock();
487
488     if (!g_surface_bufmgr)
489     {
490         _init_surface_bufmgr();
491         LIST_INITHEAD (&g_surface_list);
492     }
493
494     mgr = g_surface_bufmgr;
495     if (!TBM_BUFMGR_IS_VALID(mgr))
496     {
497         _tbm_surface_mutex_unlock();
498         return NULL;
499     }
500
501     surf = calloc (1, sizeof(struct _tbm_surface));
502     if (!surf)
503     {
504         _tbm_surface_mutex_unlock();
505         return NULL;
506     }
507
508     surf->bufmgr = mgr;
509     surf->info.width = info->width;
510     surf->info.height = info->height;
511     surf->info.format = info->format;
512     surf->info.bpp = info->bpp;
513     surf->info.num_planes = info->num_planes;
514     surf->refcnt = 1;
515
516     /* get size, stride and offset */
517     for (i = 0; i < info->num_planes; i++)
518     {
519         surf->info.planes[i].offset = info->planes[i].offset;
520         surf->info.planes[i].stride = info->planes[i].stride;
521
522         if (info->planes[i].size > 0)
523             surf->info.planes[i].size = info->planes[i].size;
524         else
525             surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
526
527         if (num == 1)
528             surf->planes_bo_idx[i] = 0;
529         else
530             surf->planes_bo_idx[i] = i;
531     }
532
533     if (info->size > 0)
534     {
535         surf->info.size = info->size;
536     }
537     else
538     {
539         surf->info.size = 0;
540         for (i = 0; i < info->num_planes; i++)
541         {
542             surf->info.size += surf->info.planes[i].size;
543         }
544     }
545
546     surf->flags = TBM_BO_DEFAULT;
547
548     /* create only one bo */
549     surf->num_bos = num;
550     for (i = 0; i < num; i++)
551     {
552         if (bos[i] == NULL)
553             goto bail1;
554
555         surf->bos[i] = tbm_bo_ref(bos[i]);
556     }
557
558     LIST_ADD (&surf->item_link, &g_surface_list);
559
560     _tbm_surface_mutex_unlock();
561
562     return surf;
563 bail1:
564     for (i = 0; i < num; i++)
565     {
566         if (surf->bos[i])
567         {
568             tbm_bo_unref (surf->bos[i]);
569             surf->bos[i] = NULL;
570         }
571     }
572
573     free (surf);
574     surf = NULL;
575
576     if(LIST_IS_EMPTY (&g_surface_list))
577     {
578         _deinit_surface_bufmgr ();
579         LIST_DELINIT (&g_surface_list);
580     }
581
582     _tbm_surface_mutex_unlock();
583
584     return NULL;
585 }
586
587
588 void
589 tbm_surface_internal_destroy (tbm_surface_h surface)
590 {
591     if (!surface)
592         return;
593
594     _tbm_surface_mutex_lock();
595
596     surface->refcnt--;
597
598     if (surface->refcnt > 0) {
599         _tbm_surface_mutex_unlock();
600         return;
601     }
602
603     if (surface->refcnt == 0)
604         _tbm_surface_internal_destroy(surface);
605
606     _tbm_surface_mutex_unlock();
607 }
608
609
610 void
611 tbm_surface_internal_ref (tbm_surface_h surface)
612 {
613     TBM_RETURN_IF_FAIL (surface);
614
615     _tbm_surface_mutex_lock();
616
617     surface->refcnt++;
618
619     _tbm_surface_mutex_unlock();
620 }
621
622 void
623 tbm_surface_internal_unref (tbm_surface_h surface)
624 {
625     TBM_RETURN_IF_FAIL (surface);
626
627     _tbm_surface_mutex_lock();
628
629     surface->refcnt--;
630
631     if (surface->refcnt > 0) {
632         _tbm_surface_mutex_unlock();
633         return;
634     }
635
636     if (surface->refcnt == 0)
637         _tbm_surface_internal_destroy(surface);
638
639     _tbm_surface_mutex_unlock();
640 }
641
642 int
643 tbm_surface_internal_get_num_bos (tbm_surface_h surface)
644 {
645     TBM_RETURN_VAL_IF_FAIL (surface, 0);
646
647     struct _tbm_surface *surf;
648     int num;
649
650     _tbm_surface_mutex_lock();
651
652     surf = (struct _tbm_surface *) surface;
653     num = surf->num_bos;
654
655     _tbm_surface_mutex_unlock();
656
657     return num;
658 }
659
660 tbm_bo
661 tbm_surface_internal_get_bo (tbm_surface_h surface, int bo_idx)
662 {
663     TBM_RETURN_VAL_IF_FAIL (surface, NULL);
664     TBM_RETURN_VAL_IF_FAIL (bo_idx > -1, NULL);
665
666     struct _tbm_surface *surf;
667     tbm_bo bo;
668
669     _tbm_surface_mutex_lock();
670
671     surf = (struct _tbm_surface *) surface;
672     bo = surf->bos[bo_idx];
673
674     _tbm_surface_mutex_unlock();
675
676     return bo;
677 }
678
679 int
680 tbm_surface_internal_get_size (tbm_surface_h surface)
681 {
682     TBM_RETURN_VAL_IF_FAIL (surface, 0);
683
684     struct _tbm_surface *surf;
685     unsigned int size;
686
687     _tbm_surface_mutex_lock();
688
689     surf = (struct _tbm_surface *) surface;
690     size = surf->info.size;
691
692     _tbm_surface_mutex_unlock();
693
694     return size;
695 }
696
697 int
698 tbm_surface_internal_get_plane_data (tbm_surface_h surface, int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch)
699 {
700     TBM_RETURN_VAL_IF_FAIL (surface, 0);
701     TBM_RETURN_VAL_IF_FAIL (plane_idx > -1, 0);
702
703     struct _tbm_surface *surf;
704
705     _tbm_surface_mutex_lock();
706
707     surf = (struct _tbm_surface *) surface;
708
709     if (plane_idx >= surf->info.num_planes)
710     {
711         _tbm_surface_mutex_unlock();
712         return 0;
713     }
714
715     *size = surf->info.planes[plane_idx].size;
716     *offset = surf->info.planes[plane_idx].offset;
717     *pitch = surf->info.planes[plane_idx].stride;
718
719     _tbm_surface_mutex_unlock();
720
721     return 1;
722 }
723
724 int
725 tbm_surface_internal_get_info (tbm_surface_h surface, int opt, tbm_surface_info_s *info, int map)
726 {
727     struct _tbm_surface *surf;
728     tbm_bo_handle bo_handles[4];
729     int i, j;
730
731     _tbm_surface_mutex_lock();
732
733     memset (bo_handles, 0, sizeof(tbm_bo_handle) * 4);
734
735     surf = (struct _tbm_surface *)surface;
736
737     info->width = surf->info.width;
738     info->height = surf->info.height;
739     info->format = surf->info.format;
740     info->bpp = surf->info.bpp;
741     info->size = surf->info.size;
742     info->num_planes = surf->info.num_planes;
743
744     if (map == 1)
745     {
746         for (i = 0; i < surf->num_bos; i++)
747         {
748             bo_handles[i] = tbm_bo_map (surf->bos[i], TBM_DEVICE_CPU, opt);
749             if (bo_handles[i].ptr == NULL)
750             {
751                 for (j = 0; j < i; j++)
752                     tbm_bo_unmap (surf->bos[j]);
753
754                 _tbm_surface_mutex_unlock();
755                 return 0;
756             }
757         }
758     }
759     else
760     {
761         for (i = 0; i < surf->num_bos; i++)
762         {
763             bo_handles[i] = tbm_bo_get_handle (surf->bos[i], TBM_DEVICE_CPU);
764             if (bo_handles[i].ptr == NULL)
765             {
766                 _tbm_surface_mutex_unlock();
767                 return 0;
768             }
769         }
770     }
771
772     for (i = 0; i < surf->info.num_planes; i++)
773     {
774         info->planes[i].size = surf->info.planes[i].size;
775         info->planes[i].offset = surf->info.planes[i].offset;
776         info->planes[i].stride = surf->info.planes[i].stride;
777         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr + surf->info.planes[i].offset;
778     }
779
780     _tbm_surface_mutex_unlock();
781
782     return 1;
783 }
784
785 void
786 tbm_surface_internal_unmap (tbm_surface_h surface)
787 {
788     struct _tbm_surface *surf;
789     int i;
790
791     _tbm_surface_mutex_lock();
792
793     surf = (struct _tbm_surface *)surface;
794
795     for (i = 0; i < surf->num_bos; i++)
796         tbm_bo_unmap (surf->bos[i]);
797
798     _tbm_surface_mutex_unlock();
799 }
800
801 unsigned int
802 tbm_surface_internal_get_width (tbm_surface_h surface)
803 {
804     struct _tbm_surface *surf;
805     unsigned int width;
806
807     _tbm_surface_mutex_lock();
808
809     surf = (struct _tbm_surface *)surface;
810     width = surf->info.width;
811
812     _tbm_surface_mutex_unlock();
813
814     return width;
815 }
816
817 unsigned int
818 tbm_surface_internal_get_height (tbm_surface_h surface)
819 {
820     struct _tbm_surface *surf;
821     unsigned int height;
822
823     _tbm_surface_mutex_lock();
824
825     surf = (struct _tbm_surface *)surface;
826     height = surf->info.height;
827
828     _tbm_surface_mutex_unlock();
829
830     return height;
831
832 }
833
834 tbm_format
835 tbm_surface_internal_get_format (tbm_surface_h surface)
836 {
837     struct _tbm_surface *surf;
838     tbm_format format;
839
840     _tbm_surface_mutex_lock();
841
842     surf = (struct _tbm_surface *)surface;
843     format = surf->info.format;
844
845     _tbm_surface_mutex_unlock();
846
847     return format;
848 }
849
850 int
851 tbm_surface_internal_get_plane_bo_idx (tbm_surface_h surface, int plane_idx)
852 {
853     TBM_RETURN_VAL_IF_FAIL (surface, 0);
854     TBM_RETURN_VAL_IF_FAIL (plane_idx > -1, 0);
855     struct _tbm_surface *surf;
856     int bo_idx;
857
858     _tbm_surface_mutex_lock();
859
860     surf = (struct _tbm_surface *)surface;
861     bo_idx = surf->planes_bo_idx[plane_idx];
862
863     _tbm_surface_mutex_unlock();
864
865     return bo_idx;
866 }
867