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