Add tbm surface user data
[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 #include "tbm_user_data.h"
38
39 static tbm_bufmgr g_surface_bufmgr = NULL;
40 static pthread_mutex_t tbm_surface_lock;
41
42 char *_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 _tbm_surface_mutex_init(void)
169 {
170         static bool tbm_surface_mutex_init = false;
171
172         if (tbm_surface_mutex_init)
173                 return true;
174
175         if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
176                 TBM_LOG("[libtbm] fail: tbm_surface mutex init\n");
177                 return false;
178         }
179
180         tbm_surface_mutex_init = true;
181
182         return true;
183 }
184
185 void _tbm_surface_mutex_lock(void)
186 {
187         if (!_tbm_surface_mutex_init())
188                 return;
189
190         pthread_mutex_lock(&tbm_surface_lock);
191 }
192
193 void _tbm_surface_mutex_unlock(void)
194 {
195         pthread_mutex_unlock(&tbm_surface_lock);
196 }
197
198 static void _init_surface_bufmgr()
199 {
200         g_surface_bufmgr = tbm_bufmgr_init(-1);
201 }
202
203 static void _deinit_surface_bufmgr()
204 {
205         if (!g_surface_bufmgr)
206                 return;
207
208         tbm_bufmgr_deinit(g_surface_bufmgr);
209         g_surface_bufmgr = NULL;
210 }
211
212 static int _tbm_surface_internal_query_size(tbm_surface_h surface)
213 {
214         TBM_RETURN_VAL_IF_FAIL(surface, 0);
215
216         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
217         struct _tbm_bufmgr *mgr = surf->bufmgr;
218         int size = 0;
219
220         TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
221         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
222         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
223         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
224
225         if (!mgr->backend->surface_get_size)
226                 return 0;
227
228         size = mgr->backend->surface_get_size(surf, surf->info.width, surf->info.height, surf->info.format);
229
230         return size;
231 }
232
233 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)
234 {
235         TBM_RETURN_VAL_IF_FAIL(surface, 0);
236         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
237
238         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
239         struct _tbm_bufmgr *mgr = surf->bufmgr;
240         int ret = 0;
241
242         TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
243         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
244         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
245         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
246
247         if (!mgr->backend->surface_get_plane_data)
248                 return 0;
249
250         ret = mgr->backend->surface_get_plane_data(surf, surf->info.width, surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
251         if (!ret)
252                 return 0;
253
254         return 1;
255 }
256
257 static int _tbm_surface_internal_query_num_bos(tbm_format format)
258 {
259         TBM_RETURN_VAL_IF_FAIL(format > 0, 0);
260         struct _tbm_bufmgr *mgr;
261         int ret = 0;
262
263         mgr = g_surface_bufmgr;
264
265         if (!mgr->backend->surface_get_num_bos)
266                 return 0;
267
268         ret = mgr->backend->surface_get_num_bos(format);
269         if (!ret)
270                 return 0;
271
272         return ret;
273 }
274
275 static void _tbm_surface_internal_destroy(tbm_surface_h surface)
276 {
277         int i;
278         tbm_bufmgr bufmgr = surface->bufmgr;
279         tbm_user_data *old_data = NULL, *tmp = NULL;
280
281         for (i = 0; i < surface->num_bos; i++) {
282                 surface->bos[i]->surface = NULL;
283
284                 tbm_bo_unref(surface->bos[i]);
285                 surface->bos[i] = NULL;
286         }
287
288         /* destory the user_data_list */
289         if (!LIST_IS_EMPTY(&surface->user_data_list)) {
290                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
291                         TBM_LOG("[tbm_surface:%d] free user_data \n",
292                                 getpid());
293                         user_data_delete(old_data);
294                 }
295         }
296
297         LIST_DEL(&surface->item_link);
298
299         free(surface);
300         surface = NULL;
301
302         if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
303                 LIST_DELINIT(&bufmgr->surf_list);
304                 _deinit_surface_bufmgr();
305         }
306 }
307
308 int tbm_surface_internal_query_supported_formats(uint32_t ** formats, uint32_t * num)
309 {
310         struct _tbm_bufmgr *mgr;
311         int ret = 0;
312
313         _tbm_surface_mutex_lock();
314
315         if (!g_surface_bufmgr) {
316                 _init_surface_bufmgr();
317                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
318         }
319
320         mgr = g_surface_bufmgr;
321
322         if (!mgr->backend->surface_supported_format) {
323                 _tbm_surface_mutex_unlock();
324                 return 0;
325         }
326
327         ret = mgr->backend->surface_supported_format(formats, num);
328
329         _tbm_surface_mutex_unlock();
330
331         return ret;
332 }
333
334 int tbm_surface_internal_get_num_planes(tbm_format format)
335 {
336         int num_planes = 0;
337
338         switch (format) {
339         case TBM_FORMAT_C8:
340         case TBM_FORMAT_RGB332:
341         case TBM_FORMAT_BGR233:
342         case TBM_FORMAT_XRGB4444:
343         case TBM_FORMAT_XBGR4444:
344         case TBM_FORMAT_RGBX4444:
345         case TBM_FORMAT_BGRX4444:
346         case TBM_FORMAT_ARGB4444:
347         case TBM_FORMAT_ABGR4444:
348         case TBM_FORMAT_RGBA4444:
349         case TBM_FORMAT_BGRA4444:
350         case TBM_FORMAT_XRGB1555:
351         case TBM_FORMAT_XBGR1555:
352         case TBM_FORMAT_RGBX5551:
353         case TBM_FORMAT_BGRX5551:
354         case TBM_FORMAT_ARGB1555:
355         case TBM_FORMAT_ABGR1555:
356         case TBM_FORMAT_RGBA5551:
357         case TBM_FORMAT_BGRA5551:
358         case TBM_FORMAT_RGB565:
359         case TBM_FORMAT_BGR565:
360         case TBM_FORMAT_RGB888:
361         case TBM_FORMAT_BGR888:
362         case TBM_FORMAT_XRGB8888:
363         case TBM_FORMAT_XBGR8888:
364         case TBM_FORMAT_RGBX8888:
365         case TBM_FORMAT_BGRX8888:
366         case TBM_FORMAT_ARGB8888:
367         case TBM_FORMAT_ABGR8888:
368         case TBM_FORMAT_RGBA8888:
369         case TBM_FORMAT_BGRA8888:
370         case TBM_FORMAT_XRGB2101010:
371         case TBM_FORMAT_XBGR2101010:
372         case TBM_FORMAT_RGBX1010102:
373         case TBM_FORMAT_BGRX1010102:
374         case TBM_FORMAT_ARGB2101010:
375         case TBM_FORMAT_ABGR2101010:
376         case TBM_FORMAT_RGBA1010102:
377         case TBM_FORMAT_BGRA1010102:
378         case TBM_FORMAT_YUYV:
379         case TBM_FORMAT_YVYU:
380         case TBM_FORMAT_UYVY:
381         case TBM_FORMAT_VYUY:
382         case TBM_FORMAT_AYUV:
383                 num_planes = 1;
384                 break;
385         case TBM_FORMAT_NV12:
386         case TBM_FORMAT_NV21:
387         case TBM_FORMAT_NV16:
388         case TBM_FORMAT_NV61:
389                 num_planes = 2;
390                 break;
391         case TBM_FORMAT_YUV410:
392         case TBM_FORMAT_YVU410:
393         case TBM_FORMAT_YUV411:
394         case TBM_FORMAT_YVU411:
395         case TBM_FORMAT_YUV420:
396         case TBM_FORMAT_YVU420:
397         case TBM_FORMAT_YUV422:
398         case TBM_FORMAT_YVU422:
399         case TBM_FORMAT_YUV444:
400         case TBM_FORMAT_YVU444:
401                 num_planes = 3;
402                 break;
403
404         default:
405                 break;
406         }
407
408         return num_planes;
409 }
410
411 int tbm_surface_internal_get_bpp(tbm_format format)
412 {
413         int bpp = 0;
414
415         switch (format) {
416         case TBM_FORMAT_C8:
417         case TBM_FORMAT_RGB332:
418         case TBM_FORMAT_BGR233:
419                 bpp = 8;
420                 break;
421         case TBM_FORMAT_XRGB4444:
422         case TBM_FORMAT_XBGR4444:
423         case TBM_FORMAT_RGBX4444:
424         case TBM_FORMAT_BGRX4444:
425         case TBM_FORMAT_ARGB4444:
426         case TBM_FORMAT_ABGR4444:
427         case TBM_FORMAT_RGBA4444:
428         case TBM_FORMAT_BGRA4444:
429         case TBM_FORMAT_XRGB1555:
430         case TBM_FORMAT_XBGR1555:
431         case TBM_FORMAT_RGBX5551:
432         case TBM_FORMAT_BGRX5551:
433         case TBM_FORMAT_ARGB1555:
434         case TBM_FORMAT_ABGR1555:
435         case TBM_FORMAT_RGBA5551:
436         case TBM_FORMAT_BGRA5551:
437         case TBM_FORMAT_RGB565:
438         case TBM_FORMAT_BGR565:
439                 bpp = 16;
440                 break;
441         case TBM_FORMAT_RGB888:
442         case TBM_FORMAT_BGR888:
443                 bpp = 24;
444                 break;
445         case TBM_FORMAT_XRGB8888:
446         case TBM_FORMAT_XBGR8888:
447         case TBM_FORMAT_RGBX8888:
448         case TBM_FORMAT_BGRX8888:
449         case TBM_FORMAT_ARGB8888:
450         case TBM_FORMAT_ABGR8888:
451         case TBM_FORMAT_RGBA8888:
452         case TBM_FORMAT_BGRA8888:
453         case TBM_FORMAT_XRGB2101010:
454         case TBM_FORMAT_XBGR2101010:
455         case TBM_FORMAT_RGBX1010102:
456         case TBM_FORMAT_BGRX1010102:
457         case TBM_FORMAT_ARGB2101010:
458         case TBM_FORMAT_ABGR2101010:
459         case TBM_FORMAT_RGBA1010102:
460         case TBM_FORMAT_BGRA1010102:
461         case TBM_FORMAT_YUYV:
462         case TBM_FORMAT_YVYU:
463         case TBM_FORMAT_UYVY:
464         case TBM_FORMAT_VYUY:
465         case TBM_FORMAT_AYUV:
466                 bpp = 32;
467                 break;
468         case TBM_FORMAT_NV12:
469         case TBM_FORMAT_NV21:
470                 bpp = 12;
471                 break;
472         case TBM_FORMAT_NV16:
473         case TBM_FORMAT_NV61:
474                 bpp = 16;
475                 break;
476         case TBM_FORMAT_YUV410:
477         case TBM_FORMAT_YVU410:
478                 bpp = 9;
479                 break;
480         case TBM_FORMAT_YUV411:
481         case TBM_FORMAT_YVU411:
482         case TBM_FORMAT_YUV420:
483         case TBM_FORMAT_YVU420:
484                 bpp = 12;
485                 break;
486         case TBM_FORMAT_YUV422:
487         case TBM_FORMAT_YVU422:
488                 bpp = 16;
489                 break;
490         case TBM_FORMAT_YUV444:
491         case TBM_FORMAT_YVU444:
492                 bpp = 24;
493                 break;
494         default:
495                 break;
496         }
497
498         return bpp;
499 }
500
501 tbm_surface_h tbm_surface_internal_create_with_flags(int width, int height, int format, int flags)
502 {
503         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
504         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
505
506         struct _tbm_bufmgr *mgr;
507         struct _tbm_surface *surf = NULL;
508         uint32_t size = 0;
509         uint32_t offset = 0;
510         uint32_t stride = 0;
511         uint32_t bo_size = 0;
512         int bo_idx;
513         int i, j;
514
515         _tbm_surface_mutex_lock();
516
517         if (!g_surface_bufmgr) {
518                 _init_surface_bufmgr();
519                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
520         }
521
522         mgr = g_surface_bufmgr;
523         if (!TBM_BUFMGR_IS_VALID(mgr)) {
524                 _tbm_surface_mutex_unlock();
525                 return NULL;
526         }
527         surf = calloc(1, sizeof(struct _tbm_surface));
528         if (!surf) {
529                 _tbm_surface_mutex_unlock();
530                 return NULL;
531         }
532
533         surf->bufmgr = mgr;
534         surf->info.width = width;
535         surf->info.height = height;
536         surf->info.format = format;
537         surf->info.bpp = tbm_surface_internal_get_bpp(format);
538         surf->info.size = _tbm_surface_internal_query_size(surf);
539         surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
540         surf->num_bos = _tbm_surface_internal_query_num_bos(format);
541         surf->refcnt = 1;
542
543         /* get size, stride and offset bo_idx */
544         for (i = 0; i < surf->info.num_planes; i++) {
545                 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx);
546                 surf->info.planes[i].size = size;
547                 surf->info.planes[i].offset = offset;
548                 surf->info.planes[i].stride = stride;
549                 surf->planes_bo_idx[i] = bo_idx;
550         }
551
552         surf->flags = flags;
553
554         for (i = 0; i < surf->num_bos; i++) {
555                 bo_size = 0;
556                 for (j = 0; j < surf->info.num_planes; j++) {
557                         if (surf->planes_bo_idx[j] == i)
558                                 bo_size += surf->info.planes[j].size;
559                 }
560                 surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
561                 if (!surf->bos[i]) {
562                         for (j = 0; j < i; j++) {
563                                 if (surf->bos[j])
564                                         tbm_bo_unref(surf->bos[j]);
565                         }
566
567                         free(surf);
568                         surf = NULL;
569
570                         if (LIST_IS_EMPTY(&mgr->surf_list)) {
571                                 LIST_DELINIT(&mgr->surf_list);
572                                 _deinit_surface_bufmgr();
573                         }
574
575                         _tbm_surface_mutex_unlock();
576                         return NULL;
577                 }
578                 _tbm_bo_set_surface(surf->bos[i], surf);
579
580         }
581
582         LIST_ADD(&surf->item_link, &mgr->surf_list);
583
584         _tbm_surface_mutex_unlock();
585
586         return surf;
587 }
588
589 tbm_surface_h tbm_surface_internal_create_with_bos(tbm_surface_info_s * info, tbm_bo * bos, int num)
590 {
591         TBM_RETURN_VAL_IF_FAIL(bos, NULL);
592         TBM_RETURN_VAL_IF_FAIL(info, NULL);
593         TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
594
595         struct _tbm_bufmgr *mgr;
596         struct _tbm_surface *surf = NULL;
597         int i;
598
599         _tbm_surface_mutex_lock();
600
601         if (!g_surface_bufmgr) {
602                 _init_surface_bufmgr();
603                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
604         }
605
606         mgr = g_surface_bufmgr;
607         if (!TBM_BUFMGR_IS_VALID(mgr)) {
608                 _tbm_surface_mutex_unlock();
609                 return NULL;
610         }
611
612         surf = calloc(1, sizeof(struct _tbm_surface));
613         if (!surf) {
614                 _tbm_surface_mutex_unlock();
615                 return NULL;
616         }
617
618         surf->bufmgr = mgr;
619         surf->info.width = info->width;
620         surf->info.height = info->height;
621         surf->info.format = info->format;
622         surf->info.bpp = info->bpp;
623         surf->info.num_planes = info->num_planes;
624         surf->refcnt = 1;
625
626         /* get size, stride and offset */
627         for (i = 0; i < info->num_planes; i++) {
628                 surf->info.planes[i].offset = info->planes[i].offset;
629                 surf->info.planes[i].stride = info->planes[i].stride;
630
631                 if (info->planes[i].size > 0)
632                         surf->info.planes[i].size = info->planes[i].size;
633                 else
634                         surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
635
636                 if (num == 1)
637                         surf->planes_bo_idx[i] = 0;
638                 else
639                         surf->planes_bo_idx[i] = i;
640         }
641
642         if (info->size > 0) {
643                 surf->info.size = info->size;
644         } else {
645                 surf->info.size = 0;
646                 for (i = 0; i < info->num_planes; i++)
647                         surf->info.size += surf->info.planes[i].size;
648         }
649
650         surf->flags = TBM_BO_DEFAULT;
651
652         /* create only one bo */
653         surf->num_bos = num;
654         for (i = 0; i < num; i++) {
655                 if (bos[i] == NULL)
656                         goto bail1;
657
658                 surf->bos[i] = tbm_bo_ref(bos[i]);
659                 _tbm_bo_set_surface(bos[i], surf);
660         }
661
662         LIST_ADD(&surf->item_link, &mgr->surf_list);
663
664         _tbm_surface_mutex_unlock();
665
666         return surf;
667  bail1:
668         for (i = 0; i < num; i++) {
669                 if (surf->bos[i]) {
670                         tbm_bo_unref(surf->bos[i]);
671                         surf->bos[i] = NULL;
672                 }
673         }
674
675         free(surf);
676         surf = NULL;
677
678         if (LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
679                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
680                 _deinit_surface_bufmgr();
681         }
682
683         _tbm_surface_mutex_unlock();
684
685         return NULL;
686 }
687
688 void tbm_surface_internal_destroy(tbm_surface_h surface)
689 {
690         if (!surface)
691                 return;
692
693         _tbm_surface_mutex_lock();
694
695         surface->refcnt--;
696
697         if (surface->refcnt > 0) {
698                 _tbm_surface_mutex_unlock();
699                 return;
700         }
701
702         if (surface->refcnt == 0)
703                 _tbm_surface_internal_destroy(surface);
704
705         _tbm_surface_mutex_unlock();
706 }
707
708 void tbm_surface_internal_ref(tbm_surface_h surface)
709 {
710         TBM_RETURN_IF_FAIL(surface);
711
712         _tbm_surface_mutex_lock();
713
714         surface->refcnt++;
715
716         _tbm_surface_mutex_unlock();
717 }
718
719 void tbm_surface_internal_unref(tbm_surface_h surface)
720 {
721         TBM_RETURN_IF_FAIL(surface);
722
723         _tbm_surface_mutex_lock();
724
725         surface->refcnt--;
726
727         if (surface->refcnt > 0) {
728                 _tbm_surface_mutex_unlock();
729                 return;
730         }
731
732         if (surface->refcnt == 0)
733                 _tbm_surface_internal_destroy(surface);
734
735         _tbm_surface_mutex_unlock();
736 }
737
738 int tbm_surface_internal_get_num_bos(tbm_surface_h surface)
739 {
740         TBM_RETURN_VAL_IF_FAIL(surface, 0);
741
742         struct _tbm_surface *surf;
743         int num;
744
745         _tbm_surface_mutex_lock();
746
747         surf = (struct _tbm_surface *)surface;
748         num = surf->num_bos;
749
750         _tbm_surface_mutex_unlock();
751
752         return num;
753 }
754
755 tbm_bo tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
756 {
757         TBM_RETURN_VAL_IF_FAIL(surface, NULL);
758         TBM_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
759
760         struct _tbm_surface *surf;
761         tbm_bo bo;
762
763         _tbm_surface_mutex_lock();
764
765         surf = (struct _tbm_surface *)surface;
766         bo = surf->bos[bo_idx];
767
768         _tbm_surface_mutex_unlock();
769
770         return bo;
771 }
772
773 int tbm_surface_internal_get_size(tbm_surface_h surface)
774 {
775         TBM_RETURN_VAL_IF_FAIL(surface, 0);
776
777         struct _tbm_surface *surf;
778         unsigned int size;
779
780         _tbm_surface_mutex_lock();
781
782         surf = (struct _tbm_surface *)surface;
783         size = surf->info.size;
784
785         _tbm_surface_mutex_unlock();
786
787         return size;
788 }
789
790 int tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx, uint32_t * size, uint32_t * offset, uint32_t * pitch)
791 {
792         TBM_RETURN_VAL_IF_FAIL(surface, 0);
793         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
794
795         struct _tbm_surface *surf;
796
797         _tbm_surface_mutex_lock();
798
799         surf = (struct _tbm_surface *)surface;
800
801         if (plane_idx >= surf->info.num_planes) {
802                 _tbm_surface_mutex_unlock();
803                 return 0;
804         }
805
806         if (size)
807                 *size = surf->info.planes[plane_idx].size;
808
809         if (offset)
810                 *offset = surf->info.planes[plane_idx].offset;
811
812         if (pitch)
813                 *pitch = surf->info.planes[plane_idx].stride;
814
815         _tbm_surface_mutex_unlock();
816
817         return 1;
818 }
819
820 int tbm_surface_internal_get_info(tbm_surface_h surface, int opt, 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         info->width = surf->info.width;
833         info->height = surf->info.height;
834         info->format = surf->info.format;
835         info->bpp = surf->info.bpp;
836         info->size = surf->info.size;
837         info->num_planes = surf->info.num_planes;
838
839         if (map == 1) {
840                 for (i = 0; i < surf->num_bos; i++) {
841                         bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
842                         if (bo_handles[i].ptr == NULL) {
843                                 for (j = 0; j < i; j++)
844                                         tbm_bo_unmap(surf->bos[j]);
845
846                                 _tbm_surface_mutex_unlock();
847                                 return 0;
848                         }
849                 }
850         } else {
851                 for (i = 0; i < surf->num_bos; i++) {
852                         bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
853                         if (bo_handles[i].ptr == NULL) {
854                                 _tbm_surface_mutex_unlock();
855                                 return 0;
856                         }
857                 }
858         }
859
860         for (i = 0; i < surf->info.num_planes; i++) {
861                 info->planes[i].size = surf->info.planes[i].size;
862                 info->planes[i].offset = surf->info.planes[i].offset;
863                 info->planes[i].stride = surf->info.planes[i].stride;
864                 info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr + surf->info.planes[i].offset;
865         }
866
867         _tbm_surface_mutex_unlock();
868
869         return 1;
870 }
871
872 void 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 tbm_surface_internal_get_width(tbm_surface_h surface)
888 {
889         struct _tbm_surface *surf;
890         unsigned int width;
891
892         _tbm_surface_mutex_lock();
893
894         surf = (struct _tbm_surface *)surface;
895         width = surf->info.width;
896
897         _tbm_surface_mutex_unlock();
898
899         return width;
900 }
901
902 unsigned int tbm_surface_internal_get_height(tbm_surface_h surface)
903 {
904         struct _tbm_surface *surf;
905         unsigned int height;
906
907         _tbm_surface_mutex_lock();
908
909         surf = (struct _tbm_surface *)surface;
910         height = surf->info.height;
911
912         _tbm_surface_mutex_unlock();
913
914         return height;
915
916 }
917
918 tbm_format tbm_surface_internal_get_format(tbm_surface_h surface)
919 {
920         struct _tbm_surface *surf;
921         tbm_format format;
922
923         _tbm_surface_mutex_lock();
924
925         surf = (struct _tbm_surface *)surface;
926         format = surf->info.format;
927
928         _tbm_surface_mutex_unlock();
929
930         return format;
931 }
932
933 int tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
934 {
935         TBM_RETURN_VAL_IF_FAIL(surface, 0);
936         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
937         struct _tbm_surface *surf;
938         int bo_idx;
939
940         _tbm_surface_mutex_lock();
941
942         surf = (struct _tbm_surface *)surface;
943         bo_idx = surf->planes_bo_idx[plane_idx];
944
945         _tbm_surface_mutex_unlock();
946
947         return bo_idx;
948 }
949
950 unsigned int _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
951 {
952         TBM_RETURN_VAL_IF_FAIL(surface, 0);
953
954         return surface->debug_pid;
955 }
956
957 void tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
958 {
959         TBM_RETURN_IF_FAIL(surface);
960
961         surface->debug_pid = pid;
962 }
963
964 int tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key, tbm_data_free data_free_func)
965 {
966         TBM_RETURN_VAL_IF_FAIL(surface, 0);
967
968         tbm_user_data *data;
969
970         /* check if the data according to the key exist if so, return false. */
971         data = user_data_lookup(&surface->user_data_list, key);
972         if (data) {
973                 TBM_LOG("[libtbm:%d] "
974                         "waring: %s:%d user data already exist. key:%ld\n",
975                         getpid(), __FUNCTION__, __LINE__, key);
976                 return 0;
977         }
978
979         data = user_data_create(key, data_free_func);
980         if (!data)
981                 return 0;
982
983         LIST_ADD(&data->item_link, &surface->user_data_list);
984
985         return 1;
986 }
987
988 int tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key, void *data)
989 {
990         TBM_RETURN_VAL_IF_FAIL(surface, 0);
991
992         tbm_user_data *old_data;
993
994         if (LIST_IS_EMPTY(&surface->user_data_list))
995                 return 0;
996
997         old_data = user_data_lookup(&surface->user_data_list, key);
998         if (!old_data)
999                 return 0;
1000
1001         if (old_data->data && old_data->free_func)
1002                 old_data->free_func(old_data->data);
1003
1004         old_data->data = data;
1005
1006         return 1;
1007 }
1008
1009 int tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key, void **data)
1010 {
1011         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1012
1013         tbm_user_data *old_data;
1014
1015         if (!data || LIST_IS_EMPTY(&surface->user_data_list))
1016                 return 0;
1017
1018         old_data = user_data_lookup(&surface->user_data_list, key);
1019         if (!old_data) {
1020                 *data = NULL;
1021                 return 0;
1022         }
1023
1024         *data = old_data->data;
1025
1026         return 1;
1027 }
1028
1029 int tbm_surface_internal_delete_user_data(tbm_surface_h surface, unsigned long key)
1030 {
1031         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1032
1033         tbm_user_data *old_data = (void *)0;
1034
1035         if (LIST_IS_EMPTY(&surface->user_data_list))
1036                 return 0;
1037
1038         old_data = user_data_lookup(&surface->user_data_list, key);
1039         if (!old_data)
1040                 return 0;
1041
1042         user_data_delete(old_data);
1043
1044         return 1;
1045 }
1046