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