Fix svace issues:DEREF_OF_NULL
[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 = NULL;
39 static pthread_mutex_t tbm_surface_lock;
40
41 char *_tbm_surface_internal_format_to_str(tbm_format format)
42 {
43         switch (format) {
44         case TBM_FORMAT_C8:
45                 return "TBM_FORMAT_C8";
46         case TBM_FORMAT_RGB332:
47                 return "TBM_FORMAT_RGB332";
48         case TBM_FORMAT_BGR233:
49                 return "TBM_FORMAT_BGR233";
50         case TBM_FORMAT_XRGB4444:
51                 return "TBM_FORMAT_XRGB4444";
52         case TBM_FORMAT_XBGR4444:
53                 return "TBM_FORMAT_XBGR4444";
54         case TBM_FORMAT_RGBX4444:
55                 return "TBM_FORMAT_RGBX4444";
56         case TBM_FORMAT_BGRX4444:
57                 return "TBM_FORMAT_BGRX4444";
58         case TBM_FORMAT_ARGB4444:
59                 return "TBM_FORMAT_ARGB4444";
60         case TBM_FORMAT_ABGR4444:
61                 return "TBM_FORMAT_ABGR4444";
62         case TBM_FORMAT_RGBA4444:
63                 return "TBM_FORMAT_RGBA4444";
64         case TBM_FORMAT_BGRA4444:
65                 return "TBM_FORMAT_BGRA4444";
66         case TBM_FORMAT_XRGB1555:
67                 return "TBM_FORMAT_XRGB1555";
68         case TBM_FORMAT_XBGR1555:
69                 return "TBM_FORMAT_XBGR1555";
70         case TBM_FORMAT_RGBX5551:
71                 return "TBM_FORMAT_RGBX5551";
72         case TBM_FORMAT_BGRX5551:
73                 return "TBM_FORMAT_BGRX5551";
74         case TBM_FORMAT_ARGB1555:
75                 return "TBM_FORMAT_ARGB1555";
76         case TBM_FORMAT_ABGR1555:
77                 return "TBM_FORMAT_ABGR1555";
78         case TBM_FORMAT_RGBA5551:
79                 return "TBM_FORMAT_RGBA5551";
80         case TBM_FORMAT_BGRA5551:
81                 return "TBM_FORMAT_BGRA5551";
82         case TBM_FORMAT_RGB565:
83                 return "TBM_FORMAT_RGB565";
84         case TBM_FORMAT_BGR565:
85                 return "TBM_FORMAT_BGR565";
86         case TBM_FORMAT_RGB888:
87                 return "TBM_FORMAT_RGB888";
88         case TBM_FORMAT_BGR888:
89                 return "TBM_FORMAT_BGR888";
90         case TBM_FORMAT_XRGB8888:
91                 return "TBM_FORMAT_XRGB8888";
92         case TBM_FORMAT_XBGR8888:
93                 return "TBM_FORMAT_XBGR8888";
94         case TBM_FORMAT_RGBX8888:
95                 return "TBM_FORMAT_RGBX8888";
96         case TBM_FORMAT_BGRX8888:
97                 return "TBM_FORMAT_BGRX8888";
98         case TBM_FORMAT_ARGB8888:
99                 return "TBM_FORMAT_ARGB8888";
100         case TBM_FORMAT_ABGR8888:
101                 return "TBM_FORMAT_ABGR8888";
102         case TBM_FORMAT_RGBA8888:
103                 return "TBM_FORMAT_RGBA8888";
104         case TBM_FORMAT_BGRA8888:
105                 return "TBM_FORMAT_BGRA8888";
106         case TBM_FORMAT_XRGB2101010:
107                 return "TBM_FORMAT_XRGB2101010";
108         case TBM_FORMAT_XBGR2101010:
109                 return "TBM_FORMAT_XBGR2101010";
110         case TBM_FORMAT_RGBX1010102:
111                 return "TBM_FORMAT_RGBX1010102";
112         case TBM_FORMAT_BGRX1010102:
113                 return "TBM_FORMAT_BGRX1010102";
114         case TBM_FORMAT_ARGB2101010:
115                 return "TBM_FORMAT_ARGB2101010";
116         case TBM_FORMAT_ABGR2101010:
117                 return "TBM_FORMAT_ABGR2101010";
118         case TBM_FORMAT_RGBA1010102:
119                 return "TBM_FORMAT_RGBA1010102";
120         case TBM_FORMAT_BGRA1010102:
121                 return "TBM_FORMAT_BGRA1010102";
122         case TBM_FORMAT_YUYV:
123                 return "TBM_FORMAT_YUYV";
124         case TBM_FORMAT_YVYU:
125                 return "TBM_FORMAT_YVYU";
126         case TBM_FORMAT_UYVY:
127                 return "TBM_FORMAT_UYVY";
128         case TBM_FORMAT_VYUY:
129                 return "TBM_FORMAT_VYUY";
130         case TBM_FORMAT_AYUV:
131                 return "TBM_FORMAT_AYUV";
132         case TBM_FORMAT_NV12:
133                 return "TBM_FORMAT_NV12";
134         case TBM_FORMAT_NV21:
135                 return "TBM_FORMAT_NV21";
136         case TBM_FORMAT_NV16:
137                 return "TBM_FORMAT_NV16";
138         case TBM_FORMAT_NV61:
139                 return "TBM_FORMAT_NV61";
140         case TBM_FORMAT_YUV410:
141                 return "TBM_FORMAT_YUV410";
142         case TBM_FORMAT_YVU410:
143                 return "TBM_FORMAT_YVU410";
144         case TBM_FORMAT_YUV411:
145                 return "TBM_FORMAT_YUV411";
146         case TBM_FORMAT_YVU411:
147                 return "TBM_FORMAT_YVU411";
148         case TBM_FORMAT_YUV420:
149                 return "TBM_FORMAT_YUV420";
150         case TBM_FORMAT_YVU420:
151                 return "TBM_FORMAT_YVU420";
152         case TBM_FORMAT_YUV422:
153                 return "TBM_FORMAT_YUV422";
154         case TBM_FORMAT_YVU422:
155                 return "TBM_FORMAT_YVU422";
156         case TBM_FORMAT_YUV444:
157                 return "TBM_FORMAT_YUV444";
158         case TBM_FORMAT_YVU444:
159                 return "TBM_FORMAT_YVU444";
160         case TBM_FORMAT_NV12MT:
161                 return "TBM_FORMAT_NV12MT";
162         default:
163                 return "unknwon";
164         }
165 }
166
167 static bool _tbm_surface_mutex_init(void)
168 {
169         static bool tbm_surface_mutex_init = false;
170
171         if (tbm_surface_mutex_init)
172                 return true;
173
174         if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
175                 TBM_LOG("[libtbm] fail: tbm_surface mutex init\n");
176                 return false;
177         }
178
179         tbm_surface_mutex_init = true;
180
181         return true;
182 }
183
184 void _tbm_surface_mutex_lock(void)
185 {
186         if (!_tbm_surface_mutex_init())
187                 return;
188
189         pthread_mutex_lock(&tbm_surface_lock);
190 }
191
192 void _tbm_surface_mutex_unlock(void)
193 {
194         pthread_mutex_unlock(&tbm_surface_lock);
195 }
196
197 static void _init_surface_bufmgr()
198 {
199         g_surface_bufmgr = tbm_bufmgr_init(-1);
200 }
201
202 static void _deinit_surface_bufmgr()
203 {
204         if (!g_surface_bufmgr)
205                 return;
206
207         tbm_bufmgr_deinit(g_surface_bufmgr);
208         g_surface_bufmgr = NULL;
209 }
210
211 static int _tbm_surface_internal_query_size(tbm_surface_h surface)
212 {
213         TBM_RETURN_VAL_IF_FAIL(surface, 0);
214
215         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
216         struct _tbm_bufmgr *mgr = surf->bufmgr;
217         int size = 0;
218
219         TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
220         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
221         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
222         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
223
224         if (!mgr->backend->surface_get_size)
225                 return 0;
226
227         size = mgr->backend->surface_get_size(surf, surf->info.width, surf->info.height, surf->info.format);
228
229         return size;
230 }
231
232 static int _tbm_surface_internal_query_plane_data(tbm_surface_h surface, int plane_idx, uint32_t * size, uint32_t * offset, uint32_t * pitch, int *bo_idx)
233 {
234         TBM_RETURN_VAL_IF_FAIL(surface, 0);
235         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
236
237         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
238         struct _tbm_bufmgr *mgr = surf->bufmgr;
239         int ret = 0;
240
241         TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
242         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
243         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
244         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
245
246         if (!mgr->backend->surface_get_plane_data)
247                 return 0;
248
249         ret = mgr->backend->surface_get_plane_data(surf, surf->info.width, surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
250         if (!ret)
251                 return 0;
252
253         return 1;
254 }
255
256 static int _tbm_surface_internal_query_num_bos(tbm_format format)
257 {
258         TBM_RETURN_VAL_IF_FAIL(format > 0, 0);
259         struct _tbm_bufmgr *mgr;
260         int ret = 0;
261
262         mgr = g_surface_bufmgr;
263
264         if (!mgr->backend->surface_get_num_bos)
265                 return 0;
266
267         ret = mgr->backend->surface_get_num_bos(format);
268         if (!ret)
269                 return 0;
270
271         return ret;
272 }
273
274 static void _tbm_surface_internal_destroy(tbm_surface_h surface)
275 {
276         int i;
277         tbm_bufmgr bufmgr = surface->bufmgr;
278
279         for (i = 0; i < surface->num_bos; i++) {
280                 surface->bos[i]->surface = NULL;
281
282                 tbm_bo_unref(surface->bos[i]);
283                 surface->bos[i] = NULL;
284         }
285
286         LIST_DEL(&surface->item_link);
287
288         free(surface);
289         surface = NULL;
290
291         if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
292                 LIST_DELINIT(&bufmgr->surf_list);
293                 _deinit_surface_bufmgr();
294         }
295 }
296
297 int tbm_surface_internal_query_supported_formats(uint32_t ** formats, 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 tbm_surface_internal_get_num_planes(tbm_format format)
324 {
325         int num_planes = 0;
326
327         switch (format) {
328         case TBM_FORMAT_C8:
329         case TBM_FORMAT_RGB332:
330         case TBM_FORMAT_BGR233:
331         case TBM_FORMAT_XRGB4444:
332         case TBM_FORMAT_XBGR4444:
333         case TBM_FORMAT_RGBX4444:
334         case TBM_FORMAT_BGRX4444:
335         case TBM_FORMAT_ARGB4444:
336         case TBM_FORMAT_ABGR4444:
337         case TBM_FORMAT_RGBA4444:
338         case TBM_FORMAT_BGRA4444:
339         case TBM_FORMAT_XRGB1555:
340         case TBM_FORMAT_XBGR1555:
341         case TBM_FORMAT_RGBX5551:
342         case TBM_FORMAT_BGRX5551:
343         case TBM_FORMAT_ARGB1555:
344         case TBM_FORMAT_ABGR1555:
345         case TBM_FORMAT_RGBA5551:
346         case TBM_FORMAT_BGRA5551:
347         case TBM_FORMAT_RGB565:
348         case TBM_FORMAT_BGR565:
349         case TBM_FORMAT_RGB888:
350         case TBM_FORMAT_BGR888:
351         case TBM_FORMAT_XRGB8888:
352         case TBM_FORMAT_XBGR8888:
353         case TBM_FORMAT_RGBX8888:
354         case TBM_FORMAT_BGRX8888:
355         case TBM_FORMAT_ARGB8888:
356         case TBM_FORMAT_ABGR8888:
357         case TBM_FORMAT_RGBA8888:
358         case TBM_FORMAT_BGRA8888:
359         case TBM_FORMAT_XRGB2101010:
360         case TBM_FORMAT_XBGR2101010:
361         case TBM_FORMAT_RGBX1010102:
362         case TBM_FORMAT_BGRX1010102:
363         case TBM_FORMAT_ARGB2101010:
364         case TBM_FORMAT_ABGR2101010:
365         case TBM_FORMAT_RGBA1010102:
366         case TBM_FORMAT_BGRA1010102:
367         case TBM_FORMAT_YUYV:
368         case TBM_FORMAT_YVYU:
369         case TBM_FORMAT_UYVY:
370         case TBM_FORMAT_VYUY:
371         case TBM_FORMAT_AYUV:
372                 num_planes = 1;
373                 break;
374         case TBM_FORMAT_NV12:
375         case TBM_FORMAT_NV21:
376         case TBM_FORMAT_NV16:
377         case TBM_FORMAT_NV61:
378                 num_planes = 2;
379                 break;
380         case TBM_FORMAT_YUV410:
381         case TBM_FORMAT_YVU410:
382         case TBM_FORMAT_YUV411:
383         case TBM_FORMAT_YVU411:
384         case TBM_FORMAT_YUV420:
385         case TBM_FORMAT_YVU420:
386         case TBM_FORMAT_YUV422:
387         case TBM_FORMAT_YVU422:
388         case TBM_FORMAT_YUV444:
389         case TBM_FORMAT_YVU444:
390                 num_planes = 3;
391                 break;
392
393         default:
394                 break;
395         }
396
397         return num_planes;
398 }
399
400 int tbm_surface_internal_get_bpp(tbm_format format)
401 {
402         int bpp = 0;
403
404         switch (format) {
405         case TBM_FORMAT_C8:
406         case TBM_FORMAT_RGB332:
407         case TBM_FORMAT_BGR233:
408                 bpp = 8;
409                 break;
410         case TBM_FORMAT_XRGB4444:
411         case TBM_FORMAT_XBGR4444:
412         case TBM_FORMAT_RGBX4444:
413         case TBM_FORMAT_BGRX4444:
414         case TBM_FORMAT_ARGB4444:
415         case TBM_FORMAT_ABGR4444:
416         case TBM_FORMAT_RGBA4444:
417         case TBM_FORMAT_BGRA4444:
418         case TBM_FORMAT_XRGB1555:
419         case TBM_FORMAT_XBGR1555:
420         case TBM_FORMAT_RGBX5551:
421         case TBM_FORMAT_BGRX5551:
422         case TBM_FORMAT_ARGB1555:
423         case TBM_FORMAT_ABGR1555:
424         case TBM_FORMAT_RGBA5551:
425         case TBM_FORMAT_BGRA5551:
426         case TBM_FORMAT_RGB565:
427         case TBM_FORMAT_BGR565:
428                 bpp = 16;
429                 break;
430         case TBM_FORMAT_RGB888:
431         case TBM_FORMAT_BGR888:
432                 bpp = 24;
433                 break;
434         case TBM_FORMAT_XRGB8888:
435         case TBM_FORMAT_XBGR8888:
436         case TBM_FORMAT_RGBX8888:
437         case TBM_FORMAT_BGRX8888:
438         case TBM_FORMAT_ARGB8888:
439         case TBM_FORMAT_ABGR8888:
440         case TBM_FORMAT_RGBA8888:
441         case TBM_FORMAT_BGRA8888:
442         case TBM_FORMAT_XRGB2101010:
443         case TBM_FORMAT_XBGR2101010:
444         case TBM_FORMAT_RGBX1010102:
445         case TBM_FORMAT_BGRX1010102:
446         case TBM_FORMAT_ARGB2101010:
447         case TBM_FORMAT_ABGR2101010:
448         case TBM_FORMAT_RGBA1010102:
449         case TBM_FORMAT_BGRA1010102:
450         case TBM_FORMAT_YUYV:
451         case TBM_FORMAT_YVYU:
452         case TBM_FORMAT_UYVY:
453         case TBM_FORMAT_VYUY:
454         case TBM_FORMAT_AYUV:
455                 bpp = 32;
456                 break;
457         case TBM_FORMAT_NV12:
458         case TBM_FORMAT_NV21:
459                 bpp = 12;
460                 break;
461         case TBM_FORMAT_NV16:
462         case TBM_FORMAT_NV61:
463                 bpp = 16;
464                 break;
465         case TBM_FORMAT_YUV410:
466         case TBM_FORMAT_YVU410:
467                 bpp = 9;
468                 break;
469         case TBM_FORMAT_YUV411:
470         case TBM_FORMAT_YVU411:
471         case TBM_FORMAT_YUV420:
472         case TBM_FORMAT_YVU420:
473                 bpp = 12;
474                 break;
475         case TBM_FORMAT_YUV422:
476         case TBM_FORMAT_YVU422:
477                 bpp = 16;
478                 break;
479         case TBM_FORMAT_YUV444:
480         case TBM_FORMAT_YVU444:
481                 bpp = 24;
482                 break;
483         default:
484                 break;
485         }
486
487         return bpp;
488 }
489
490 tbm_surface_h tbm_surface_internal_create_with_flags(int width, int height, int format, int flags)
491 {
492         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
493         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
494
495         struct _tbm_bufmgr *mgr;
496         struct _tbm_surface *surf = NULL;
497         uint32_t size = 0;
498         uint32_t offset = 0;
499         uint32_t stride = 0;
500         uint32_t bo_size = 0;
501         int bo_idx;
502         int i, j;
503
504         _tbm_surface_mutex_lock();
505
506         if (!g_surface_bufmgr) {
507                 _init_surface_bufmgr();
508                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
509         }
510
511         mgr = g_surface_bufmgr;
512         if (!TBM_BUFMGR_IS_VALID(mgr)) {
513                 _tbm_surface_mutex_unlock();
514                 return NULL;
515         }
516         surf = calloc(1, sizeof(struct _tbm_surface));
517         if (!surf) {
518                 _tbm_surface_mutex_unlock();
519                 return NULL;
520         }
521
522         surf->bufmgr = mgr;
523         surf->info.width = width;
524         surf->info.height = height;
525         surf->info.format = format;
526         surf->info.bpp = tbm_surface_internal_get_bpp(format);
527         surf->info.size = _tbm_surface_internal_query_size(surf);
528         surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
529         surf->num_bos = _tbm_surface_internal_query_num_bos(format);
530         surf->refcnt = 1;
531
532         /* get size, stride and offset bo_idx */
533         for (i = 0; i < surf->info.num_planes; i++) {
534                 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx);
535                 surf->info.planes[i].size = size;
536                 surf->info.planes[i].offset = offset;
537                 surf->info.planes[i].stride = stride;
538                 surf->planes_bo_idx[i] = bo_idx;
539         }
540
541         surf->flags = flags;
542
543         for (i = 0; i < surf->num_bos; i++) {
544                 bo_size = 0;
545                 for (j = 0; j < surf->info.num_planes; j++) {
546                         if (surf->planes_bo_idx[j] == i)
547                                 bo_size += surf->info.planes[j].size;
548                 }
549                 surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
550                 if (!surf->bos[i]) {
551                         for (j = 0; j < i; j++) {
552                                 if (!surf->bos[j])
553                                         tbm_bo_unref(surf->bos[j]);
554                         }
555
556                         free(surf);
557                         surf = NULL;
558
559                         if (LIST_IS_EMPTY(&mgr->surf_list)) {
560                                 LIST_DELINIT(&mgr->surf_list);
561                                 _deinit_surface_bufmgr();
562                         }
563
564                         _tbm_surface_mutex_unlock();
565                         return NULL;
566                 }
567                 _tbm_bo_set_surface(surf->bos[i], surf);
568
569         }
570
571         LIST_ADD(&surf->item_link, &mgr->surf_list);
572
573         _tbm_surface_mutex_unlock();
574
575         return surf;
576 }
577
578 tbm_surface_h tbm_surface_internal_create_with_bos(tbm_surface_info_s * info, tbm_bo * bos, int num)
579 {
580         TBM_RETURN_VAL_IF_FAIL(bos, NULL);
581         TBM_RETURN_VAL_IF_FAIL(info, NULL);
582         TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
583
584         struct _tbm_bufmgr *mgr;
585         struct _tbm_surface *surf = NULL;
586         int i;
587
588         _tbm_surface_mutex_lock();
589
590         if (!g_surface_bufmgr) {
591                 _init_surface_bufmgr();
592                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
593         }
594
595         mgr = g_surface_bufmgr;
596         if (!TBM_BUFMGR_IS_VALID(mgr)) {
597                 _tbm_surface_mutex_unlock();
598                 return NULL;
599         }
600
601         surf = calloc(1, sizeof(struct _tbm_surface));
602         if (!surf) {
603                 _tbm_surface_mutex_unlock();
604                 return NULL;
605         }
606
607         surf->bufmgr = mgr;
608         surf->info.width = info->width;
609         surf->info.height = info->height;
610         surf->info.format = info->format;
611         surf->info.bpp = info->bpp;
612         surf->info.num_planes = info->num_planes;
613         surf->refcnt = 1;
614
615         /* get size, stride and offset */
616         for (i = 0; i < info->num_planes; i++) {
617                 surf->info.planes[i].offset = info->planes[i].offset;
618                 surf->info.planes[i].stride = info->planes[i].stride;
619
620                 if (info->planes[i].size > 0)
621                         surf->info.planes[i].size = info->planes[i].size;
622                 else
623                         surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
624
625                 if (num == 1)
626                         surf->planes_bo_idx[i] = 0;
627                 else
628                         surf->planes_bo_idx[i] = i;
629         }
630
631         if (info->size > 0) {
632                 surf->info.size = info->size;
633         } else {
634                 surf->info.size = 0;
635                 for (i = 0; i < info->num_planes; i++)
636                         surf->info.size += surf->info.planes[i].size;
637         }
638
639         surf->flags = TBM_BO_DEFAULT;
640
641         /* create only one bo */
642         surf->num_bos = num;
643         for (i = 0; i < num; i++) {
644                 if (bos[i] == NULL)
645                         goto bail1;
646
647                 surf->bos[i] = tbm_bo_ref(bos[i]);
648                 _tbm_bo_set_surface(bos[i], surf);
649         }
650
651         LIST_ADD(&surf->item_link, &mgr->surf_list);
652
653         _tbm_surface_mutex_unlock();
654
655         return surf;
656  bail1:
657         for (i = 0; i < num; i++) {
658                 if (surf->bos[i]) {
659                         tbm_bo_unref(surf->bos[i]);
660                         surf->bos[i] = NULL;
661                 }
662         }
663
664         free(surf);
665         surf = NULL;
666
667         if (LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
668                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
669                 _deinit_surface_bufmgr();
670         }
671
672         _tbm_surface_mutex_unlock();
673
674         return NULL;
675 }
676
677 void tbm_surface_internal_destroy(tbm_surface_h surface)
678 {
679         if (!surface)
680                 return;
681
682         _tbm_surface_mutex_lock();
683
684         surface->refcnt--;
685
686         if (surface->refcnt > 0) {
687                 _tbm_surface_mutex_unlock();
688                 return;
689         }
690
691         if (surface->refcnt == 0)
692                 _tbm_surface_internal_destroy(surface);
693
694         _tbm_surface_mutex_unlock();
695 }
696
697 void tbm_surface_internal_ref(tbm_surface_h surface)
698 {
699         TBM_RETURN_IF_FAIL(surface);
700
701         _tbm_surface_mutex_lock();
702
703         surface->refcnt++;
704
705         _tbm_surface_mutex_unlock();
706 }
707
708 void tbm_surface_internal_unref(tbm_surface_h surface)
709 {
710         TBM_RETURN_IF_FAIL(surface);
711
712         _tbm_surface_mutex_lock();
713
714         surface->refcnt--;
715
716         if (surface->refcnt > 0) {
717                 _tbm_surface_mutex_unlock();
718                 return;
719         }
720
721         if (surface->refcnt == 0)
722                 _tbm_surface_internal_destroy(surface);
723
724         _tbm_surface_mutex_unlock();
725 }
726
727 int tbm_surface_internal_get_num_bos(tbm_surface_h surface)
728 {
729         TBM_RETURN_VAL_IF_FAIL(surface, 0);
730
731         struct _tbm_surface *surf;
732         int num;
733
734         _tbm_surface_mutex_lock();
735
736         surf = (struct _tbm_surface *)surface;
737         num = surf->num_bos;
738
739         _tbm_surface_mutex_unlock();
740
741         return num;
742 }
743
744 tbm_bo tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
745 {
746         TBM_RETURN_VAL_IF_FAIL(surface, NULL);
747         TBM_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
748
749         struct _tbm_surface *surf;
750         tbm_bo bo;
751
752         _tbm_surface_mutex_lock();
753
754         surf = (struct _tbm_surface *)surface;
755         bo = surf->bos[bo_idx];
756
757         _tbm_surface_mutex_unlock();
758
759         return bo;
760 }
761
762 int tbm_surface_internal_get_size(tbm_surface_h surface)
763 {
764         TBM_RETURN_VAL_IF_FAIL(surface, 0);
765
766         struct _tbm_surface *surf;
767         unsigned int size;
768
769         _tbm_surface_mutex_lock();
770
771         surf = (struct _tbm_surface *)surface;
772         size = surf->info.size;
773
774         _tbm_surface_mutex_unlock();
775
776         return size;
777 }
778
779 int tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx, uint32_t * size, uint32_t * offset, uint32_t * pitch)
780 {
781         TBM_RETURN_VAL_IF_FAIL(surface, 0);
782         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
783
784         struct _tbm_surface *surf;
785
786         _tbm_surface_mutex_lock();
787
788         surf = (struct _tbm_surface *)surface;
789
790         if (plane_idx >= surf->info.num_planes) {
791                 _tbm_surface_mutex_unlock();
792                 return 0;
793         }
794
795         *size = surf->info.planes[plane_idx].size;
796         *offset = surf->info.planes[plane_idx].offset;
797         *pitch = surf->info.planes[plane_idx].stride;
798
799         _tbm_surface_mutex_unlock();
800
801         return 1;
802 }
803
804 int tbm_surface_internal_get_info(tbm_surface_h surface, int opt, tbm_surface_info_s * info, int map)
805 {
806         struct _tbm_surface *surf;
807         tbm_bo_handle bo_handles[4];
808         int i, j;
809
810         _tbm_surface_mutex_lock();
811
812         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
813
814         surf = (struct _tbm_surface *)surface;
815
816         info->width = surf->info.width;
817         info->height = surf->info.height;
818         info->format = surf->info.format;
819         info->bpp = surf->info.bpp;
820         info->size = surf->info.size;
821         info->num_planes = surf->info.num_planes;
822
823         if (map == 1) {
824                 for (i = 0; i < surf->num_bos; i++) {
825                         bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
826                         if (bo_handles[i].ptr == NULL) {
827                                 for (j = 0; j < i; j++)
828                                         tbm_bo_unmap(surf->bos[j]);
829
830                                 _tbm_surface_mutex_unlock();
831                                 return 0;
832                         }
833                 }
834         } else {
835                 for (i = 0; i < surf->num_bos; i++) {
836                         bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
837                         if (bo_handles[i].ptr == NULL) {
838                                 _tbm_surface_mutex_unlock();
839                                 return 0;
840                         }
841                 }
842         }
843
844         for (i = 0; i < surf->info.num_planes; i++) {
845                 info->planes[i].size = surf->info.planes[i].size;
846                 info->planes[i].offset = surf->info.planes[i].offset;
847                 info->planes[i].stride = surf->info.planes[i].stride;
848                 info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr + surf->info.planes[i].offset;
849         }
850
851         _tbm_surface_mutex_unlock();
852
853         return 1;
854 }
855
856 void tbm_surface_internal_unmap(tbm_surface_h surface)
857 {
858         struct _tbm_surface *surf;
859         int i;
860
861         _tbm_surface_mutex_lock();
862
863         surf = (struct _tbm_surface *)surface;
864
865         for (i = 0; i < surf->num_bos; i++)
866                 tbm_bo_unmap(surf->bos[i]);
867
868         _tbm_surface_mutex_unlock();
869 }
870
871 unsigned int tbm_surface_internal_get_width(tbm_surface_h surface)
872 {
873         struct _tbm_surface *surf;
874         unsigned int width;
875
876         _tbm_surface_mutex_lock();
877
878         surf = (struct _tbm_surface *)surface;
879         width = surf->info.width;
880
881         _tbm_surface_mutex_unlock();
882
883         return width;
884 }
885
886 unsigned int tbm_surface_internal_get_height(tbm_surface_h surface)
887 {
888         struct _tbm_surface *surf;
889         unsigned int height;
890
891         _tbm_surface_mutex_lock();
892
893         surf = (struct _tbm_surface *)surface;
894         height = surf->info.height;
895
896         _tbm_surface_mutex_unlock();
897
898         return height;
899
900 }
901
902 tbm_format tbm_surface_internal_get_format(tbm_surface_h surface)
903 {
904         struct _tbm_surface *surf;
905         tbm_format format;
906
907         _tbm_surface_mutex_lock();
908
909         surf = (struct _tbm_surface *)surface;
910         format = surf->info.format;
911
912         _tbm_surface_mutex_unlock();
913
914         return format;
915 }
916
917 int tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
918 {
919         TBM_RETURN_VAL_IF_FAIL(surface, 0);
920         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
921         struct _tbm_surface *surf;
922         int bo_idx;
923
924         _tbm_surface_mutex_lock();
925
926         surf = (struct _tbm_surface *)surface;
927         bo_idx = surf->planes_bo_idx[plane_idx];
928
929         _tbm_surface_mutex_unlock();
930
931         return bo_idx;
932 }
933
934 unsigned int _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
935 {
936         TBM_RETURN_VAL_IF_FAIL(surface, 0);
937
938         return surface->debug_pid;
939 }
940
941 void tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
942 {
943         TBM_RETURN_IF_FAIL(surface);
944
945         surface->debug_pid = pid;
946 }
947