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