Set planes_bo_idx when create_with_bos
[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[i] == i)
447                 bo_size += surf->info.planes[i].size;
448         }
449
450         surf->bos[i] = tbm_bo_alloc (mgr, bo_size, flags);
451         if (!surf->bos[i]) {
452             for (j = 0; j < i; j++)
453                 tbm_bo_unref (surf->bos[j]);
454
455             free (surf);
456             surf = NULL;
457
458             if(LIST_IS_EMPTY (&g_surface_list))
459             {
460                 _deinit_surface_bufmgr ();
461                 LIST_DELINIT (&g_surface_list);
462             }
463
464             _tbm_surface_mutex_unlock();
465             return NULL;
466         }
467     }
468
469     LIST_ADD (&surf->item_link, &g_surface_list);
470
471     _tbm_surface_mutex_unlock();
472
473     return surf;
474 }
475
476 tbm_surface_h
477 tbm_surface_internal_create_with_bos (tbm_surface_info_s *info, tbm_bo *bos, int num)
478 {
479     TBM_RETURN_VAL_IF_FAIL (bos, NULL);
480     TBM_RETURN_VAL_IF_FAIL (info, NULL);
481     TBM_RETURN_VAL_IF_FAIL (num == 1 || info->num_planes == num, NULL);
482
483     struct _tbm_bufmgr *mgr;
484     struct _tbm_surface *surf = NULL;
485     int i;
486
487     _tbm_surface_mutex_lock();
488
489     if (!g_surface_bufmgr)
490     {
491         _init_surface_bufmgr();
492         LIST_INITHEAD (&g_surface_list);
493     }
494
495     mgr = g_surface_bufmgr;
496     if (!TBM_BUFMGR_IS_VALID(mgr))
497     {
498         _tbm_surface_mutex_unlock();
499         return NULL;
500     }
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         if (num == 1)
529             surf->planes_bo_idx[i] = 0;
530         else
531             surf->planes_bo_idx[i] = i;
532     }
533
534     if (info->size > 0)
535     {
536         surf->info.size = info->size;
537     }
538     else
539     {
540         surf->info.size = 0;
541         for (i = 0; i < info->num_planes; i++)
542         {
543             surf->info.size += surf->info.planes[i].size;
544         }
545     }
546
547     surf->flags = TBM_BO_DEFAULT;
548
549     /* create only one bo */
550     surf->num_bos = num;
551     for (i = 0; i < num; i++)
552     {
553         if (bos[i] == NULL)
554             goto bail1;
555
556         surf->bos[i] = tbm_bo_ref(bos[i]);
557     }
558
559     LIST_ADD (&surf->item_link, &g_surface_list);
560
561     _tbm_surface_mutex_unlock();
562
563     return surf;
564 bail1:
565     for (i = 0; i < num; i++)
566     {
567         if (surf->bos[i])
568         {
569             tbm_bo_unref (surf->bos[i]);
570             surf->bos[i] = NULL;
571         }
572     }
573
574     free (surf);
575     surf = NULL;
576
577     if(LIST_IS_EMPTY (&g_surface_list))
578     {
579         _deinit_surface_bufmgr ();
580         LIST_DELINIT (&g_surface_list);
581     }
582
583     _tbm_surface_mutex_unlock();
584
585     return NULL;
586 }
587
588
589 void
590 tbm_surface_internal_destroy (tbm_surface_h surface)
591 {
592     if (!surface)
593         return;
594
595     _tbm_surface_mutex_lock();
596
597     surface->refcnt--;
598
599     if (surface->refcnt > 0) {
600         _tbm_surface_mutex_unlock();
601         return;
602     }
603
604     if (surface->refcnt == 0)
605         _tbm_surface_internal_destroy(surface);
606
607     _tbm_surface_mutex_unlock();
608 }
609
610
611 void
612 tbm_surface_internal_ref (tbm_surface_h surface)
613 {
614     TBM_RETURN_IF_FAIL (surface);
615
616     _tbm_surface_mutex_lock();
617
618     surface->refcnt++;
619
620     _tbm_surface_mutex_unlock();
621 }
622
623 void
624 tbm_surface_internal_unref (tbm_surface_h surface)
625 {
626     TBM_RETURN_IF_FAIL (surface);
627
628     _tbm_surface_mutex_lock();
629
630     surface->refcnt--;
631
632     if (surface->refcnt > 0) {
633         _tbm_surface_mutex_unlock();
634         return;
635     }
636
637     if (surface->refcnt == 0)
638         _tbm_surface_internal_destroy(surface);
639
640     _tbm_surface_mutex_unlock();
641 }
642
643 int
644 tbm_surface_internal_get_num_bos (tbm_surface_h surface)
645 {
646     TBM_RETURN_VAL_IF_FAIL (surface, 0);
647
648     struct _tbm_surface *surf;
649     int num;
650
651     _tbm_surface_mutex_lock();
652
653     surf = (struct _tbm_surface *) surface;
654     num = surf->num_bos;
655
656     _tbm_surface_mutex_unlock();
657
658     return num;
659 }
660
661 tbm_bo
662 tbm_surface_internal_get_bo (tbm_surface_h surface, int bo_idx)
663 {
664     TBM_RETURN_VAL_IF_FAIL (surface, NULL);
665     TBM_RETURN_VAL_IF_FAIL (bo_idx > -1, NULL);
666
667     struct _tbm_surface *surf;
668     tbm_bo bo;
669
670     _tbm_surface_mutex_lock();
671
672     surf = (struct _tbm_surface *) surface;
673     bo = surf->bos[bo_idx];
674
675     _tbm_surface_mutex_unlock();
676
677     return bo;
678 }
679
680 int
681 tbm_surface_internal_get_size (tbm_surface_h surface)
682 {
683     TBM_RETURN_VAL_IF_FAIL (surface, 0);
684
685     struct _tbm_surface *surf;
686     unsigned int size;
687
688     _tbm_surface_mutex_lock();
689
690     surf = (struct _tbm_surface *) surface;
691     size = surf->info.size;
692
693     _tbm_surface_mutex_unlock();
694
695     return size;
696 }
697
698 int
699 tbm_surface_internal_get_plane_data (tbm_surface_h surface, int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch)
700 {
701     TBM_RETURN_VAL_IF_FAIL (surface, 0);
702     TBM_RETURN_VAL_IF_FAIL (plane_idx > -1, 0);
703
704     struct _tbm_surface *surf;
705
706     _tbm_surface_mutex_lock();
707
708     surf = (struct _tbm_surface *) surface;
709
710     if (plane_idx >= surf->info.num_planes)
711     {
712         _tbm_surface_mutex_unlock();
713         return 0;
714     }
715
716     *size = surf->info.planes[plane_idx].size;
717     *offset = surf->info.planes[plane_idx].offset;
718     *pitch = surf->info.planes[plane_idx].stride;
719
720     _tbm_surface_mutex_unlock();
721
722     return 1;
723 }
724
725 int
726 tbm_surface_internal_get_info (tbm_surface_h surface, int opt, tbm_surface_info_s *info, int map)
727 {
728     struct _tbm_surface *surf;
729     tbm_bo_handle bo_handles[4];
730     int i, j;
731
732     _tbm_surface_mutex_lock();
733
734     memset (bo_handles, 0, sizeof(tbm_bo_handle) * 4);
735
736     surf = (struct _tbm_surface *)surface;
737
738     info->width = surf->info.width;
739     info->height = surf->info.height;
740     info->format = surf->info.format;
741     info->bpp = surf->info.bpp;
742     info->size = surf->info.size;
743     info->num_planes = surf->info.num_planes;
744
745     if (map == 1)
746     {
747         for (i = 0; i < surf->num_bos; i++)
748         {
749             bo_handles[i] = tbm_bo_map (surf->bos[i], TBM_DEVICE_CPU, opt);
750             if (bo_handles[i].ptr == NULL)
751             {
752                 for (j = 0; j < i; j++)
753                     tbm_bo_unmap (surf->bos[j]);
754
755                 _tbm_surface_mutex_unlock();
756                 return 0;
757             }
758         }
759     }
760     else
761     {
762         for (i = 0; i < surf->num_bos; i++)
763         {
764             bo_handles[i] = tbm_bo_get_handle (surf->bos[i], TBM_DEVICE_CPU);
765             if (bo_handles[i].ptr == NULL)
766             {
767                 _tbm_surface_mutex_unlock();
768                 return 0;
769             }
770         }
771     }
772
773     for (i = 0; i < surf->info.num_planes; i++)
774     {
775         info->planes[i].size = surf->info.planes[i].size;
776         info->planes[i].offset = surf->info.planes[i].offset;
777         info->planes[i].stride = surf->info.planes[i].stride;
778         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr + surf->info.planes[i].offset;
779     }
780
781     _tbm_surface_mutex_unlock();
782
783     return 1;
784 }
785
786 void
787 tbm_surface_internal_unmap (tbm_surface_h surface)
788 {
789     struct _tbm_surface *surf;
790     int i;
791
792     _tbm_surface_mutex_lock();
793
794     surf = (struct _tbm_surface *)surface;
795
796     for (i = 0; i < surf->num_bos; i++)
797         tbm_bo_unmap (surf->bos[i]);
798
799     _tbm_surface_mutex_unlock();
800 }
801
802 unsigned int
803 tbm_surface_internal_get_width (tbm_surface_h surface)
804 {
805     struct _tbm_surface *surf;
806     unsigned int width;
807
808     _tbm_surface_mutex_lock();
809
810     surf = (struct _tbm_surface *)surface;
811     width = surf->info.width;
812
813     _tbm_surface_mutex_unlock();
814
815     return width;
816 }
817
818 unsigned int
819 tbm_surface_internal_get_height (tbm_surface_h surface)
820 {
821     struct _tbm_surface *surf;
822     unsigned int height;
823
824     _tbm_surface_mutex_lock();
825
826     surf = (struct _tbm_surface *)surface;
827     height = surf->info.height;
828
829     _tbm_surface_mutex_unlock();
830
831     return height;
832
833 }
834
835 tbm_format
836 tbm_surface_internal_get_format (tbm_surface_h surface)
837 {
838     struct _tbm_surface *surf;
839     tbm_format format;
840
841     _tbm_surface_mutex_lock();
842
843     surf = (struct _tbm_surface *)surface;
844     format = surf->info.format;
845
846     _tbm_surface_mutex_unlock();
847
848     return format;
849 }
850
851 int
852 tbm_surface_internal_get_plane_bo_idx (tbm_surface_h surface, int plane_idx)
853 {
854     TBM_RETURN_VAL_IF_FAIL (surface, 0);
855     TBM_RETURN_VAL_IF_FAIL (plane_idx > -1, 0);
856     struct _tbm_surface *surf;
857     int bo_idx;
858
859     _tbm_surface_mutex_lock();
860
861     surf = (struct _tbm_surface *)surface;
862     bo_idx = surf->planes_bo_idx[plane_idx];
863
864     _tbm_surface_mutex_unlock();
865
866     return bo_idx;
867 }
868