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