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