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