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