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