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