Don't use surface get num bos
[platform/core/uifw/libtbm.git] / src / tbm_surface_internal.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #include "config.h"
33 #include "tbm_bufmgr.h"
34 #include "tbm_bufmgr_int.h"
35 #include "tbm_surface_internal.h"
36 #include "list.h"
37
38 static tbm_bufmgr g_surface_bufmgr;
39 static pthread_mutex_t tbm_surface_lock;
40
41 char *
42 _tbm_surface_internal_format_to_str(tbm_format format)
43 {
44         switch (format) {
45         case TBM_FORMAT_C8:
46                 return "TBM_FORMAT_C8";
47         case TBM_FORMAT_RGB332:
48                 return "TBM_FORMAT_RGB332";
49         case TBM_FORMAT_BGR233:
50                 return "TBM_FORMAT_BGR233";
51         case TBM_FORMAT_XRGB4444:
52                 return "TBM_FORMAT_XRGB4444";
53         case TBM_FORMAT_XBGR4444:
54                 return "TBM_FORMAT_XBGR4444";
55         case TBM_FORMAT_RGBX4444:
56                 return "TBM_FORMAT_RGBX4444";
57         case TBM_FORMAT_BGRX4444:
58                 return "TBM_FORMAT_BGRX4444";
59         case TBM_FORMAT_ARGB4444:
60                 return "TBM_FORMAT_ARGB4444";
61         case TBM_FORMAT_ABGR4444:
62                 return "TBM_FORMAT_ABGR4444";
63         case TBM_FORMAT_RGBA4444:
64                 return "TBM_FORMAT_RGBA4444";
65         case TBM_FORMAT_BGRA4444:
66                 return "TBM_FORMAT_BGRA4444";
67         case TBM_FORMAT_XRGB1555:
68                 return "TBM_FORMAT_XRGB1555";
69         case TBM_FORMAT_XBGR1555:
70                 return "TBM_FORMAT_XBGR1555";
71         case TBM_FORMAT_RGBX5551:
72                 return "TBM_FORMAT_RGBX5551";
73         case TBM_FORMAT_BGRX5551:
74                 return "TBM_FORMAT_BGRX5551";
75         case TBM_FORMAT_ARGB1555:
76                 return "TBM_FORMAT_ARGB1555";
77         case TBM_FORMAT_ABGR1555:
78                 return "TBM_FORMAT_ABGR1555";
79         case TBM_FORMAT_RGBA5551:
80                 return "TBM_FORMAT_RGBA5551";
81         case TBM_FORMAT_BGRA5551:
82                 return "TBM_FORMAT_BGRA5551";
83         case TBM_FORMAT_RGB565:
84                 return "TBM_FORMAT_RGB565";
85         case TBM_FORMAT_BGR565:
86                 return "TBM_FORMAT_BGR565";
87         case TBM_FORMAT_RGB888:
88                 return "TBM_FORMAT_RGB888";
89         case TBM_FORMAT_BGR888:
90                 return "TBM_FORMAT_BGR888";
91         case TBM_FORMAT_XRGB8888:
92                 return "TBM_FORMAT_XRGB8888";
93         case TBM_FORMAT_XBGR8888:
94                 return "TBM_FORMAT_XBGR8888";
95         case TBM_FORMAT_RGBX8888:
96                 return "TBM_FORMAT_RGBX8888";
97         case TBM_FORMAT_BGRX8888:
98                 return "TBM_FORMAT_BGRX8888";
99         case TBM_FORMAT_ARGB8888:
100                 return "TBM_FORMAT_ARGB8888";
101         case TBM_FORMAT_ABGR8888:
102                 return "TBM_FORMAT_ABGR8888";
103         case TBM_FORMAT_RGBA8888:
104                 return "TBM_FORMAT_RGBA8888";
105         case TBM_FORMAT_BGRA8888:
106                 return "TBM_FORMAT_BGRA8888";
107         case TBM_FORMAT_XRGB2101010:
108                 return "TBM_FORMAT_XRGB2101010";
109         case TBM_FORMAT_XBGR2101010:
110                 return "TBM_FORMAT_XBGR2101010";
111         case TBM_FORMAT_RGBX1010102:
112                 return "TBM_FORMAT_RGBX1010102";
113         case TBM_FORMAT_BGRX1010102:
114                 return "TBM_FORMAT_BGRX1010102";
115         case TBM_FORMAT_ARGB2101010:
116                 return "TBM_FORMAT_ARGB2101010";
117         case TBM_FORMAT_ABGR2101010:
118                 return "TBM_FORMAT_ABGR2101010";
119         case TBM_FORMAT_RGBA1010102:
120                 return "TBM_FORMAT_RGBA1010102";
121         case TBM_FORMAT_BGRA1010102:
122                 return "TBM_FORMAT_BGRA1010102";
123         case TBM_FORMAT_YUYV:
124                 return "TBM_FORMAT_YUYV";
125         case TBM_FORMAT_YVYU:
126                 return "TBM_FORMAT_YVYU";
127         case TBM_FORMAT_UYVY:
128                 return "TBM_FORMAT_UYVY";
129         case TBM_FORMAT_VYUY:
130                 return "TBM_FORMAT_VYUY";
131         case TBM_FORMAT_AYUV:
132                 return "TBM_FORMAT_AYUV";
133         case TBM_FORMAT_NV12:
134                 return "TBM_FORMAT_NV12";
135         case TBM_FORMAT_NV21:
136                 return "TBM_FORMAT_NV21";
137         case TBM_FORMAT_NV16:
138                 return "TBM_FORMAT_NV16";
139         case TBM_FORMAT_NV61:
140                 return "TBM_FORMAT_NV61";
141         case TBM_FORMAT_YUV410:
142                 return "TBM_FORMAT_YUV410";
143         case TBM_FORMAT_YVU410:
144                 return "TBM_FORMAT_YVU410";
145         case TBM_FORMAT_YUV411:
146                 return "TBM_FORMAT_YUV411";
147         case TBM_FORMAT_YVU411:
148                 return "TBM_FORMAT_YVU411";
149         case TBM_FORMAT_YUV420:
150                 return "TBM_FORMAT_YUV420";
151         case TBM_FORMAT_YVU420:
152                 return "TBM_FORMAT_YVU420";
153         case TBM_FORMAT_YUV422:
154                 return "TBM_FORMAT_YUV422";
155         case TBM_FORMAT_YVU422:
156                 return "TBM_FORMAT_YVU422";
157         case TBM_FORMAT_YUV444:
158                 return "TBM_FORMAT_YUV444";
159         case TBM_FORMAT_YVU444:
160                 return "TBM_FORMAT_YVU444";
161         case TBM_FORMAT_NV12MT:
162                 return "TBM_FORMAT_NV12MT";
163         default:
164                 return "unknwon";
165         }
166 }
167
168 static bool
169 _tbm_surface_mutex_init(void)
170 {
171         static bool tbm_surface_mutex_init = false;
172
173         if (tbm_surface_mutex_init)
174                 return true;
175
176         if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
177                 TBM_LOG("[libtbm] fail: tbm_surface mutex init\n");
178                 return false;
179         }
180
181         tbm_surface_mutex_init = true;
182
183         return true;
184 }
185
186 void
187 _tbm_surface_mutex_lock(void)
188 {
189         if (!_tbm_surface_mutex_init())
190                 return;
191
192         pthread_mutex_lock(&tbm_surface_lock);
193 }
194
195 void
196 _tbm_surface_mutex_unlock(void)
197 {
198         pthread_mutex_unlock(&tbm_surface_lock);
199 }
200
201 static void
202 _init_surface_bufmgr(void)
203 {
204         g_surface_bufmgr = tbm_bufmgr_init(-1);
205 }
206
207 static void
208 _deinit_surface_bufmgr(void)
209 {
210         if (!g_surface_bufmgr)
211                 return;
212
213         tbm_bufmgr_deinit(g_surface_bufmgr);
214         g_surface_bufmgr = NULL;
215 }
216
217 static int
218 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
219                                        int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
220 {
221         TBM_RETURN_VAL_IF_FAIL(surface, 0);
222         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
223
224         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
225         struct _tbm_bufmgr *mgr = surf->bufmgr;
226         int ret = 0;
227
228         TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
229         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
230         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
231         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
232
233         if (!mgr->backend->surface_get_plane_data)
234                 return 0;
235
236         ret = mgr->backend->surface_get_plane_data(surf, surf->info.width,
237                         surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
238         if (!ret)
239                 return 0;
240
241         return 1;
242 }
243
244 static void
245 _tbm_surface_internal_destroy(tbm_surface_h surface)
246 {
247         int i;
248         tbm_bufmgr bufmgr = surface->bufmgr;
249         tbm_user_data *old_data = NULL, *tmp = NULL;
250
251         for (i = 0; i < surface->num_bos; i++) {
252                 surface->bos[i]->surface = NULL;
253
254                 tbm_bo_unref(surface->bos[i]);
255                 surface->bos[i] = NULL;
256         }
257
258         /* destory the user_data_list */
259         if (!LIST_IS_EMPTY(&surface->user_data_list)) {
260                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
261                         TBM_LOG("[tbm_surface:%d] free user_data\n",
262                                 getpid());
263                         user_data_delete(old_data);
264                 }
265         }
266
267         LIST_DEL(&surface->item_link);
268
269         free(surface);
270         surface = NULL;
271
272         if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
273                 LIST_DELINIT(&bufmgr->surf_list);
274                 _deinit_surface_bufmgr();
275         }
276 }
277
278 int
279 tbm_surface_internal_query_supported_formats(uint32_t **formats,
280                 uint32_t *num)
281 {
282         struct _tbm_bufmgr *mgr;
283         int ret = 0;
284
285         _tbm_surface_mutex_lock();
286
287         if (!g_surface_bufmgr) {
288                 _init_surface_bufmgr();
289                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
290         }
291
292         mgr = g_surface_bufmgr;
293
294         if (!mgr->backend->surface_supported_format) {
295                 _tbm_surface_mutex_unlock();
296                 return 0;
297         }
298
299         ret = mgr->backend->surface_supported_format(formats, num);
300
301         _tbm_surface_mutex_unlock();
302
303         return ret;
304 }
305
306 int
307 tbm_surface_internal_get_num_planes(tbm_format format)
308 {
309         int num_planes = 0;
310
311         switch (format) {
312         case TBM_FORMAT_C8:
313         case TBM_FORMAT_RGB332:
314         case TBM_FORMAT_BGR233:
315         case TBM_FORMAT_XRGB4444:
316         case TBM_FORMAT_XBGR4444:
317         case TBM_FORMAT_RGBX4444:
318         case TBM_FORMAT_BGRX4444:
319         case TBM_FORMAT_ARGB4444:
320         case TBM_FORMAT_ABGR4444:
321         case TBM_FORMAT_RGBA4444:
322         case TBM_FORMAT_BGRA4444:
323         case TBM_FORMAT_XRGB1555:
324         case TBM_FORMAT_XBGR1555:
325         case TBM_FORMAT_RGBX5551:
326         case TBM_FORMAT_BGRX5551:
327         case TBM_FORMAT_ARGB1555:
328         case TBM_FORMAT_ABGR1555:
329         case TBM_FORMAT_RGBA5551:
330         case TBM_FORMAT_BGRA5551:
331         case TBM_FORMAT_RGB565:
332         case TBM_FORMAT_BGR565:
333         case TBM_FORMAT_RGB888:
334         case TBM_FORMAT_BGR888:
335         case TBM_FORMAT_XRGB8888:
336         case TBM_FORMAT_XBGR8888:
337         case TBM_FORMAT_RGBX8888:
338         case TBM_FORMAT_BGRX8888:
339         case TBM_FORMAT_ARGB8888:
340         case TBM_FORMAT_ABGR8888:
341         case TBM_FORMAT_RGBA8888:
342         case TBM_FORMAT_BGRA8888:
343         case TBM_FORMAT_XRGB2101010:
344         case TBM_FORMAT_XBGR2101010:
345         case TBM_FORMAT_RGBX1010102:
346         case TBM_FORMAT_BGRX1010102:
347         case TBM_FORMAT_ARGB2101010:
348         case TBM_FORMAT_ABGR2101010:
349         case TBM_FORMAT_RGBA1010102:
350         case TBM_FORMAT_BGRA1010102:
351         case TBM_FORMAT_YUYV:
352         case TBM_FORMAT_YVYU:
353         case TBM_FORMAT_UYVY:
354         case TBM_FORMAT_VYUY:
355         case TBM_FORMAT_AYUV:
356                 num_planes = 1;
357                 break;
358         case TBM_FORMAT_NV12:
359         case TBM_FORMAT_NV21:
360         case TBM_FORMAT_NV16:
361         case TBM_FORMAT_NV61:
362                 num_planes = 2;
363                 break;
364         case TBM_FORMAT_YUV410:
365         case TBM_FORMAT_YVU410:
366         case TBM_FORMAT_YUV411:
367         case TBM_FORMAT_YVU411:
368         case TBM_FORMAT_YUV420:
369         case TBM_FORMAT_YVU420:
370         case TBM_FORMAT_YUV422:
371         case TBM_FORMAT_YVU422:
372         case TBM_FORMAT_YUV444:
373         case TBM_FORMAT_YVU444:
374                 num_planes = 3;
375                 break;
376
377         default:
378                 break;
379         }
380
381         return num_planes;
382 }
383
384 int
385 tbm_surface_internal_get_bpp(tbm_format format)
386 {
387         int bpp = 0;
388
389         switch (format) {
390         case TBM_FORMAT_C8:
391         case TBM_FORMAT_RGB332:
392         case TBM_FORMAT_BGR233:
393                 bpp = 8;
394                 break;
395         case TBM_FORMAT_XRGB4444:
396         case TBM_FORMAT_XBGR4444:
397         case TBM_FORMAT_RGBX4444:
398         case TBM_FORMAT_BGRX4444:
399         case TBM_FORMAT_ARGB4444:
400         case TBM_FORMAT_ABGR4444:
401         case TBM_FORMAT_RGBA4444:
402         case TBM_FORMAT_BGRA4444:
403         case TBM_FORMAT_XRGB1555:
404         case TBM_FORMAT_XBGR1555:
405         case TBM_FORMAT_RGBX5551:
406         case TBM_FORMAT_BGRX5551:
407         case TBM_FORMAT_ARGB1555:
408         case TBM_FORMAT_ABGR1555:
409         case TBM_FORMAT_RGBA5551:
410         case TBM_FORMAT_BGRA5551:
411         case TBM_FORMAT_RGB565:
412         case TBM_FORMAT_BGR565:
413                 bpp = 16;
414                 break;
415         case TBM_FORMAT_RGB888:
416         case TBM_FORMAT_BGR888:
417                 bpp = 24;
418                 break;
419         case TBM_FORMAT_XRGB8888:
420         case TBM_FORMAT_XBGR8888:
421         case TBM_FORMAT_RGBX8888:
422         case TBM_FORMAT_BGRX8888:
423         case TBM_FORMAT_ARGB8888:
424         case TBM_FORMAT_ABGR8888:
425         case TBM_FORMAT_RGBA8888:
426         case TBM_FORMAT_BGRA8888:
427         case TBM_FORMAT_XRGB2101010:
428         case TBM_FORMAT_XBGR2101010:
429         case TBM_FORMAT_RGBX1010102:
430         case TBM_FORMAT_BGRX1010102:
431         case TBM_FORMAT_ARGB2101010:
432         case TBM_FORMAT_ABGR2101010:
433         case TBM_FORMAT_RGBA1010102:
434         case TBM_FORMAT_BGRA1010102:
435         case TBM_FORMAT_YUYV:
436         case TBM_FORMAT_YVYU:
437         case TBM_FORMAT_UYVY:
438         case TBM_FORMAT_VYUY:
439         case TBM_FORMAT_AYUV:
440                 bpp = 32;
441                 break;
442         case TBM_FORMAT_NV12:
443         case TBM_FORMAT_NV21:
444                 bpp = 12;
445                 break;
446         case TBM_FORMAT_NV16:
447         case TBM_FORMAT_NV61:
448                 bpp = 16;
449                 break;
450         case TBM_FORMAT_YUV410:
451         case TBM_FORMAT_YVU410:
452                 bpp = 9;
453                 break;
454         case TBM_FORMAT_YUV411:
455         case TBM_FORMAT_YVU411:
456         case TBM_FORMAT_YUV420:
457         case TBM_FORMAT_YVU420:
458                 bpp = 12;
459                 break;
460         case TBM_FORMAT_YUV422:
461         case TBM_FORMAT_YVU422:
462                 bpp = 16;
463                 break;
464         case TBM_FORMAT_YUV444:
465         case TBM_FORMAT_YVU444:
466                 bpp = 24;
467                 break;
468         default:
469                 break;
470         }
471
472         return bpp;
473 }
474
475 tbm_surface_h
476 tbm_surface_internal_create_with_flags(int width, int height,
477                                        int format, int flags)
478 {
479         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
480         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
481
482         struct _tbm_bufmgr *mgr;
483         struct _tbm_surface *surf = NULL;
484         uint32_t size = 0;
485         uint32_t offset = 0;
486         uint32_t stride = 0;
487         uint32_t bo_size = 0;
488         int bo_idx;
489         int i, j;
490
491         _tbm_surface_mutex_lock();
492
493         if (!g_surface_bufmgr) {
494                 _init_surface_bufmgr();
495                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
496         }
497
498         mgr = g_surface_bufmgr;
499         if (!TBM_BUFMGR_IS_VALID(mgr)) {
500                 _tbm_surface_mutex_unlock();
501                 return NULL;
502         }
503         surf = calloc(1, sizeof(struct _tbm_surface));
504         if (!surf) {
505                 _tbm_surface_mutex_unlock();
506                 return NULL;
507         }
508
509         surf->bufmgr = mgr;
510         surf->info.width = width;
511         surf->info.height = height;
512         surf->info.format = format;
513         surf->info.bpp = tbm_surface_internal_get_bpp(format);
514         surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
515         surf->refcnt = 1;
516
517         /* get size, stride and offset bo_idx */
518         for (i = 0; i < surf->info.num_planes; i++) {
519                 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride,
520                                                        &bo_idx);
521                 surf->info.planes[i].size = size;
522                 surf->info.planes[i].offset = offset;
523                 surf->info.planes[i].stride = stride;
524                 surf->planes_bo_idx[i] = bo_idx;
525         }
526
527         surf->num_bos = 1;
528
529         for (i = 0; i < surf->info.num_planes; i++) {
530                 surf->info.size += surf->info.planes[i].size;
531
532                 if (surf->num_bos -1 > surf->planes_bo_idx[i])
533                         surf->num_bos = surf->planes_bo_idx[i]++;
534         }
535
536         surf->flags = flags;
537
538         for (i = 0; i < surf->num_bos; i++) {
539                 bo_size = 0;
540                 for (j = 0; j < surf->info.num_planes; j++) {
541                         if (surf->planes_bo_idx[j] == i)
542                                 bo_size += surf->info.planes[j].size;
543                 }
544                 surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
545                 if (!surf->bos[i]) {
546                         for (j = 0; j < i; j++) {
547                                 if (surf->bos[j])
548                                         tbm_bo_unref(surf->bos[j]);
549                         }
550
551                         free(surf);
552                         surf = NULL;
553
554                         if (LIST_IS_EMPTY(&mgr->surf_list)) {
555                                 LIST_DELINIT(&mgr->surf_list);
556                                 _deinit_surface_bufmgr();
557                         }
558
559                         _tbm_surface_mutex_unlock();
560                         return NULL;
561                 }
562                 _tbm_bo_set_surface(surf->bos[i], surf);
563
564         }
565
566         LIST_INITHEAD(&surf->user_data_list);
567
568         LIST_ADD(&surf->item_link, &mgr->surf_list);
569
570         _tbm_surface_mutex_unlock();
571
572         return surf;
573 }
574
575 tbm_surface_h
576 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
577                                      tbm_bo *bos, int num)
578 {
579         TBM_RETURN_VAL_IF_FAIL(bos, NULL);
580         TBM_RETURN_VAL_IF_FAIL(info, NULL);
581         TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
582
583         struct _tbm_bufmgr *mgr;
584         struct _tbm_surface *surf = NULL;
585         int i;
586
587         _tbm_surface_mutex_lock();
588
589         if (!g_surface_bufmgr) {
590                 _init_surface_bufmgr();
591                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
592         }
593
594         mgr = g_surface_bufmgr;
595         if (!TBM_BUFMGR_IS_VALID(mgr)) {
596                 _tbm_surface_mutex_unlock();
597                 return NULL;
598         }
599
600         surf = calloc(1, sizeof(struct _tbm_surface));
601         if (!surf) {
602                 _tbm_surface_mutex_unlock();
603                 return NULL;
604         }
605
606         surf->bufmgr = mgr;
607         surf->info.width = info->width;
608         surf->info.height = info->height;
609         surf->info.format = info->format;
610         surf->info.bpp = info->bpp;
611         surf->info.num_planes = info->num_planes;
612         surf->refcnt = 1;
613
614         /* get size, stride and offset */
615         for (i = 0; i < info->num_planes; i++) {
616                 surf->info.planes[i].offset = info->planes[i].offset;
617                 surf->info.planes[i].stride = info->planes[i].stride;
618
619                 if (info->planes[i].size > 0)
620                         surf->info.planes[i].size = info->planes[i].size;
621                 else
622                         surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
623
624                 if (num == 1)
625                         surf->planes_bo_idx[i] = 0;
626                 else
627                         surf->planes_bo_idx[i] = i;
628         }
629
630         if (info->size > 0) {
631                 surf->info.size = info->size;
632         } else {
633                 surf->info.size = 0;
634                 for (i = 0; i < info->num_planes; i++)
635                         surf->info.size += surf->info.planes[i].size;
636         }
637
638         surf->flags = TBM_BO_DEFAULT;
639
640         /* create only one bo */
641         surf->num_bos = num;
642         for (i = 0; i < num; i++) {
643                 if (bos[i] == NULL)
644                         goto bail1;
645
646                 surf->bos[i] = tbm_bo_ref(bos[i]);
647                 _tbm_bo_set_surface(bos[i], surf);
648         }
649
650         LIST_INITHEAD(&surf->user_data_list);
651
652         LIST_ADD(&surf->item_link, &mgr->surf_list);
653
654         _tbm_surface_mutex_unlock();
655
656         return surf;
657 bail1:
658         for (i = 0; i < num; i++) {
659                 if (surf->bos[i]) {
660                         tbm_bo_unref(surf->bos[i]);
661                         surf->bos[i] = NULL;
662                 }
663         }
664
665         free(surf);
666         surf = NULL;
667
668         if (LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
669                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
670                 _deinit_surface_bufmgr();
671         }
672
673         _tbm_surface_mutex_unlock();
674
675         return NULL;
676 }
677
678 void
679 tbm_surface_internal_destroy(tbm_surface_h surface)
680 {
681         if (!surface)
682                 return;
683
684         _tbm_surface_mutex_lock();
685
686         surface->refcnt--;
687
688         if (surface->refcnt > 0) {
689                 _tbm_surface_mutex_unlock();
690                 return;
691         }
692
693         if (surface->refcnt == 0)
694                 _tbm_surface_internal_destroy(surface);
695
696         _tbm_surface_mutex_unlock();
697 }
698
699 void
700 tbm_surface_internal_ref(tbm_surface_h surface)
701 {
702         TBM_RETURN_IF_FAIL(surface);
703
704         _tbm_surface_mutex_lock();
705
706         surface->refcnt++;
707
708         _tbm_surface_mutex_unlock();
709 }
710
711 void
712 tbm_surface_internal_unref(tbm_surface_h surface)
713 {
714         TBM_RETURN_IF_FAIL(surface);
715
716         _tbm_surface_mutex_lock();
717
718         surface->refcnt--;
719
720         if (surface->refcnt > 0) {
721                 _tbm_surface_mutex_unlock();
722                 return;
723         }
724
725         if (surface->refcnt == 0)
726                 _tbm_surface_internal_destroy(surface);
727
728         _tbm_surface_mutex_unlock();
729 }
730
731 int
732 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
733 {
734         TBM_RETURN_VAL_IF_FAIL(surface, 0);
735
736         struct _tbm_surface *surf;
737         int num;
738
739         _tbm_surface_mutex_lock();
740
741         surf = (struct _tbm_surface *)surface;
742         num = surf->num_bos;
743
744         _tbm_surface_mutex_unlock();
745
746         return num;
747 }
748
749 tbm_bo
750 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
751 {
752         TBM_RETURN_VAL_IF_FAIL(surface, NULL);
753         TBM_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
754
755         struct _tbm_surface *surf;
756         tbm_bo bo;
757
758         _tbm_surface_mutex_lock();
759
760         surf = (struct _tbm_surface *)surface;
761         bo = surf->bos[bo_idx];
762
763         _tbm_surface_mutex_unlock();
764
765         return bo;
766 }
767
768 int
769 tbm_surface_internal_get_size(tbm_surface_h surface)
770 {
771         TBM_RETURN_VAL_IF_FAIL(surface, 0);
772
773         struct _tbm_surface *surf;
774         unsigned int size;
775
776         _tbm_surface_mutex_lock();
777
778         surf = (struct _tbm_surface *)surface;
779         size = surf->info.size;
780
781         _tbm_surface_mutex_unlock();
782
783         return size;
784 }
785
786 int
787 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
788                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
789 {
790         TBM_RETURN_VAL_IF_FAIL(surface, 0);
791         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
792
793         struct _tbm_surface *surf;
794
795         _tbm_surface_mutex_lock();
796
797         surf = (struct _tbm_surface *)surface;
798
799         if (plane_idx >= surf->info.num_planes) {
800                 _tbm_surface_mutex_unlock();
801                 return 0;
802         }
803
804         if (size)
805                 *size = surf->info.planes[plane_idx].size;
806
807         if (offset)
808                 *offset = surf->info.planes[plane_idx].offset;
809
810         if (pitch)
811                 *pitch = surf->info.planes[plane_idx].stride;
812
813         _tbm_surface_mutex_unlock();
814
815         return 1;
816 }
817
818 int
819 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
820                               tbm_surface_info_s *info, int map)
821 {
822         struct _tbm_surface *surf;
823         tbm_bo_handle bo_handles[4];
824         int i, j;
825
826         _tbm_surface_mutex_lock();
827
828         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
829
830         surf = (struct _tbm_surface *)surface;
831
832         memset(info, 0x00, sizeof(tbm_surface_info_s));
833         info->width = surf->info.width;
834         info->height = surf->info.height;
835         info->format = surf->info.format;
836         info->bpp = surf->info.bpp;
837         info->size = surf->info.size;
838         info->num_planes = surf->info.num_planes;
839
840         if (map == 1) {
841                 for (i = 0; i < surf->num_bos; i++) {
842                         bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
843                         if (bo_handles[i].ptr == NULL) {
844                                 for (j = 0; j < i; j++)
845                                         tbm_bo_unmap(surf->bos[j]);
846
847                                 _tbm_surface_mutex_unlock();
848                                 return 0;
849                         }
850                 }
851         } else {
852                 for (i = 0; i < surf->num_bos; i++)
853                         bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
854         }
855
856         for (i = 0; i < surf->info.num_planes; i++) {
857                 info->planes[i].size = surf->info.planes[i].size;
858                 info->planes[i].offset = surf->info.planes[i].offset;
859                 info->planes[i].stride = surf->info.planes[i].stride;
860
861                 if (bo_handles[surf->planes_bo_idx[i]].ptr)
862                         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
863                                               surf->info.planes[i].offset;
864         }
865
866         _tbm_surface_mutex_unlock();
867
868         return 1;
869 }
870
871 void
872 tbm_surface_internal_unmap(tbm_surface_h surface)
873 {
874         struct _tbm_surface *surf;
875         int i;
876
877         _tbm_surface_mutex_lock();
878
879         surf = (struct _tbm_surface *)surface;
880
881         for (i = 0; i < surf->num_bos; i++)
882                 tbm_bo_unmap(surf->bos[i]);
883
884         _tbm_surface_mutex_unlock();
885 }
886
887 unsigned int
888 tbm_surface_internal_get_width(tbm_surface_h surface)
889 {
890         struct _tbm_surface *surf;
891         unsigned int width;
892
893         _tbm_surface_mutex_lock();
894
895         surf = (struct _tbm_surface *)surface;
896         width = surf->info.width;
897
898         _tbm_surface_mutex_unlock();
899
900         return width;
901 }
902
903 unsigned int
904 tbm_surface_internal_get_height(tbm_surface_h surface)
905 {
906         struct _tbm_surface *surf;
907         unsigned int height;
908
909         _tbm_surface_mutex_lock();
910
911         surf = (struct _tbm_surface *)surface;
912         height = surf->info.height;
913
914         _tbm_surface_mutex_unlock();
915
916         return height;
917
918 }
919
920 tbm_format
921 tbm_surface_internal_get_format(tbm_surface_h surface)
922 {
923         struct _tbm_surface *surf;
924         tbm_format format;
925
926         _tbm_surface_mutex_lock();
927
928         surf = (struct _tbm_surface *)surface;
929         format = surf->info.format;
930
931         _tbm_surface_mutex_unlock();
932
933         return format;
934 }
935
936 int
937 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
938 {
939         TBM_RETURN_VAL_IF_FAIL(surface, 0);
940         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
941         struct _tbm_surface *surf;
942         int bo_idx;
943
944         _tbm_surface_mutex_lock();
945
946         surf = (struct _tbm_surface *)surface;
947         bo_idx = surf->planes_bo_idx[plane_idx];
948
949         _tbm_surface_mutex_unlock();
950
951         return bo_idx;
952 }
953
954 unsigned int
955 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
956 {
957         TBM_RETURN_VAL_IF_FAIL(surface, 0);
958
959         return surface->debug_pid;
960 }
961
962 void
963 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
964 {
965         TBM_RETURN_IF_FAIL(surface);
966
967         surface->debug_pid = pid;
968 }
969
970 int
971 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
972                                    tbm_data_free data_free_func)
973 {
974         TBM_RETURN_VAL_IF_FAIL(surface, 0);
975
976         tbm_user_data *data;
977
978         /* check if the data according to the key exist if so, return false. */
979         data = user_data_lookup(&surface->user_data_list, key);
980         if (data) {
981                 TBM_LOG("[libtbm:%d] "
982                         "waring: %s:%d user data already exist. key:%ld\n",
983                         getpid(), __func__, __LINE__, key);
984                 return 0;
985         }
986
987         data = user_data_create(key, data_free_func);
988         if (!data)
989                 return 0;
990
991         LIST_ADD(&data->item_link, &surface->user_data_list);
992
993         return 1;
994 }
995
996 int
997 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
998                                    void *data)
999 {
1000         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1001
1002         tbm_user_data *old_data;
1003
1004         if (LIST_IS_EMPTY(&surface->user_data_list))
1005                 return 0;
1006
1007         old_data = user_data_lookup(&surface->user_data_list, key);
1008         if (!old_data)
1009                 return 0;
1010
1011         if (old_data->data && old_data->free_func)
1012                 old_data->free_func(old_data->data);
1013
1014         old_data->data = data;
1015
1016         return 1;
1017 }
1018
1019 int
1020 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1021                                    void **data)
1022 {
1023         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1024
1025         tbm_user_data *old_data;
1026
1027         if (!data || LIST_IS_EMPTY(&surface->user_data_list))
1028                 return 0;
1029
1030         old_data = user_data_lookup(&surface->user_data_list, key);
1031         if (!old_data) {
1032                 *data = NULL;
1033                 return 0;
1034         }
1035
1036         *data = old_data->data;
1037
1038         return 1;
1039 }
1040
1041 int
1042 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1043                                       unsigned long key)
1044 {
1045         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1046
1047         tbm_user_data *old_data = (void *)0;
1048
1049         if (LIST_IS_EMPTY(&surface->user_data_list))
1050                 return 0;
1051
1052         old_data = user_data_lookup(&surface->user_data_list, key);
1053         if (!old_data)
1054                 return 0;
1055
1056         user_data_delete(old_data);
1057
1058         return 1;
1059 }
1060