tbm_bufmgr: change tbm_bo_alloc_with_format name
[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
34 #include <stdio.h>
35 #include <time.h>
36 #include <sys/time.h>
37 #include "tbm_bufmgr.h"
38 #include "tbm_bufmgr_int.h"
39 #include "tbm_surface_internal.h"
40 #include "list.h"
41 #include <png.h>
42 #include <pixman.h>
43
44 #define TBM_SURFACE_MAGIC 0xBF021234
45
46 static tbm_bufmgr g_surface_bufmgr;
47 static pthread_mutex_t tbm_surface_lock = PTHREAD_MUTEX_INITIALIZER;
48 void _tbm_surface_mutex_unlock(void);
49
50 /* check condition */
51 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
52         if (!(cond)) {\
53                 TBM_ERR("'%s' failed.\n", #cond);\
54                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
55                 _tbm_surface_mutex_unlock();\
56                 return;\
57         } \
58 }
59
60 #define TBM_SURFACE_RETURN_ERR_IF_FAIL(cond, error_type) {\
61         if (!(cond)) {\
62                 TBM_ERR("'%s' failed.\n", #cond);\
63                 _tbm_set_last_result(error_type);\
64                 _tbm_surface_mutex_unlock();\
65                 return;\
66         } \
67 }
68
69 #define TBM_SURFACE_RETURN_SET_ERR_IF_FAIL(cond, error, error_type) {\
70         if (!(cond)) {\
71                 TBM_ERR("'%s' failed.\n", #cond);\
72                 error = error_type;\
73                 _tbm_set_last_result(error_type);\
74                 _tbm_surface_mutex_unlock();\
75                 return;\
76         } \
77 }
78
79 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
80         if (!(cond)) {\
81                 TBM_ERR("'%s' failed.\n", #cond);\
82                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
83                 _tbm_surface_mutex_unlock();\
84                 return val;\
85         } \
86 }
87
88
89 #define TBM_SURFACE_RETURN_VAL_ERR_IF_FAIL(cond, val, error_type) {\
90         if (!(cond)) {\
91                 TBM_ERR("'%s' failed.\n", #cond);\
92                 _tbm_set_last_result(error_type);\
93                 _tbm_surface_mutex_unlock();\
94                 return val;\
95         } \
96 }
97
98 #define TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(cond, val, error, error_type) {\
99         if (!(cond)) {\
100                 TBM_ERR("'%s' failed.\n", #cond);\
101                 error = error_type;\
102                 _tbm_set_last_result(error_type);\
103                 _tbm_surface_mutex_unlock();\
104                 return val;\
105         } \
106 }
107
108 /* LCOV_EXCL_START */
109 static double
110 _tbm_surface_internal_get_time(void)
111 {
112         struct timespec tp;
113         unsigned int time;
114
115         clock_gettime(CLOCK_MONOTONIC, &tp);
116         time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
117
118         return time / 1000.0;
119 }
120
121 static void
122 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
123 {
124         LIST_DEL(&debug_data->item_link);
125
126         if (debug_data->key) free(debug_data->key);
127         if (debug_data->value) free(debug_data->value);
128         free(debug_data);
129 }
130
131 char *
132 _tbm_surface_internal_format_to_str(tbm_format format)
133 {
134         switch (format) {
135         case TBM_FORMAT_C8:
136                 return "TBM_FORMAT_C8";
137         case TBM_FORMAT_RGB332:
138                 return "TBM_FORMAT_RGB332";
139         case TBM_FORMAT_BGR233:
140                 return "TBM_FORMAT_BGR233";
141         case TBM_FORMAT_XRGB4444:
142                 return "TBM_FORMAT_XRGB4444";
143         case TBM_FORMAT_XBGR4444:
144                 return "TBM_FORMAT_XBGR4444";
145         case TBM_FORMAT_RGBX4444:
146                 return "TBM_FORMAT_RGBX4444";
147         case TBM_FORMAT_BGRX4444:
148                 return "TBM_FORMAT_BGRX4444";
149         case TBM_FORMAT_ARGB4444:
150                 return "TBM_FORMAT_ARGB4444";
151         case TBM_FORMAT_ABGR4444:
152                 return "TBM_FORMAT_ABGR4444";
153         case TBM_FORMAT_RGBA4444:
154                 return "TBM_FORMAT_RGBA4444";
155         case TBM_FORMAT_BGRA4444:
156                 return "TBM_FORMAT_BGRA4444";
157         case TBM_FORMAT_XRGB1555:
158                 return "TBM_FORMAT_XRGB1555";
159         case TBM_FORMAT_XBGR1555:
160                 return "TBM_FORMAT_XBGR1555";
161         case TBM_FORMAT_RGBX5551:
162                 return "TBM_FORMAT_RGBX5551";
163         case TBM_FORMAT_BGRX5551:
164                 return "TBM_FORMAT_BGRX5551";
165         case TBM_FORMAT_ARGB1555:
166                 return "TBM_FORMAT_ARGB1555";
167         case TBM_FORMAT_ABGR1555:
168                 return "TBM_FORMAT_ABGR1555";
169         case TBM_FORMAT_RGBA5551:
170                 return "TBM_FORMAT_RGBA5551";
171         case TBM_FORMAT_BGRA5551:
172                 return "TBM_FORMAT_BGRA5551";
173         case TBM_FORMAT_RGB565:
174                 return "TBM_FORMAT_RGB565";
175         case TBM_FORMAT_BGR565:
176                 return "TBM_FORMAT_BGR565";
177         case TBM_FORMAT_RGB888:
178                 return "TBM_FORMAT_RGB888";
179         case TBM_FORMAT_BGR888:
180                 return "TBM_FORMAT_BGR888";
181         case TBM_FORMAT_XRGB8888:
182                 return "TBM_FORMAT_XRGB8888";
183         case TBM_FORMAT_XBGR8888:
184                 return "TBM_FORMAT_XBGR8888";
185         case TBM_FORMAT_RGBX8888:
186                 return "TBM_FORMAT_RGBX8888";
187         case TBM_FORMAT_BGRX8888:
188                 return "TBM_FORMAT_BGRX8888";
189         case TBM_FORMAT_ARGB8888:
190                 return "TBM_FORMAT_ARGB8888";
191         case TBM_FORMAT_ABGR8888:
192                 return "TBM_FORMAT_ABGR8888";
193         case TBM_FORMAT_RGBA8888:
194                 return "TBM_FORMAT_RGBA8888";
195         case TBM_FORMAT_BGRA8888:
196                 return "TBM_FORMAT_BGRA8888";
197         case TBM_FORMAT_XRGB2101010:
198                 return "TBM_FORMAT_XRGB2101010";
199         case TBM_FORMAT_XBGR2101010:
200                 return "TBM_FORMAT_XBGR2101010";
201         case TBM_FORMAT_RGBX1010102:
202                 return "TBM_FORMAT_RGBX1010102";
203         case TBM_FORMAT_BGRX1010102:
204                 return "TBM_FORMAT_BGRX1010102";
205         case TBM_FORMAT_ARGB2101010:
206                 return "TBM_FORMAT_ARGB2101010";
207         case TBM_FORMAT_ABGR2101010:
208                 return "TBM_FORMAT_ABGR2101010";
209         case TBM_FORMAT_RGBA1010102:
210                 return "TBM_FORMAT_RGBA1010102";
211         case TBM_FORMAT_BGRA1010102:
212                 return "TBM_FORMAT_BGRA1010102";
213         case TBM_FORMAT_YUYV:
214                 return "TBM_FORMAT_YUYV";
215         case TBM_FORMAT_YVYU:
216                 return "TBM_FORMAT_YVYU";
217         case TBM_FORMAT_UYVY:
218                 return "TBM_FORMAT_UYVY";
219         case TBM_FORMAT_VYUY:
220                 return "TBM_FORMAT_VYUY";
221         case TBM_FORMAT_AYUV:
222                 return "TBM_FORMAT_AYUV";
223         case TBM_FORMAT_NV12:
224                 return "TBM_FORMAT_NV12";
225         case TBM_FORMAT_NV21:
226                 return "TBM_FORMAT_NV21";
227         case TBM_FORMAT_NV16:
228                 return "TBM_FORMAT_NV16";
229         case TBM_FORMAT_NV61:
230                 return "TBM_FORMAT_NV61";
231         case TBM_FORMAT_YUV410:
232                 return "TBM_FORMAT_YUV410";
233         case TBM_FORMAT_YVU410:
234                 return "TBM_FORMAT_YVU410";
235         case TBM_FORMAT_YUV411:
236                 return "TBM_FORMAT_YUV411";
237         case TBM_FORMAT_YVU411:
238                 return "TBM_FORMAT_YVU411";
239         case TBM_FORMAT_YUV420:
240                 return "TBM_FORMAT_YUV420";
241         case TBM_FORMAT_YVU420:
242                 return "TBM_FORMAT_YVU420";
243         case TBM_FORMAT_YUV422:
244                 return "TBM_FORMAT_YUV422";
245         case TBM_FORMAT_YVU422:
246                 return "TBM_FORMAT_YVU422";
247         case TBM_FORMAT_YUV444:
248                 return "TBM_FORMAT_YUV444";
249         case TBM_FORMAT_YVU444:
250                 return "TBM_FORMAT_YVU444";
251         case TBM_FORMAT_NV12MT:
252                 return "TBM_FORMAT_NV12MT";
253         default:
254                 return "unknwon";
255         }
256 }
257
258 void
259 _tbm_surface_mutex_lock(void)
260 {
261         pthread_mutex_lock(&tbm_surface_lock);
262 }
263
264 void
265 _tbm_surface_mutex_unlock(void)
266 {
267         pthread_mutex_unlock(&tbm_surface_lock);
268 }
269
270 static void
271 _init_surface_bufmgr(void)
272 {
273         g_surface_bufmgr = tbm_bufmgr_init(-1);
274 }
275
276 static void
277 _deinit_surface_bufmgr(void)
278 {
279         if (!g_surface_bufmgr)
280                 return;
281
282         tbm_bufmgr_deinit(g_surface_bufmgr);
283         g_surface_bufmgr = NULL;
284 }
285 /* LCOV_EXCL_STOP */
286
287 static int
288 _tbm_surface_internal_magic_check(tbm_surface_h surface)
289 {
290         if (surface->magic != TBM_SURFACE_MAGIC)
291                 return 0;
292
293         return 1;
294 }
295
296 static int
297 _tbm_surface_internal_is_valid(tbm_surface_h surface)
298 {
299         if (!surface) {
300                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
301                 TBM_ERR("error: No valid tbm_surface is NULL\n");
302                 return 0;
303         }
304
305         if (!_tbm_surface_internal_magic_check(surface)) {
306                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
307                 TBM_ERR("error: No valid tbm_surface(%p)\n", surface);
308                 return 0;
309         }
310
311         return 1;
312 }
313
314 static int
315 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
316                                        int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
317 {
318         TBM_RETURN_VAL_IF_FAIL(surface, 0);
319         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
320
321         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
322         struct _tbm_bufmgr *bufmgr = surf->bufmgr;
323         tbm_error_e error;
324
325         TBM_RETURN_VAL_IF_FAIL(bufmgr != NULL, 0);
326         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
327         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
328         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
329
330         error = tbm_module_bufmgr_get_plane_data(bufmgr->module, surf->info.format, plane_idx, surf->info.width, surf->info.height, size, offset, pitch, bo_idx);
331         if (error != TBM_ERROR_NONE) {
332                 _tbm_set_last_result(error);
333                 return 0;
334         }
335
336         return 1;
337 }
338
339 static void
340 _tbm_surface_internal_destroy(tbm_surface_h surface)
341 {
342         int i;
343         tbm_bufmgr bufmgr = surface->bufmgr;
344         tbm_user_data *old_data = NULL, *tmp = NULL;
345         tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
346         tbm_surface_destroy_func_info *func_info = NULL, *func_next = NULL;
347
348         if (!LIST_IS_EMPTY(&surface->destroy_funcs)) {
349                 LIST_FOR_EACH_ENTRY_SAFE(func_info, func_next, &surface->destroy_funcs, item_link) {
350                         func_info->destroy_func(surface, func_info->user_data);
351                 }
352                 TBM_DBG("free destroy_funcs %p\n", surface);
353                 LIST_FOR_EACH_ENTRY_SAFE(func_info, func_next, &surface->destroy_funcs, item_link) {
354                         LIST_DEL(&func_info->item_link);
355                         free(func_info);
356                 }
357         }
358
359         /* destory the user_data_list */
360         if (!LIST_IS_EMPTY(&surface->user_data_list)) {
361                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
362                         TBM_DBG("free user_data\n");
363                         user_data_delete(old_data);
364                 }
365         }
366
367         for (i = 0; i < surface->num_bos; i++) {
368                 surface->bos[i]->surface = NULL;
369
370                 tbm_bo_unref(surface->bos[i]);
371                 surface->bos[i] = NULL;
372         }
373
374         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
375                 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
376                         _tbm_surface_internal_debug_data_delete(debug_old_data);
377         }
378
379         LIST_DEL(&surface->item_link);
380         surface->magic = 0;
381
382         if (surface->hal_surface) {
383                 hal_tbm_surface_free(surface->hal_surface);
384                 surface->hal_surface = NULL;
385         }
386
387         free(surface);
388         surface = NULL;
389
390         if (bufmgr && LIST_IS_EMPTY(&bufmgr->surf_list)) {
391                 LIST_DELINIT(&bufmgr->surf_list);
392
393                 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
394                         LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
395                                 _tbm_surface_internal_debug_data_delete(debug_old_data);
396                         }
397                 }
398
399                 _deinit_surface_bufmgr();
400         }
401 }
402
403 /* LCOV_EXCL_START */
404 static int
405 _tbm_surface_check_file_is_symbolic_link(const char* path)
406 {
407         struct stat sb;
408
409         if (!path)
410                 return 0;
411
412         if (stat(path, &sb) != 0)
413                 return 0;
414
415         if (S_ISLNK(sb.st_mode))
416                 return 1;
417
418         return 0;
419 }
420 /* LCOV_EXCL_STOP */
421
422 static int
423 _tbm_surface_internal_get_num_planes(tbm_format format)
424 {
425         int num_planes = 0;
426
427         switch (format) {
428         case TBM_FORMAT_C8:
429         case TBM_FORMAT_RGB332:
430         case TBM_FORMAT_BGR233:
431         case TBM_FORMAT_XRGB4444:
432         case TBM_FORMAT_XBGR4444:
433         case TBM_FORMAT_RGBX4444:
434         case TBM_FORMAT_BGRX4444:
435         case TBM_FORMAT_ARGB4444:
436         case TBM_FORMAT_ABGR4444:
437         case TBM_FORMAT_RGBA4444:
438         case TBM_FORMAT_BGRA4444:
439         case TBM_FORMAT_XRGB1555:
440         case TBM_FORMAT_XBGR1555:
441         case TBM_FORMAT_RGBX5551:
442         case TBM_FORMAT_BGRX5551:
443         case TBM_FORMAT_ARGB1555:
444         case TBM_FORMAT_ABGR1555:
445         case TBM_FORMAT_RGBA5551:
446         case TBM_FORMAT_BGRA5551:
447         case TBM_FORMAT_RGB565:
448         case TBM_FORMAT_BGR565:
449         case TBM_FORMAT_RGB888:
450         case TBM_FORMAT_BGR888:
451         case TBM_FORMAT_XRGB8888:
452         case TBM_FORMAT_XBGR8888:
453         case TBM_FORMAT_RGBX8888:
454         case TBM_FORMAT_BGRX8888:
455         case TBM_FORMAT_ARGB8888:
456         case TBM_FORMAT_ABGR8888:
457         case TBM_FORMAT_RGBA8888:
458         case TBM_FORMAT_BGRA8888:
459         case TBM_FORMAT_XRGB2101010:
460         case TBM_FORMAT_XBGR2101010:
461         case TBM_FORMAT_RGBX1010102:
462         case TBM_FORMAT_BGRX1010102:
463         case TBM_FORMAT_ARGB2101010:
464         case TBM_FORMAT_ABGR2101010:
465         case TBM_FORMAT_RGBA1010102:
466         case TBM_FORMAT_BGRA1010102:
467         case TBM_FORMAT_YUYV:
468         case TBM_FORMAT_YVYU:
469         case TBM_FORMAT_UYVY:
470         case TBM_FORMAT_VYUY:
471         case TBM_FORMAT_AYUV:
472                 num_planes = 1;
473                 break;
474         case TBM_FORMAT_NV12:
475         case TBM_FORMAT_NV12MT:
476         case TBM_FORMAT_NV21:
477         case TBM_FORMAT_NV16:
478         case TBM_FORMAT_NV61:
479                 num_planes = 2;
480                 break;
481         case TBM_FORMAT_YUV410:
482         case TBM_FORMAT_YVU410:
483         case TBM_FORMAT_YUV411:
484         case TBM_FORMAT_YVU411:
485         case TBM_FORMAT_YUV420:
486         case TBM_FORMAT_YVU420:
487         case TBM_FORMAT_YUV422:
488         case TBM_FORMAT_YVU422:
489         case TBM_FORMAT_YUV444:
490         case TBM_FORMAT_YVU444:
491                 num_planes = 3;
492                 break;
493
494         default:
495                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
496                 break;
497         }
498
499         return num_planes;
500 }
501
502 static int
503 _tbm_surface_internal_get_bpp(tbm_format format)
504 {
505
506         int bpp = 0;
507
508         switch (format) {
509         case TBM_FORMAT_C8:
510         case TBM_FORMAT_RGB332:
511         case TBM_FORMAT_BGR233:
512                 bpp = 8;
513                 break;
514         case TBM_FORMAT_XRGB4444:
515         case TBM_FORMAT_XBGR4444:
516         case TBM_FORMAT_RGBX4444:
517         case TBM_FORMAT_BGRX4444:
518         case TBM_FORMAT_ARGB4444:
519         case TBM_FORMAT_ABGR4444:
520         case TBM_FORMAT_RGBA4444:
521         case TBM_FORMAT_BGRA4444:
522         case TBM_FORMAT_XRGB1555:
523         case TBM_FORMAT_XBGR1555:
524         case TBM_FORMAT_RGBX5551:
525         case TBM_FORMAT_BGRX5551:
526         case TBM_FORMAT_ARGB1555:
527         case TBM_FORMAT_ABGR1555:
528         case TBM_FORMAT_RGBA5551:
529         case TBM_FORMAT_BGRA5551:
530         case TBM_FORMAT_RGB565:
531         case TBM_FORMAT_BGR565:
532                 bpp = 16;
533                 break;
534         case TBM_FORMAT_RGB888:
535         case TBM_FORMAT_BGR888:
536                 bpp = 24;
537                 break;
538         case TBM_FORMAT_XRGB8888:
539         case TBM_FORMAT_XBGR8888:
540         case TBM_FORMAT_RGBX8888:
541         case TBM_FORMAT_BGRX8888:
542         case TBM_FORMAT_ARGB8888:
543         case TBM_FORMAT_ABGR8888:
544         case TBM_FORMAT_RGBA8888:
545         case TBM_FORMAT_BGRA8888:
546         case TBM_FORMAT_XRGB2101010:
547         case TBM_FORMAT_XBGR2101010:
548         case TBM_FORMAT_RGBX1010102:
549         case TBM_FORMAT_BGRX1010102:
550         case TBM_FORMAT_ARGB2101010:
551         case TBM_FORMAT_ABGR2101010:
552         case TBM_FORMAT_RGBA1010102:
553         case TBM_FORMAT_BGRA1010102:
554         case TBM_FORMAT_YUYV:
555         case TBM_FORMAT_YVYU:
556         case TBM_FORMAT_UYVY:
557         case TBM_FORMAT_VYUY:
558         case TBM_FORMAT_AYUV:
559                 bpp = 32;
560                 break;
561         case TBM_FORMAT_NV12:
562         case TBM_FORMAT_NV12MT:
563         case TBM_FORMAT_NV21:
564                 bpp = 12;
565                 break;
566         case TBM_FORMAT_NV16:
567         case TBM_FORMAT_NV61:
568                 bpp = 16;
569                 break;
570         case TBM_FORMAT_YUV410:
571         case TBM_FORMAT_YVU410:
572                 bpp = 9;
573                 break;
574         case TBM_FORMAT_YUV411:
575         case TBM_FORMAT_YVU411:
576         case TBM_FORMAT_YUV420:
577         case TBM_FORMAT_YVU420:
578                 bpp = 12;
579                 break;
580         case TBM_FORMAT_YUV422:
581         case TBM_FORMAT_YVU422:
582                 bpp = 16;
583                 break;
584         case TBM_FORMAT_YUV444:
585         case TBM_FORMAT_YVU444:
586                 bpp = 24;
587                 break;
588         default:
589                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
590                 break;
591         }
592
593         return bpp;
594 }
595
596 static struct _tbm_surface *
597 _tbm_surface_internal_create_surface(tbm_bufmgr bufmgr, int width, int height, int format, int flags, tbm_error_e *error)
598 {
599         struct _tbm_surface *surf = NULL;
600         uint32_t size = 0, offset = 0, stride = 0, bo_size = 0;
601         int i, j, bo_idx;
602
603         surf = calloc(1, sizeof(struct _tbm_surface));
604         if (!surf) {
605                 /* LCOV_EXCL_START */
606                 TBM_ERR("fail to alloc surf\n");
607                 *error = TBM_ERROR_OUT_OF_MEMORY;
608                 goto alloc_surf_fail;
609                 /* LCOV_EXCL_STOP */
610         }
611
612         surf->magic = TBM_SURFACE_MAGIC;
613         surf->bufmgr = bufmgr;
614         surf->info.width = width;
615         surf->info.height = height;
616         surf->info.format = format;
617         surf->info.bpp = _tbm_surface_internal_get_bpp(format);
618         if (!surf->info.bpp) {
619                 TBM_ERR("fail to get bpp from format(%d), error(%s)\n", format, tbm_error_str(*error));
620                 *error = tbm_get_last_error();
621                 goto bpp_fail;
622         }
623
624         surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
625         if (!surf->info.num_planes) {
626                 TBM_ERR("fail to get num_planes from format(%d), error(%s)\n", format, tbm_error_str(*error));
627                 *error = tbm_get_last_error();
628                 goto num_planes_fail;
629         }
630         surf->refcnt = 1;
631
632         /* get size, stride and offset bo_idx */
633         for (i = 0; i < surf->info.num_planes; i++) {
634                 if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
635                         TBM_ERR("fail to query plane data\n");
636                         *error = tbm_get_last_error();
637                         goto query_plane_data_fail;
638                 }
639
640                 surf->info.planes[i].size = size;
641                 surf->info.planes[i].offset = offset;
642                 surf->info.planes[i].stride = stride;
643                 surf->planes_bo_idx[i] = bo_idx;
644         }
645
646         surf->num_bos = 1;
647
648         for (i = 0; i < surf->info.num_planes; i++) {
649                 surf->info.size += surf->info.planes[i].size;
650
651                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
652                         surf->num_bos = surf->planes_bo_idx[i] + 1;
653         }
654
655         surf->flags = flags;
656
657         for (i = 0; i < surf->num_bos; i++) {
658                 bo_size = 0;
659                 for (j = 0; j < surf->info.num_planes; j++) {
660                         if (surf->planes_bo_idx[j] == i)
661                                 bo_size += surf->info.planes[j].size;
662                 }
663
664                 surf->bos[i] = tbm_bufmgr_internal_alloc_bo_with_format(bufmgr, format, i, width, height, surf->info.bpp/8, flags, error);
665                 if (!surf->bos[i]) {
666                         surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
667                         if (!surf->bos[i]) {
668                                 TBM_ERR("fail to alloc bo idx:%d\n", i);
669                                 *error = tbm_get_last_error();
670                                 goto alloc_bo_fail;
671                         }
672                 }
673
674                 _tbm_bo_set_surface(surf->bos[i], surf);
675         }
676
677         *error = TBM_ERROR_NONE;
678
679         return surf;
680
681 alloc_bo_fail:
682         for (j = 0; j < i; j++) {
683                 if (surf->bos[j])
684                         tbm_bo_unref(surf->bos[j]);
685         }
686 query_plane_data_fail:
687 bpp_fail:
688 num_planes_fail:
689         free(surf);
690 alloc_surf_fail:
691
692         return NULL;
693 }
694
695 static struct _tbm_surface *
696 _tbm_surface_internal_hal_tbm_create_surface(tbm_bufmgr bufmgr, int width, int height, int format, int flags, tbm_error_e *error)
697 {
698         struct _tbm_surface *surf = NULL;
699         uint32_t size = 0, offset = 0, stride = 0, bo_size = 0;
700         int i, j, bo_idx;
701         hal_tbm_surface *hal_surface = NULL;
702         hal_tbm_bo **hal_bos = NULL;
703         int num_bos = 0;
704
705         surf = calloc(1, sizeof(struct _tbm_surface));
706         if (!surf) {
707                 /* LCOV_EXCL_START */
708                 TBM_ERR("fail to alloc surf");
709                 *error = TBM_ERROR_OUT_OF_MEMORY;
710                 goto alloc_surf_fail;
711                 /* LCOV_EXCL_STOP */
712         }
713         surf->refcnt = 1;
714
715         surf->magic = TBM_SURFACE_MAGIC;
716         surf->bufmgr = bufmgr;
717         surf->info.width = width;
718         surf->info.height = height;
719         surf->info.format = format;
720         surf->info.bpp = _tbm_surface_internal_get_bpp(format);
721         if (!surf->info.bpp) {
722                 TBM_ERR("fail to get bpp from format(%d), error(%s)", format, tbm_error_str(*error));
723                 *error = tbm_get_last_error();
724                 goto bpp_fail;
725         }
726         surf->flags = flags;
727
728         // get number of planes
729         surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
730         if (!surf->info.num_planes) {
731                 TBM_ERR("fail to get num_planes from format(%d), error(%s)", format, tbm_error_str(*error));
732                 *error = tbm_get_last_error();
733                 goto num_planes_fail;
734         }
735
736         hal_surface = hal_tbm_bufmgr_alloc_surface(bufmgr->hal_bufmgr, (uint32_t)width, (uint32_t)height, (hal_tbm_format)format, (hal_tbm_bo_memory_type)flags, NULL, 0, (hal_tbm_error *)error);
737         if (hal_surface) {
738                 // set hal_surface
739                 surf->hal_surface = hal_surface;
740
741                 // set infomation of planes
742                 for (i = 0; i < surf->info.num_planes; i++) {
743                         *error = (tbm_error_e)hal_tbm_surface_get_plane_data(hal_surface, i, &size, &offset, &stride, &bo_idx);
744                         if (*error != TBM_ERROR_NONE) {
745                                 goto query_plane_data_fail;
746                         }
747                         surf->info.planes[i].size = size;
748                         surf->info.planes[i].offset = offset;
749                         surf->info.planes[i].stride = stride;
750                         surf->planes_bo_idx[i] = bo_idx;
751                 }
752
753                 // set infomation of bos
754                 hal_bos = hal_tbm_surface_get_bos(hal_surface, &num_bos, (hal_tbm_error *)error);
755                 if (!hal_bos) {
756                         TBM_ERR("fail to get bos, error(%s)", tbm_error_str(*error));
757                         goto get_bos_fail;
758                 }
759                 surf->num_bos = num_bos;
760
761                 for (i = 0; i < surf->info.num_planes; i++) {
762                         surf->info.size += surf->info.planes[i].size;
763
764                         if (surf->num_bos < surf->planes_bo_idx[i] + 1)
765                                 surf->num_bos = surf->planes_bo_idx[i] + 1;
766                 }
767
768                 for (i = 0; i < num_bos; i++) {
769                         surf->bos[i] = tbm_bo_alloc_with_bo_data(bufmgr, (tbm_backend_bo_data *)hal_bos[i], flags);
770                         if (!surf->bos[i]) {
771                                 TBM_ERR("fail to alloc bo idx:%d", i);
772                                 *error = tbm_get_last_error();
773                                 goto get_bo_fail;
774                         }
775
776                         _tbm_bo_set_surface(surf->bos[i], surf);
777                 }
778         } else {
779                 // set infomation of planes
780                 for (i = 0; i < surf->info.num_planes; i++) {
781                         if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
782                                 TBM_ERR("fail to query plane data");
783                                 *error = tbm_get_last_error();
784                                 goto query_plane_data_fail;
785                         }
786                         surf->info.planes[i].size = size;
787                         surf->info.planes[i].offset = offset;
788                         surf->info.planes[i].stride = stride;
789                         surf->planes_bo_idx[i] = bo_idx;
790                 }
791
792                 // count number of bos
793                 surf->num_bos = 1;
794                 for (i = 0; i < surf->info.num_planes; i++) {
795                         surf->info.size += surf->info.planes[i].size;
796
797                         if (surf->num_bos < surf->planes_bo_idx[i] + 1)
798                                 surf->num_bos = surf->planes_bo_idx[i] + 1;
799                 }
800
801                 // set infomation of bos
802                 for (i = 0; i < surf->num_bos; i++) {
803                         bo_size = 0;
804                         for (j = 0; j < surf->info.num_planes; j++) {
805                                 if (surf->planes_bo_idx[j] == i)
806                                         bo_size += surf->info.planes[j].size;
807                         }
808
809                         surf->bos[i] = tbm_bufmgr_internal_alloc_bo_with_format(bufmgr, format, i, width, height, surf->info.bpp / 8, flags, error);
810                         if (*error == TBM_ERROR_NOT_SUPPORTED) {
811                                 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
812                                 if (!surf->bos[i]) {
813                                         TBM_ERR("fail to alloc bo idx:%d", i);
814                                         *error = tbm_get_last_error();
815                                         goto get_bo_fail;
816                                 }
817                         }
818
819                         _tbm_bo_set_surface(surf->bos[i], surf);
820                 }
821         }
822
823         *error = TBM_ERROR_NONE;
824
825         return surf;
826
827 get_bo_fail:
828 get_bos_fail:
829 query_plane_data_fail:
830         if (hal_surface) {
831                 hal_tbm_surface_free(hal_surface);
832         } else {
833                 for (j = 0; j < i; j++) {
834                         if (surf->bos[j])
835                                 tbm_bo_unref(surf->bos[j]);
836                 }
837         }
838 num_planes_fail:
839 bpp_fail:
840         if (surf)
841                 free(surf);
842 alloc_surf_fail:
843
844         return NULL;
845 }
846
847 static struct _tbm_surface *
848 _tbm_surface_internal_hal_tbm_import_surface(tbm_bufmgr bufmgr, int width, int height, int format, tbm_surface_buffer_data *buffer_data, tbm_error_e *error)
849 {
850         struct _tbm_surface *surf = NULL;
851         uint32_t size = 0, offset = 0, stride = 0;
852         int i, j, bo_idx;
853         hal_tbm_surface *hal_surface = NULL;
854         hal_tbm_bo **hal_bos = NULL;
855         int num_bos = 0;
856         int flags;
857
858         surf = calloc(1, sizeof(struct _tbm_surface));
859         if (!surf) {
860                 /* LCOV_EXCL_START */
861                 TBM_ERR("fail to alloc surf");
862                 *error = TBM_ERROR_OUT_OF_MEMORY;
863                 goto alloc_surf_fail;
864                 /* LCOV_EXCL_STOP */
865         }
866         surf->refcnt = 1;
867
868         surf->magic = TBM_SURFACE_MAGIC;
869         surf->bufmgr = bufmgr;
870         surf->info.width = width;
871         surf->info.height = height;
872         surf->info.format = format;
873         surf->info.bpp = _tbm_surface_internal_get_bpp(format);
874         if (!surf->info.bpp) {
875                 TBM_ERR("fail to get bpp from format(%d), error(%s)", format, tbm_error_str(*error));
876                 *error = tbm_get_last_error();
877                 goto bpp_fail;
878         }
879
880         // get number of planes
881         surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
882         if (!surf->info.num_planes) {
883                 TBM_ERR("fail to get num_planes from format(%d), error(%s)", format, tbm_error_str(*error));
884                 *error = tbm_get_last_error();
885                 goto num_planes_fail;
886         }
887
888         // import surface
889         hal_surface = hal_tbm_bufmgr_import_surface(bufmgr->hal_bufmgr, 
890                                                                                         (uint32_t)width,
891                                                                                         (uint32_t)height,
892                                                                                         (hal_tbm_format)format,
893                                                                                         (hal_tbm_surface_buffer_data *)buffer_data,
894                                                                                         (hal_tbm_error *)error);
895         if (!hal_surface) {
896                 TBM_ERR("hal_tbm_bufmgr_import_surface failed.(width:%d height:%d format:%d error:%s)",
897                                 width, height, format, tbm_error_str(*error));
898                 goto import_surface_fail;
899         }
900         surf->hal_surface = hal_surface;
901
902         // set infomation of planes
903         for (i = 0; i < surf->info.num_planes; i++) {
904                 *error = (tbm_error_e)hal_tbm_surface_get_plane_data(hal_surface, i, &size, &offset, &stride, &bo_idx);
905                 if (*error != TBM_ERROR_NONE) {
906                         goto query_plane_data_fail;
907                 }
908                 surf->info.planes[i].size = size;
909                 surf->info.planes[i].offset = offset;
910                 surf->info.planes[i].stride = stride;
911                 surf->planes_bo_idx[i] = bo_idx;
912         }
913
914         // set infomation of bos
915         hal_bos = hal_tbm_surface_get_bos(hal_surface, &num_bos, (hal_tbm_error *)error);
916         if (!hal_bos) {
917                 TBM_ERR("fail to get bos, error(%s)", tbm_error_str(*error));
918                 goto get_bos_fail;
919         }
920         surf->num_bos = num_bos;
921
922         for (i = 0; i < surf->info.num_planes; i++) {
923                 surf->info.size += surf->info.planes[i].size;
924
925                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
926                         surf->num_bos = surf->planes_bo_idx[i] + 1;
927         }
928
929         // get memory_types(bo flags)
930         flags =  (int)hal_tbm_bo_get_memory_types(hal_bos[0], (hal_tbm_error *)error);
931         if (*error != TBM_ERROR_NONE) {
932                 TBM_ERR("hal_tbm_bo_get_memory_types failed.");
933                 goto get_memory_types_fail;
934         }
935         surf->flags = flags;
936
937         for (i = 0; i < num_bos; i++) {
938                 surf->bos[i] = tbm_bo_alloc_with_bo_data(bufmgr, (tbm_backend_bo_data *)hal_bos[i], flags);
939                 if (!surf->bos[i]) {
940                         TBM_ERR("fail to alloc bo idx:%d", i);
941                         *error = tbm_get_last_error();
942                         goto get_bo_fail;
943                 }
944
945                 _tbm_bo_set_surface(surf->bos[i], surf);
946         }
947
948         *error = TBM_ERROR_NONE;
949
950         return surf;
951
952 get_bo_fail:
953 get_memory_types_fail:
954 get_bos_fail:
955 query_plane_data_fail:
956         if (hal_surface) {
957                 hal_tbm_surface_free(hal_surface);
958         } else {
959                 for (j = 0; j < i; j++) {
960                         if (surf->bos[j])
961                                 tbm_bo_unref(surf->bos[j]);
962                 }
963         }
964 import_surface_fail:
965 num_planes_fail:
966 bpp_fail:
967         if (surf)
968                 free(surf);
969 alloc_surf_fail:
970
971         return NULL;
972 }
973
974 int
975 tbm_surface_internal_is_valid(tbm_surface_h surface)
976 {
977         int ret = 0;
978
979         _tbm_surface_mutex_lock();
980         _tbm_set_last_result(TBM_ERROR_NONE);
981
982         /* Return silently if surface is null. */
983         if (!surface) {
984                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
985                 _tbm_surface_mutex_unlock();
986                 return 0;
987         }
988
989         ret = _tbm_surface_internal_is_valid(surface);
990
991         _tbm_surface_mutex_unlock();
992
993         return ret;
994 }
995
996 int
997 tbm_surface_internal_query_supported_formats(uint32_t **formats,
998                 uint32_t *num)
999 {
1000         struct _tbm_bufmgr *bufmgr;
1001         bool bufmgr_initialized = false;
1002         tbm_error_e error;
1003
1004         _tbm_surface_mutex_lock();
1005         _tbm_set_last_result(TBM_ERROR_NONE);
1006
1007         TBM_SURFACE_RETURN_VAL_IF_FAIL(formats, 0);
1008         TBM_SURFACE_RETURN_VAL_IF_FAIL(num, 0);
1009
1010         if (!g_surface_bufmgr) {
1011                 _init_surface_bufmgr();
1012                 if (!g_surface_bufmgr) {
1013                         TBM_ERR("fail bufmgr initialization\n");
1014                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1015                         goto fail;
1016                 }
1017                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
1018                 bufmgr_initialized = true;
1019         }
1020
1021         bufmgr = g_surface_bufmgr;
1022
1023         error = tbm_module_bufmgr_get_supported_formats(bufmgr->module, formats, num);
1024         if (error != TBM_ERROR_NONE) {
1025                 _tbm_set_last_result(error);
1026                 goto fail;
1027         }
1028
1029         TBM_TRACE_SURFACE_INTERNAL("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
1030
1031         if (bufmgr_initialized) {
1032                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
1033                 _deinit_surface_bufmgr();
1034         }
1035
1036         _tbm_surface_mutex_unlock();
1037
1038         return 1;
1039
1040 /* LCOV_EXCL_START */
1041 fail:
1042         if (bufmgr_initialized) {
1043                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
1044                 _deinit_surface_bufmgr();
1045         }
1046         _tbm_surface_mutex_unlock();
1047
1048         TBM_ERR("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
1049
1050         return 0;
1051 /* LCOV_EXCL_STOP */
1052 }
1053
1054 int
1055 tbm_surface_internal_get_num_planes(tbm_format format)
1056 {
1057         int num_planes = 0;
1058
1059         _tbm_surface_mutex_lock();
1060         _tbm_set_last_result(TBM_ERROR_NONE);
1061
1062         num_planes = _tbm_surface_internal_get_num_planes(format);
1063         if (!num_planes) {
1064                 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
1065                 _tbm_surface_mutex_unlock();
1066                 return 0;
1067         }
1068
1069         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
1070
1071         _tbm_surface_mutex_unlock();
1072
1073         return num_planes;
1074 }
1075
1076 int
1077 tbm_surface_internal_get_bpp(tbm_format format)
1078 {
1079         int bpp = 0;
1080
1081         _tbm_surface_mutex_lock();
1082         _tbm_set_last_result(TBM_ERROR_NONE);
1083
1084         bpp = _tbm_surface_internal_get_bpp(format);
1085         if (!bpp) {
1086                 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
1087                 _tbm_surface_mutex_unlock();
1088                 return 0;
1089         }
1090
1091         _tbm_surface_mutex_unlock();
1092
1093         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
1094
1095         return bpp;
1096 }
1097
1098 tbm_surface_h
1099 tbm_surface_internal_create_with_flags(int width, int height,
1100                                        int format, int flags)
1101 {
1102         struct _tbm_bufmgr *bufmgr;
1103         struct _tbm_surface *surf = NULL;
1104         tbm_error_e error = TBM_ERROR_INVALID_OPERATION;
1105         bool bufmgr_initialized = false;
1106
1107         _tbm_surface_mutex_lock();
1108         _tbm_set_last_result(TBM_ERROR_NONE);
1109
1110         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, NULL);
1111         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, NULL);
1112
1113         if (!g_surface_bufmgr) {
1114                 _init_surface_bufmgr();
1115                 if (!g_surface_bufmgr) {
1116                         TBM_ERR("fail bufmgr initialization\n");
1117                         error = TBM_ERROR_INVALID_OPERATION;
1118                         goto check_valid_fail;
1119                 }
1120                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
1121                 bufmgr_initialized = true;
1122         }
1123
1124         bufmgr = g_surface_bufmgr;
1125         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
1126                 TBM_ERR("The bufmgr is invalid\n");
1127                 error = TBM_ERROR_INVALID_PARAMETER;
1128                 goto check_valid_fail;
1129         }
1130
1131         if (bufmgr->use_hal_tbm) {
1132                 surf = _tbm_surface_internal_hal_tbm_create_surface(bufmgr, width, height, format, flags, &error);
1133                 if (!surf) {
1134                         TBM_ERR("_tbm_surface_internal_hal_tbm_create_surface failed.");
1135                         goto surface_alloc_fail;
1136                 }
1137         } else {
1138                 surf = _tbm_surface_internal_create_surface(bufmgr, width, height, format, flags, &error);
1139                 if (!surf) {
1140                         TBM_ERR("_tbm_surface_internal_create_surface failed.");
1141                         goto surface_alloc_fail;
1142                 }
1143         }
1144
1145         TBM_TRACE_SURFACE_INTERNAL("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n",
1146                         width, height, _tbm_surface_internal_format_to_str(format), flags, surf);
1147
1148         LIST_INITHEAD(&surf->user_data_list);
1149         LIST_INITHEAD(&surf->debug_data_list);
1150         LIST_INITHEAD(&surf->destroy_funcs);
1151
1152         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1153
1154         _tbm_set_last_result(error);
1155         _tbm_surface_mutex_unlock();
1156
1157         return surf;
1158
1159 /* LCOV_EXCL_START */
1160
1161 surface_alloc_fail:
1162 check_valid_fail:
1163         if (bufmgr_initialized && bufmgr) {
1164                 LIST_DELINIT(&bufmgr->surf_list);
1165                 _deinit_surface_bufmgr();
1166         }
1167
1168         TBM_ERR("error: width(%d) height(%d) format(%s) flags(%d)\n",
1169                 width, height, _tbm_surface_internal_format_to_str(format), flags);
1170
1171         _tbm_set_last_result(error);
1172         _tbm_surface_mutex_unlock();
1173
1174 /* LCOV_EXCL_STOP */
1175
1176         return NULL;
1177 }
1178
1179 tbm_surface_h
1180 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
1181                                      tbm_bo *bos, int num)
1182 {
1183         struct _tbm_bufmgr *bufmgr;
1184         struct _tbm_surface *surf = NULL;
1185         int i;
1186         bool bufmgr_initialized = false;
1187
1188         _tbm_surface_mutex_lock();
1189         _tbm_set_last_result(TBM_ERROR_NONE);
1190
1191         TBM_SURFACE_RETURN_VAL_IF_FAIL(bos, NULL);
1192         TBM_SURFACE_RETURN_VAL_IF_FAIL(info, NULL);
1193         TBM_SURFACE_RETURN_VAL_IF_FAIL(info->num_planes > 0, NULL);
1194         TBM_SURFACE_RETURN_VAL_IF_FAIL(num > 0, NULL);
1195         TBM_SURFACE_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
1196
1197         if (!g_surface_bufmgr) {
1198                 _init_surface_bufmgr();
1199                 if (!g_surface_bufmgr) {
1200                         TBM_ERR("fail bufmgr initialization\n");
1201                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1202                         goto check_valid_fail;
1203                 }
1204                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
1205                 bufmgr_initialized = true;
1206         }
1207
1208         bufmgr = g_surface_bufmgr;
1209         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
1210                 TBM_ERR("fail to validate the Bufmgr.\n");
1211                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1212                 goto check_valid_fail;
1213         }
1214
1215         surf = calloc(1, sizeof(struct _tbm_surface));
1216         if (!surf) {
1217                 /* LCOV_EXCL_START */
1218                 TBM_ERR("fail to allocate struct _tbm_surface.\n");
1219                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1220                 goto alloc_surf_fail;
1221                 /* LCOV_EXCL_STOP */
1222         }
1223
1224         surf->magic = TBM_SURFACE_MAGIC;
1225         surf->bufmgr = bufmgr;
1226         surf->info.width = info->width;
1227         surf->info.height = info->height;
1228         surf->info.format = info->format;
1229         if (info->bpp > 0)
1230                 surf->info.bpp = info->bpp;
1231         else {
1232                 surf->info.bpp = _tbm_surface_internal_get_bpp(info->format);
1233                 if (!surf->info.bpp) {
1234                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1235                         goto bpp_fail;
1236                 }
1237         }
1238         surf->info.num_planes = info->num_planes;
1239         surf->refcnt = 1;
1240
1241         /* get size, stride and offset */
1242         for (i = 0; i < info->num_planes; i++) {
1243                 surf->info.planes[i].offset = info->planes[i].offset;
1244                 surf->info.planes[i].stride = info->planes[i].stride;
1245
1246                 if (info->planes[i].size > 0)
1247                         surf->info.planes[i].size = info->planes[i].size;
1248                 else {
1249                         uint32_t size = 0, offset = 0, stride = 0;
1250                         int32_t bo_idx = 0;
1251
1252                         if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
1253                                 TBM_ERR("fail to get plane_data. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1254                                 goto plane_data_fail;
1255                         }
1256                         surf->info.planes[i].size = size;
1257                 }
1258
1259                 if (num == 1)
1260                         surf->planes_bo_idx[i] = 0;
1261                 else
1262                         surf->planes_bo_idx[i] = i;
1263         }
1264
1265         if (info->size > 0) {
1266                 surf->info.size = info->size;
1267         } else {
1268                 surf->info.size = 0;
1269                 for (i = 0; i < info->num_planes; i++)
1270                         surf->info.size += surf->info.planes[i].size;
1271         }
1272
1273         surf->flags = TBM_BO_DEFAULT;
1274
1275         /* create only one bo */
1276         surf->num_bos = num;
1277         for (i = 0; i < num; i++) {
1278                 if (bos[i] == NULL) {
1279                         TBM_ERR("bos[%d] is null.\n", i);
1280                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1281                         goto check_bo_fail;
1282                 }
1283
1284                 surf->bos[i] = tbm_bo_ref(bos[i]);
1285                 _tbm_bo_set_surface(bos[i], surf);
1286         }
1287
1288         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
1289                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
1290
1291         LIST_INITHEAD(&surf->user_data_list);
1292         LIST_INITHEAD(&surf->debug_data_list);
1293         LIST_INITHEAD(&surf->destroy_funcs);
1294
1295         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1296
1297         _tbm_surface_mutex_unlock();
1298
1299         return surf;
1300
1301 /* LCOV_EXCL_START */
1302 check_bo_fail:
1303 plane_data_fail:
1304 bpp_fail:
1305         for (i = 0; i < num; i++) {
1306                 if (surf->bos[i])
1307                         tbm_bo_unref(surf->bos[i]);
1308         }
1309         free(surf);
1310 alloc_surf_fail:
1311 check_valid_fail:
1312         if (bufmgr_initialized && bufmgr) {
1313                 LIST_DELINIT(&bufmgr->surf_list);
1314                 _deinit_surface_bufmgr();
1315         }
1316         _tbm_surface_mutex_unlock();
1317
1318         TBM_ERR("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
1319                         info->width, info->height,
1320                         _tbm_surface_internal_format_to_str(info->format), num);
1321 /* LCOV_EXCL_STOP */
1322
1323         return NULL;
1324 }
1325
1326 void
1327 tbm_surface_internal_destroy(tbm_surface_h surface)
1328 {
1329         _tbm_surface_mutex_lock();
1330         _tbm_set_last_result(TBM_ERROR_NONE);
1331
1332         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1333
1334         surface->refcnt--;
1335
1336         if (surface->refcnt > 0) {
1337                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1338                 _tbm_surface_mutex_unlock();
1339                 return;
1340         }
1341
1342         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1343
1344         if (surface->refcnt == 0)
1345                 _tbm_surface_internal_destroy(surface);
1346         else // if (surface->refcnt < 0)
1347                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1348
1349         _tbm_surface_mutex_unlock();
1350 }
1351
1352 void
1353 tbm_surface_internal_ref(tbm_surface_h surface)
1354 {
1355         _tbm_surface_mutex_lock();
1356         _tbm_set_last_result(TBM_ERROR_NONE);
1357
1358         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1359
1360         surface->refcnt++;
1361
1362         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1363
1364         _tbm_surface_mutex_unlock();
1365 }
1366
1367 void
1368 tbm_surface_internal_unref(tbm_surface_h surface)
1369 {
1370         _tbm_surface_mutex_lock();
1371         _tbm_set_last_result(TBM_ERROR_NONE);
1372
1373         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1374
1375         surface->refcnt--;
1376
1377         if (surface->refcnt > 0) {
1378                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1379                 _tbm_surface_mutex_unlock();
1380                 return;
1381         }
1382
1383         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1384
1385         if (surface->refcnt == 0)
1386                 _tbm_surface_internal_destroy(surface);
1387
1388         _tbm_surface_mutex_unlock();
1389 }
1390
1391 int
1392 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
1393 {
1394         struct _tbm_surface *surf;
1395         int num;
1396
1397         _tbm_surface_mutex_lock();
1398         _tbm_set_last_result(TBM_ERROR_NONE);
1399
1400         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1401
1402         surf = (struct _tbm_surface *)surface;
1403         num = surf->num_bos;
1404
1405         if (!num)
1406                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1407
1408         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) num_bos(%d)\n", surface, num);
1409
1410         _tbm_surface_mutex_unlock();
1411
1412         return num;
1413 }
1414
1415 tbm_bo
1416 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
1417 {
1418         struct _tbm_surface *surf;
1419         tbm_bo bo;
1420
1421         _tbm_surface_mutex_lock();
1422         _tbm_set_last_result(TBM_ERROR_NONE);
1423
1424         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
1425         TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
1426
1427         surf = (struct _tbm_surface *)surface;
1428         bo = surf->bos[bo_idx];
1429
1430         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
1431
1432         _tbm_surface_mutex_unlock();
1433
1434         return bo;
1435 }
1436
1437 unsigned int
1438 tbm_surface_internal_get_size(tbm_surface_h surface)
1439 {
1440         struct _tbm_surface *surf;
1441         unsigned int size;
1442
1443         _tbm_surface_mutex_lock();
1444         _tbm_set_last_result(TBM_ERROR_NONE);
1445
1446         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1447
1448         surf = (struct _tbm_surface *)surface;
1449         size = surf->info.size;
1450
1451         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) size(%u)\n", surface, size);
1452
1453         _tbm_surface_mutex_unlock();
1454
1455         return size;
1456 }
1457
1458 int
1459 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1460                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
1461 {
1462         struct _tbm_surface *surf;
1463
1464         _tbm_surface_mutex_lock();
1465         _tbm_set_last_result(TBM_ERROR_NONE);
1466
1467         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1468         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1469
1470         surf = (struct _tbm_surface *)surface;
1471
1472         if (plane_idx >= surf->info.num_planes) {
1473                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1474                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1475                 _tbm_surface_mutex_unlock();
1476                 return 0;
1477         }
1478
1479         if (size)
1480                 *size = surf->info.planes[plane_idx].size;
1481
1482         if (offset)
1483                 *offset = surf->info.planes[plane_idx].offset;
1484
1485         if (pitch)
1486                 *pitch = surf->info.planes[plane_idx].stride;
1487
1488         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1489                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1490                                 surf->info.planes[plane_idx].stride);
1491
1492         _tbm_surface_mutex_unlock();
1493
1494         return 1;
1495 }
1496
1497 int
1498 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1499                               tbm_surface_info_s *info, int map)
1500 {
1501         struct _tbm_surface *surf;
1502         tbm_bo_handle bo_handles[4];
1503         int num_bos = 0;
1504         tbm_bo bos[4];
1505         int planes_bo_idx[TBM_SURF_PLANE_MAX];
1506         int i, j;
1507
1508         _tbm_surface_mutex_lock();
1509         _tbm_set_last_result(TBM_ERROR_NONE);
1510
1511         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1512
1513         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1514
1515         surf = (struct _tbm_surface *)surface;
1516
1517         memset(info, 0x00, sizeof(tbm_surface_info_s));
1518         info->width = surf->info.width;
1519         info->height = surf->info.height;
1520         info->format = surf->info.format;
1521         info->bpp = surf->info.bpp;
1522         info->size = surf->info.size;
1523         info->num_planes = surf->info.num_planes;
1524
1525         for (i = 0; i < surf->info.num_planes; i++) {
1526                 info->planes[i].size = surf->info.planes[i].size;
1527                 info->planes[i].offset = surf->info.planes[i].offset;
1528                 info->planes[i].stride = surf->info.planes[i].stride;
1529                 planes_bo_idx[i] = surf->planes_bo_idx[i];
1530         }
1531
1532         for (i = 0; i < surf->num_bos; i++)
1533                 bos[i] = surf->bos[i];
1534
1535         num_bos = surf->num_bos;
1536
1537         if (map == 1) {
1538                 _tbm_surface_mutex_unlock();
1539                 for (i = 0; i < num_bos; i++) {
1540                         bo_handles[i] = tbm_bo_map(bos[i], TBM_DEVICE_CPU, opt);
1541                         if (bo_handles[i].ptr == NULL) {
1542                                 for (j = 0; j < i; j++)
1543                                         tbm_bo_unmap(bos[j]);
1544
1545                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1546                                 return 0;
1547                         }
1548                 }
1549                 _tbm_surface_mutex_lock();
1550         } else {
1551                 for (i = 0; i < num_bos; i++) {
1552                         bo_handles[i] = tbm_bo_get_handle(bos[i], TBM_DEVICE_CPU);
1553                         if (bo_handles[i].ptr == NULL) {
1554                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1555                                 _tbm_surface_mutex_unlock();
1556                                 return 0;
1557                         }
1558                 }
1559         }
1560
1561         for (i = 0; i < info->num_planes; i++) {
1562                 if (bo_handles[planes_bo_idx[i]].ptr)
1563                         info->planes[i].ptr = bo_handles[planes_bo_idx[i]].ptr + info->planes[i].offset;
1564         }
1565
1566         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1567
1568         _tbm_surface_mutex_unlock();
1569
1570         return 1;
1571 }
1572
1573 void
1574 tbm_surface_internal_unmap(tbm_surface_h surface)
1575 {
1576         struct _tbm_surface *surf;
1577         int i;
1578
1579         _tbm_surface_mutex_lock();
1580         _tbm_set_last_result(TBM_ERROR_NONE);
1581
1582         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1583
1584         surf = (struct _tbm_surface *)surface;
1585
1586         for (i = 0; i < surf->num_bos; i++)
1587                 tbm_bo_unmap(surf->bos[i]);
1588
1589         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)\n", surface);
1590
1591         _tbm_surface_mutex_unlock();
1592 }
1593
1594 unsigned int
1595 tbm_surface_internal_get_width(tbm_surface_h surface)
1596 {
1597         struct _tbm_surface *surf;
1598         unsigned int width;
1599
1600         _tbm_surface_mutex_lock();
1601         _tbm_set_last_result(TBM_ERROR_NONE);
1602
1603         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1604
1605         surf = (struct _tbm_surface *)surface;
1606         width = surf->info.width;
1607
1608         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u)\n", surface, width);
1609
1610         _tbm_surface_mutex_unlock();
1611
1612         return width;
1613 }
1614
1615 unsigned int
1616 tbm_surface_internal_get_height(tbm_surface_h surface)
1617 {
1618         struct _tbm_surface *surf;
1619         unsigned int height;
1620
1621         _tbm_surface_mutex_lock();
1622         _tbm_set_last_result(TBM_ERROR_NONE);
1623
1624         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1625
1626         surf = (struct _tbm_surface *)surface;
1627         height = surf->info.height;
1628
1629         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) height(%u)\n", surface, height);
1630
1631         _tbm_surface_mutex_unlock();
1632
1633         return height;
1634
1635 }
1636
1637 tbm_format
1638 tbm_surface_internal_get_format(tbm_surface_h surface)
1639 {
1640         struct _tbm_surface *surf;
1641         tbm_format format;
1642
1643         _tbm_surface_mutex_lock();
1644         _tbm_set_last_result(TBM_ERROR_NONE);
1645
1646         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1647
1648         surf = (struct _tbm_surface *)surface;
1649         format = surf->info.format;
1650
1651         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1652
1653         _tbm_surface_mutex_unlock();
1654
1655         return format;
1656 }
1657
1658 int
1659 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1660 {
1661         struct _tbm_surface *surf;
1662         int bo_idx;
1663
1664         _tbm_surface_mutex_lock();
1665         _tbm_set_last_result(TBM_ERROR_NONE);
1666
1667         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1668         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1669
1670         surf = (struct _tbm_surface *)surface;
1671         bo_idx = surf->planes_bo_idx[plane_idx];
1672
1673         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1674
1675         _tbm_surface_mutex_unlock();
1676
1677         return bo_idx;
1678 }
1679
1680 int
1681 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1682                                    tbm_data_free data_free_func)
1683 {
1684         tbm_user_data *data;
1685
1686         _tbm_surface_mutex_lock();
1687         _tbm_set_last_result(TBM_ERROR_NONE);
1688
1689         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1690
1691         /* check if the data according to the key exist if so, return false. */
1692         data = user_data_lookup(&surface->user_data_list, key);
1693         if (data) {
1694                 TBM_TRACE_SURFACE_INTERNAL("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1695                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1696                 _tbm_surface_mutex_unlock();
1697                 return 0;
1698         }
1699
1700         data = user_data_create(key, data_free_func);
1701         if (!data) {
1702                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1703                 _tbm_surface_mutex_unlock();
1704                 return 0;
1705         }
1706
1707         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1708
1709         LIST_ADD(&data->item_link, &surface->user_data_list);
1710
1711         _tbm_surface_mutex_unlock();
1712
1713         return 1;
1714 }
1715
1716 int
1717 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1718                                    void *data)
1719 {
1720         tbm_user_data *old_data;
1721
1722         _tbm_surface_mutex_lock();
1723         _tbm_set_last_result(TBM_ERROR_NONE);
1724
1725         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1726
1727         old_data = user_data_lookup(&surface->user_data_list, key);
1728         if (!old_data) {
1729                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1730                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1731                 _tbm_surface_mutex_unlock();
1732                 return 0;
1733         }
1734
1735         if (old_data->data && old_data->free_func)
1736                 old_data->free_func(old_data->data);
1737
1738         old_data->data = data;
1739
1740         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1741
1742         _tbm_surface_mutex_unlock();
1743
1744         return 1;
1745 }
1746
1747 int
1748 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1749                                    void **data)
1750 {
1751         tbm_user_data *old_data;
1752
1753         _tbm_surface_mutex_lock();
1754         _tbm_set_last_result(TBM_ERROR_NONE);
1755
1756         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1757
1758         if (!data) {
1759                 TBM_ERR("error: tbm_surface(%p) key(%lu)\n", surface, key);
1760                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1761                 _tbm_surface_mutex_unlock();
1762                 return 0;
1763         }
1764         *data = NULL;
1765
1766         old_data = user_data_lookup(&surface->user_data_list, key);
1767         if (!old_data) {
1768                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1769                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1770                 _tbm_surface_mutex_unlock();
1771                 return 0;
1772         }
1773
1774         *data = old_data->data;
1775
1776         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1777
1778         _tbm_surface_mutex_unlock();
1779
1780         return 1;
1781 }
1782
1783 int
1784 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1785                                       unsigned long key)
1786 {
1787         tbm_user_data *old_data = (void *)0;
1788
1789         _tbm_surface_mutex_lock();
1790         _tbm_set_last_result(TBM_ERROR_NONE);
1791
1792         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1793
1794         old_data = user_data_lookup(&surface->user_data_list, key);
1795         if (!old_data) {
1796                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1797                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1798                 _tbm_surface_mutex_unlock();
1799                 return 0;
1800         }
1801
1802         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1803
1804         user_data_delete(old_data);
1805
1806         _tbm_surface_mutex_unlock();
1807
1808         return 1;
1809 }
1810
1811 /* LCOV_EXCL_START */
1812 unsigned int
1813 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1814 {
1815         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1816
1817         return surface->debug_pid;
1818 }
1819
1820 void
1821 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1822 {
1823         _tbm_surface_mutex_lock();
1824         _tbm_set_last_result(TBM_ERROR_NONE);
1825
1826         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1827
1828         surface->debug_pid = pid;
1829
1830         _tbm_surface_mutex_unlock();
1831 }
1832
1833 static tbm_surface_debug_data *
1834 _tbm_surface_internal_debug_data_create(char *key, char *value)
1835 {
1836         tbm_surface_debug_data *debug_data = NULL;
1837
1838         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1839         if (!debug_data) {
1840                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1841                 TBM_ERR("fail to allocate the debug_data.");
1842                 return NULL;
1843         }
1844
1845         if (key) debug_data->key = strdup(key);
1846         if (value) debug_data->value = strdup(value);
1847
1848         return debug_data;
1849 }
1850
1851 static void
1852 _tbm_surface_internal_debug_data_value_update(tbm_surface_debug_data *debug_data, char *value)
1853 {
1854         if (!debug_data->value && !value)
1855                 return;
1856
1857         if (debug_data->value && value && !strncmp(debug_data->value, value, strlen(debug_data->value)))
1858                 return;
1859
1860         if (debug_data->value)
1861                 free(debug_data->value);
1862
1863         if (value)
1864                 debug_data->value = strdup(value);
1865         else
1866                 debug_data->value = NULL;
1867 }
1868
1869 static tbm_surface_debug_data *
1870 _tbm_surface_internal_debug_data_find(struct list_head *list, char *key)
1871 {
1872         tbm_surface_debug_data *debug_data = NULL;
1873
1874         if (LIST_IS_EMPTY(list))
1875                 return NULL;
1876
1877         LIST_FOR_EACH_ENTRY(debug_data, list, item_link) {
1878                 if (!strncmp(debug_data->key, key, strlen(debug_data->key)))
1879                         return debug_data;
1880         }
1881
1882         return NULL;
1883 }
1884
1885 int
1886 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1887 {
1888         tbm_surface_debug_data *debug_data = NULL;
1889         tbm_bufmgr bufmgr = NULL;
1890
1891         _tbm_surface_mutex_lock();
1892         _tbm_set_last_result(TBM_ERROR_NONE);
1893
1894         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1895         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1896
1897         bufmgr = surface->bufmgr;
1898
1899         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1900
1901         debug_data = _tbm_surface_internal_debug_data_find(&surface->debug_data_list, key);
1902         if (debug_data) {
1903                 _tbm_surface_internal_debug_data_value_update(debug_data, value);
1904         } else {
1905                 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1906                 if (!debug_data) {
1907                         TBM_ERR("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1908                         _tbm_surface_mutex_unlock();
1909                         return 0;
1910                 }
1911
1912                 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1913         }
1914
1915         /* add new debug key to list */
1916         debug_data = _tbm_surface_internal_debug_data_find(&bufmgr->debug_key_list, key);
1917         if (!debug_data) {
1918                 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1919                 if (debug_data)
1920                         LIST_ADDTAIL(&debug_data->item_link, &bufmgr->debug_key_list);
1921         }
1922
1923         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1924
1925         _tbm_surface_mutex_unlock();
1926
1927         return 1;
1928 }
1929
1930 char *
1931 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1932 {
1933         tbm_surface_debug_data *old_data = NULL;
1934
1935         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1936
1937         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1938                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1939                         if (!strcmp(old_data->key, key))
1940                                 return old_data->value;
1941                 }
1942         }
1943
1944         return NULL;
1945 }
1946
1947 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1948 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1949
1950 struct _tbm_surface_dump_buf_info {
1951         int index;
1952         tbm_bo bo;
1953         int size;
1954         int dirty;
1955         int dirty_shm;
1956         int shm_stride;
1957         int shm_h;
1958         char name[1024];
1959
1960         tbm_surface_info_s info;
1961
1962         struct list_head link;
1963 };
1964
1965 struct _tbm_surface_dump_info {
1966         char *path;  // copy???
1967         int dump_max;
1968         int count;
1969         struct list_head *link;
1970         struct list_head surface_list; /* link of surface */
1971 };
1972
1973 static tbm_surface_dump_info *g_dump_info = NULL;
1974 static const char *dump_postfix[2] = {"png", "yuv"};
1975 static double scale_factor;
1976
1977 static void
1978 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1979                                 void *data2, int size2, void *data3, int size3)
1980 {
1981         FILE *fp;
1982         unsigned int *blocks;
1983
1984         if (_tbm_surface_check_file_is_symbolic_link(file))
1985                 TBM_ERR("%s is symbolic link\n", file);
1986
1987         fp = fopen(file, "w+");
1988         TBM_RETURN_IF_FAIL(fp != NULL);
1989
1990         blocks = (unsigned int *)data1;
1991         fwrite(blocks, 1, size1, fp);
1992
1993         if (size2 > 0) {
1994                 blocks = (unsigned int *)data2;
1995                 fwrite(blocks, 1, size2, fp);
1996         }
1997
1998         if (size3 > 0) {
1999                 blocks = (unsigned int *)data3;
2000                 fwrite(blocks, 1, size3, fp);
2001         }
2002
2003         fclose(fp);
2004 }
2005
2006 static void
2007 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height, int stride, int format)
2008 {
2009         unsigned int *blocks = (unsigned int *)data;
2010         FILE *fp;
2011         int pixel_size;
2012         png_bytep *row_pointers;
2013         int depth = 8, y;
2014
2015         if (_tbm_surface_check_file_is_symbolic_link(file))
2016                 TBM_ERR("%s is symbolic link\n", file);
2017
2018         fp = fopen(file, "wb");
2019         TBM_RETURN_IF_FAIL(fp != NULL);
2020
2021         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
2022                                                         NULL, NULL, NULL);
2023         if (!pPngStruct) {
2024                 TBM_ERR("fail to create a png write structure.\n");
2025                 fclose(fp);
2026                 return;
2027         }
2028
2029         png_infop pPngInfo = png_create_info_struct(pPngStruct);
2030         if (!pPngInfo) {
2031                 TBM_ERR("fail to create a png info structure.\n");
2032                 png_destroy_write_struct(&pPngStruct, NULL);
2033                 fclose(fp);
2034                 return;
2035         }
2036
2037         if (setjmp(png_jmpbuf(pPngStruct))) {
2038                 /* if png has problem of writing the file, we get here */
2039                 TBM_ERR("fail to write png file.\n");
2040                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
2041                 fclose(fp);
2042                 return;
2043         }
2044
2045         png_init_io(pPngStruct, fp);
2046         if (format == TBM_FORMAT_XRGB8888) {
2047                 pixel_size = 3;
2048                 png_set_IHDR(pPngStruct,
2049                                 pPngInfo,
2050                                 width,
2051                                 height,
2052                                 depth,
2053                                 PNG_COLOR_TYPE_RGB,
2054                                 PNG_INTERLACE_NONE,
2055                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
2056         } else {
2057                 pixel_size = 4;
2058                 png_set_IHDR(pPngStruct,
2059                                 pPngInfo,
2060                                 width,
2061                                 height,
2062                                 depth,
2063                                 PNG_COLOR_TYPE_RGBA,
2064                                 PNG_INTERLACE_NONE,
2065                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
2066         }
2067
2068         png_set_bgr(pPngStruct);
2069         png_write_info(pPngStruct, pPngInfo);
2070
2071         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
2072         if (!row_pointers) {
2073                 TBM_ERR("fail to allocate the png row_pointers.\n");
2074                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
2075                 fclose(fp);
2076                 return;
2077         }
2078
2079         for (y = 0; y < height; ++y) {
2080                 png_bytep row;
2081                 int x = 0;
2082
2083                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
2084                 if (!row) {
2085                         TBM_ERR("fail to allocate the png row.\n");
2086                         for (x = 0; x < y; x++)
2087                                 png_free(pPngStruct, row_pointers[x]);
2088                         png_free(pPngStruct, row_pointers);
2089                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
2090                         fclose(fp);
2091                         return;
2092                 }
2093                 row_pointers[y] = (png_bytep)row;
2094
2095                 for (x = 0; x < width; ++x) {
2096                         unsigned int curBlock = blocks[(y * (stride >> 2)) + x];
2097
2098                         if (pixel_size == 3) { // XRGB8888
2099                                 row[x * pixel_size] = (curBlock & 0xFF);
2100                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
2101                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
2102                         } else { // ARGB8888
2103                                 row[x * pixel_size] = (curBlock & 0xFF);
2104                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
2105                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
2106                                 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
2107                         }
2108                 }
2109         }
2110
2111         png_write_image(pPngStruct, row_pointers);
2112         png_write_end(pPngStruct, pPngInfo);
2113
2114         for (y = 0; y < height; y++)
2115                 png_free(pPngStruct, row_pointers[y]);
2116         png_free(pPngStruct, row_pointers);
2117
2118         png_destroy_write_struct(&pPngStruct, &pPngInfo);
2119
2120         fclose(fp);
2121 }
2122
2123 void
2124 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
2125 {
2126         TBM_RETURN_IF_FAIL(path != NULL);
2127         TBM_RETURN_IF_FAIL(w > 0);
2128         TBM_RETURN_IF_FAIL(h > 0);
2129         TBM_RETURN_IF_FAIL(count > 0);
2130
2131         tbm_surface_dump_buf_info *buf_info = NULL;
2132         tbm_surface_h tbm_surface;
2133         tbm_surface_info_s info;
2134         int buffer_size, i;
2135
2136         /* check running */
2137         if (g_dump_info) {
2138                 TBM_WRN("waring already running the tbm_surface_internal_dump.\n");
2139                 return;
2140         }
2141
2142         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
2143         TBM_RETURN_IF_FAIL(g_dump_info);
2144
2145         LIST_INITHEAD(&g_dump_info->surface_list);
2146         g_dump_info->count = 0;
2147         g_dump_info->dump_max = count;
2148
2149         /* get buffer size */
2150         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
2151         if (tbm_surface == NULL) {
2152                 TBM_ERR("tbm_surface_create fail\n");
2153                 free(g_dump_info);
2154                 g_dump_info = NULL;
2155                 return;
2156         }
2157
2158         if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
2159                 TBM_ERR("tbm_surface_get_info fail\n");
2160                 tbm_surface_destroy(tbm_surface);
2161                 free(g_dump_info);
2162                 g_dump_info = NULL;
2163                 return;
2164         }
2165         buffer_size = info.size;
2166         tbm_surface_destroy(tbm_surface);
2167
2168         /* create dump lists */
2169         for (i = 0; i < count; i++) {
2170                 tbm_bo bo = NULL;
2171
2172                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
2173                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
2174
2175                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
2176                 if (bo == NULL) {
2177                         TBM_ERR("fail to allocate the tbm_bo[%d]\n", i);
2178                         free(buf_info);
2179                         goto fail;
2180                 }
2181
2182                 buf_info->index = i;
2183                 buf_info->bo = bo;
2184                 buf_info->size = buffer_size;
2185
2186                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
2187         }
2188
2189         g_dump_info->path = path;
2190         g_dump_info->link = &g_dump_info->surface_list;
2191
2192         scale_factor = 0.0;
2193
2194         TBM_INFO("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
2195
2196         return;
2197
2198 fail:
2199         /* free resources */
2200         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2201                 tbm_surface_dump_buf_info *tmp;
2202
2203                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2204                         tbm_bo_unref(buf_info->bo);
2205                         LIST_DEL(&buf_info->link);
2206                         free(buf_info);
2207                 }
2208         }
2209
2210         TBM_ERR("Dump Start fail.. path:%s\n", g_dump_info->path);
2211
2212         free(g_dump_info);
2213         g_dump_info = NULL;
2214
2215         return;
2216 }
2217
2218 void
2219 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
2220 {
2221         if (scale > 0.0) {
2222                 w *= scale;
2223                 h *= scale;
2224         }
2225
2226         tbm_surface_internal_dump_start(path, w, h, count);
2227         scale_factor = scale;
2228 }
2229
2230 void
2231 tbm_surface_internal_dump_end(void)
2232 {
2233         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
2234         tbm_bo_handle bo_handle;
2235
2236         if (!g_dump_info)
2237                 return;
2238
2239         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2240                 free(g_dump_info);
2241                 g_dump_info = NULL;
2242                 return;
2243         }
2244
2245         /* make files */
2246         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2247                 char file[2048];
2248
2249                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
2250                 if (bo_handle.ptr == NULL) {
2251                         tbm_bo_unref(buf_info->bo);
2252                         LIST_DEL(&buf_info->link);
2253                         free(buf_info);
2254                         continue;
2255                 }
2256
2257                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
2258                 TBM_INFO("Dump File.. %s generated.\n", file);
2259
2260                 if (buf_info->dirty) {
2261                         void *ptr1 = NULL, *ptr2 = NULL;
2262
2263                         switch (buf_info->info.format) {
2264                         case TBM_FORMAT_ARGB8888:
2265                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2266                                                         buf_info->info.planes[0].stride >> 2,
2267                                                         buf_info->info.height,
2268                                                         buf_info->info.planes[0].stride,
2269                                                         TBM_FORMAT_ARGB8888);
2270                                 break;
2271                         case TBM_FORMAT_XRGB8888:
2272                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2273                                                         buf_info->info.planes[0].stride >> 2,
2274                                                         buf_info->info.height,
2275                                                         buf_info->info.planes[0].stride,
2276                                                         TBM_FORMAT_XRGB8888);
2277                                 break;
2278                         case TBM_FORMAT_YVU420:
2279                         case TBM_FORMAT_YUV420:
2280                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2281                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
2282                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2283                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2284                                                         ptr1,
2285                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2286                                                         ptr2,
2287                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
2288                                 break;
2289                         case TBM_FORMAT_NV12:
2290                         case TBM_FORMAT_NV21:
2291                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2292                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2293                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2294                                                         ptr1,
2295                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2296                                                         NULL, 0);
2297                                 break;
2298                         case TBM_FORMAT_YUYV:
2299                         case TBM_FORMAT_UYVY:
2300                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2301                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2302                                                         NULL, 0, NULL, 0);
2303                                 break;
2304                         default:
2305                                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
2306                                 break;
2307                         }
2308                 } else if (buf_info->dirty_shm)
2309                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2310                                                         buf_info->shm_stride >> 2,
2311                                                         buf_info->shm_h,
2312                                                         buf_info->shm_stride, 0);
2313
2314                 tbm_bo_unmap(buf_info->bo);
2315                 tbm_bo_unref(buf_info->bo);
2316                 LIST_DEL(&buf_info->link);
2317                 free(buf_info);
2318         }
2319
2320         free(g_dump_info);
2321         g_dump_info = NULL;
2322
2323         TBM_INFO("Dump End..\n");
2324 }
2325
2326 static pixman_format_code_t
2327 _tbm_surface_internal_pixman_format_get(tbm_format format)
2328 {
2329         switch (format) {
2330         case TBM_FORMAT_ARGB8888:
2331                 return PIXMAN_a8r8g8b8;
2332         case TBM_FORMAT_XRGB8888:
2333                 return PIXMAN_x8r8g8b8;
2334         default:
2335                 return 0;
2336         }
2337
2338         return 0;
2339 }
2340
2341 /**
2342  * This function supports only if a buffer has below formats.
2343  * - TBM_FORMAT_ARGB8888
2344  * - TBM_FORMAT_XRGB8888
2345  */
2346 static tbm_surface_error_e
2347 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
2348                                                                    int format, int src_stride, int src_w, int src_h,
2349                                                                    int dst_stride, int dst_w, int dst_h)
2350 {
2351         pixman_image_t *src_img = NULL, *dst_img = NULL;
2352         pixman_format_code_t pixman_format;
2353         pixman_transform_t t;
2354         struct pixman_f_transform ft;
2355         double scale_x, scale_y;
2356
2357         TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2358         TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2359
2360         pixman_format = _tbm_surface_internal_pixman_format_get(format);
2361         TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2362
2363         /* src */
2364         src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2365                                                                            (uint32_t*)src_ptr, src_stride);
2366         TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2367
2368         /* dst */
2369         dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2370                                                                            (uint32_t*)dst_ptr, dst_stride);
2371         TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2372
2373         pixman_f_transform_init_identity(&ft);
2374
2375         scale_x = (double)src_w / dst_w;
2376         scale_y = (double)src_h / dst_h;
2377
2378         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2379         pixman_f_transform_translate(&ft, NULL, 0, 0);
2380         pixman_transform_from_pixman_f_transform(&t, &ft);
2381         pixman_image_set_transform(src_img, &t);
2382
2383         pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2384                                                    0, 0, 0, 0, 0, 0, dst_w, dst_h);
2385
2386         pixman_image_unref(src_img);
2387         pixman_image_unref(dst_img);
2388
2389         return TBM_SURFACE_ERROR_NONE;
2390
2391 cant_convert:
2392         if (src_img)
2393                 pixman_image_unref(src_img);
2394
2395         return TBM_SURFACE_ERROR_INVALID_OPERATION;
2396 }
2397
2398 #define MAX_BOS         4       // This value is came from bos[4] in struct _tbm_surface
2399 #define KEY_LEN         5       // "_XXXX"
2400 #define KEYS_LEN        KEY_LEN * MAX_BOS
2401
2402 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2403 {
2404         char *keys, temp_key[KEY_LEN + 1];
2405         struct _tbm_surface *surf;
2406         int i, num_bos;
2407         tbm_bo bo;
2408
2409         _tbm_surface_mutex_lock();
2410
2411         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2412
2413         surf = (struct _tbm_surface *)surface;
2414
2415         num_bos = surf->num_bos;
2416         if (num_bos > MAX_BOS)
2417                 num_bos = MAX_BOS;
2418
2419         keys = calloc(KEYS_LEN + 1, sizeof(char));
2420         if (!keys) {
2421                 TBM_ERR("Failed to alloc memory");
2422                 _tbm_surface_mutex_unlock();
2423                 return NULL;
2424         }
2425
2426         for (i = 0; i < num_bos; i++) {
2427                 memset(temp_key, 0x00, KEY_LEN + 1);
2428                 bo = surf->bos[i];
2429                 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2430                 strncat(keys, temp_key, KEY_LEN + 1);
2431         }
2432
2433         _tbm_surface_mutex_unlock();
2434
2435         return keys;
2436 }
2437
2438 static void _tbm_surface_internal_put_keys(char *keys)
2439 {
2440         if (keys)
2441                 free(keys);
2442 }
2443
2444 void
2445 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2446 {
2447         TBM_RETURN_IF_FAIL(surface != NULL);
2448         TBM_RETURN_IF_FAIL(type != NULL);
2449
2450         tbm_surface_dump_buf_info *buf_info;
2451         struct list_head *next_link;
2452         tbm_surface_info_s info;
2453         tbm_bo_handle bo_handle;
2454         const char *postfix;
2455         const char *format = NULL;
2456         char *keys;
2457         int ret;
2458
2459         if (!g_dump_info)
2460                 return;
2461
2462         next_link = g_dump_info->link->next;
2463         TBM_RETURN_IF_FAIL(next_link != NULL);
2464
2465         if (next_link == &g_dump_info->surface_list) {
2466                 next_link = next_link->next;
2467                 TBM_RETURN_IF_FAIL(next_link != NULL);
2468         }
2469
2470         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2471         TBM_RETURN_IF_FAIL(buf_info != NULL);
2472
2473         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2474         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2475
2476         if (scale_factor > 0.0) {
2477                 const int bpp = 4;
2478
2479                 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
2480                         TBM_WRN("Dump with scale skip. unsupported format(%s)\n",
2481                                           _tbm_surface_internal_format_to_str(info.format));
2482                         tbm_surface_unmap(surface);
2483                         return;
2484                 }
2485
2486                 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2487
2488                 buf_info->info.width = info.width * scale_factor;
2489                 buf_info->info.height = info.height * scale_factor;
2490                 buf_info->info.format = info.format;
2491                 buf_info->info.bpp = _tbm_surface_internal_get_bpp(buf_info->info.format);
2492                 if (!buf_info->info.bpp) {
2493                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
2494                         tbm_surface_unmap(surface);
2495                         return;
2496                 }
2497                 buf_info->info.num_planes = 1;
2498                 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2499                 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2500
2501                 if (buf_info->info.size > buf_info->size) {
2502                         TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)\n",
2503                                         buf_info->info.size, buf_info->size);
2504                         tbm_surface_unmap(surface);
2505                         return;
2506                 }
2507         } else {
2508                 if (info.size > buf_info->size) {
2509                         TBM_WRN("Dump skip. surface over created buffer size(%u, %d)\n",
2510                                         info.size, buf_info->size);
2511                         tbm_surface_unmap(surface);
2512                         return;
2513                 }
2514
2515                 /* make the file information */
2516                 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2517         }
2518
2519         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888) {
2520                 postfix = dump_postfix[0];
2521                 format = _tbm_surface_internal_format_to_str(info.format);
2522         } else
2523                 postfix = dump_postfix[1];
2524
2525         keys = _tbm_surface_internal_get_keys(surface);
2526         if (!keys) {
2527                 TBM_ERR("fail to get keys");
2528                 tbm_surface_unmap(surface);
2529                 return;
2530         }
2531
2532         /* dump */
2533         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2534         if (!bo_handle.ptr) {
2535                 TBM_ERR("fail to map bo");
2536                 _tbm_surface_internal_put_keys(keys);
2537                 tbm_surface_unmap(surface);
2538                 return;
2539         }
2540         memset(bo_handle.ptr, 0x00, buf_info->size);
2541
2542         switch (info.format) {
2543         case TBM_FORMAT_ARGB8888:
2544         case TBM_FORMAT_XRGB8888:
2545                 snprintf(buf_info->name, sizeof(buf_info->name),
2546                                 "%10.3f_%03d%s_%p_%s-%s.%s",
2547                                  _tbm_surface_internal_get_time(),
2548                                  g_dump_info->count++, keys, surface, format, type, postfix);
2549
2550                 if (scale_factor > 0.0) {
2551                         ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2552                                                                                                          bo_handle.ptr,
2553                                                                                                          buf_info->info.format,
2554                                                                                                          info.planes[0].stride,
2555                                                                                                          info.width, info.height,
2556                                                                                                          buf_info->info.planes[0].stride,
2557                                                                                                          buf_info->info.width,
2558                                                                                                          buf_info->info.height);
2559                         if (ret != TBM_SURFACE_ERROR_NONE) {
2560                                 TBM_ERR("fail to scale buffer");
2561                                 tbm_bo_unmap(buf_info->bo);
2562                                 _tbm_surface_internal_put_keys(keys);
2563                                 tbm_surface_unmap(surface);
2564                                 return;
2565                         }
2566                 } else
2567                         memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2568                 break;
2569         case TBM_FORMAT_YVU420:
2570         case TBM_FORMAT_YUV420:
2571                 snprintf(buf_info->name, sizeof(buf_info->name),
2572                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2573                                  _tbm_surface_internal_get_time(),
2574                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2575                                 info.height, FOURCC_STR(info.format), postfix);
2576                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2577                 bo_handle.ptr += info.planes[0].stride * info.height;
2578                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2579                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2580                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2581                 break;
2582         case TBM_FORMAT_NV12:
2583         case TBM_FORMAT_NV21:
2584                 snprintf(buf_info->name, sizeof(buf_info->name),
2585                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2586                                  _tbm_surface_internal_get_time(),
2587                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2588                                 info.height, FOURCC_STR(info.format), postfix);
2589                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2590                 bo_handle.ptr += info.planes[0].stride * info.height;
2591                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2592                 break;
2593         case TBM_FORMAT_YUYV:
2594         case TBM_FORMAT_UYVY:
2595                 snprintf(buf_info->name, sizeof(buf_info->name),
2596                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2597                                  _tbm_surface_internal_get_time(),
2598                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2599                                 info.height, FOURCC_STR(info.format), postfix);
2600                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2601                 break;
2602         default:
2603                 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2604                 tbm_bo_unmap(buf_info->bo);
2605                 _tbm_surface_internal_put_keys(keys);
2606                 tbm_surface_unmap(surface);
2607                 return;
2608         }
2609
2610         tbm_bo_unmap(buf_info->bo);
2611
2612         _tbm_surface_internal_put_keys(keys);
2613
2614         tbm_surface_unmap(surface);
2615
2616         buf_info->dirty = 1;
2617         buf_info->dirty_shm = 0;
2618
2619         if (g_dump_info->count == 1000)
2620                 g_dump_info->count = 0;
2621
2622         g_dump_info->link = next_link;
2623
2624         TBM_INFO("Dump %s \n", buf_info->name);
2625 }
2626
2627 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2628                                                 const char *type)
2629 {
2630         TBM_RETURN_IF_FAIL(ptr != NULL);
2631         TBM_RETURN_IF_FAIL(w > 0);
2632         TBM_RETURN_IF_FAIL(h > 0);
2633         TBM_RETURN_IF_FAIL(stride > 0);
2634         TBM_RETURN_IF_FAIL(type != NULL);
2635
2636         tbm_surface_dump_buf_info *buf_info;
2637         struct list_head *next_link;
2638         tbm_bo_handle bo_handle;
2639         int ret, size, dw = 0, dh = 0, dstride = 0;
2640
2641         if (!g_dump_info)
2642                 return;
2643
2644         next_link = g_dump_info->link->next;
2645         TBM_RETURN_IF_FAIL(next_link != NULL);
2646
2647         if (next_link == &g_dump_info->surface_list) {
2648                 next_link = next_link->next;
2649                 TBM_RETURN_IF_FAIL(next_link != NULL);
2650         }
2651
2652         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2653         TBM_RETURN_IF_FAIL(buf_info != NULL);
2654
2655         if (scale_factor > 0.0) {
2656                 const int bpp = 4;
2657
2658                 dw = w * scale_factor;
2659                 dh = h * scale_factor;
2660                 dstride = dw * bpp;
2661                 size = dstride * dh;
2662         } else
2663                 size = stride * h;
2664
2665         if (size > buf_info->size) {
2666                 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2667                                 size, buf_info->size);
2668                 return;
2669         }
2670
2671         /* dump */
2672         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2673         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2674
2675         memset(bo_handle.ptr, 0x00, buf_info->size);
2676         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2677
2678         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2679                          _tbm_surface_internal_get_time(),
2680                          g_dump_info->count++, type, dump_postfix[0]);
2681         if (scale_factor > 0.0) {
2682                 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2683                                                                                                  TBM_FORMAT_ARGB8888, stride,
2684                                                                                                  w, h, dstride, dw, dh);
2685                 if (ret != TBM_SURFACE_ERROR_NONE) {
2686                         TBM_ERR("fail to scale buffer");
2687                         tbm_bo_unmap(buf_info->bo);
2688                         return;
2689                 }
2690                 buf_info->shm_stride = dstride;
2691                 buf_info->shm_h = dh;
2692         } else {
2693                 memcpy(bo_handle.ptr, ptr, size);
2694                 buf_info->shm_stride = stride;
2695                 buf_info->shm_h = h;
2696         }
2697
2698         tbm_bo_unmap(buf_info->bo);
2699
2700         buf_info->dirty = 0;
2701         buf_info->dirty_shm = 1;
2702
2703         if (g_dump_info->count == 1000)
2704                 g_dump_info->count = 0;
2705
2706         g_dump_info->link = next_link;
2707
2708         TBM_INFO("Dump %s \n", buf_info->name);
2709 }
2710
2711 int
2712 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2713 {
2714         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2715         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2716         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2717
2718         tbm_surface_info_s info;
2719         const char *postfix;
2720         int ret;
2721         char file[1024];
2722
2723         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2724         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2725
2726         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2727                 postfix = dump_postfix[0];
2728         else
2729                 postfix = dump_postfix[1];
2730
2731         if (strcmp(postfix, type)) {
2732                 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2733                 tbm_surface_unmap(surface);
2734                 return 0;
2735         }
2736
2737         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2738
2739         if (!access(file, 0)) {
2740                 TBM_ERR("can't capture  buffer, exist file %s", file);
2741                 tbm_surface_unmap(surface);
2742                 return 0;
2743         }
2744
2745         switch (info.format) {
2746         case TBM_FORMAT_ARGB8888:
2747                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2748                                                         info.width,
2749                                                         info.height,
2750                                                         info.planes[0].stride,
2751                                                         TBM_FORMAT_ARGB8888);
2752                 break;
2753         case TBM_FORMAT_XRGB8888:
2754                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2755                                                         info.width,
2756                                                         info.height,
2757                                                         info.planes[0].stride,
2758                                                         TBM_FORMAT_XRGB8888);
2759                 break;
2760         case TBM_FORMAT_YVU420:
2761         case TBM_FORMAT_YUV420:
2762                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2763                                 info.planes[0].stride * info.height,
2764                                 info.planes[1].ptr,
2765                                 info.planes[1].stride * (info.height >> 1),
2766                                 info.planes[2].ptr,
2767                                 info.planes[2].stride * (info.height >> 1));
2768                 break;
2769         case TBM_FORMAT_NV12:
2770         case TBM_FORMAT_NV21:
2771                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2772                                         info.planes[0].stride * info.height,
2773                                         info.planes[1].ptr,
2774                                         info.planes[1].stride * (info.height >> 1),
2775                                         NULL, 0);
2776                 break;
2777         case TBM_FORMAT_YUYV:
2778         case TBM_FORMAT_UYVY:
2779                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2780                                         info.planes[0].stride * info.height,
2781                                         NULL, 0, NULL, 0);
2782                 break;
2783         default:
2784                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2785                 tbm_surface_unmap(surface);
2786                 return 0;
2787         }
2788
2789         tbm_surface_unmap(surface);
2790
2791         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2792
2793         return 1;
2794 }
2795
2796 int
2797 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2798                                                 const char *path, const char *name, const char *type)
2799 {
2800         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2801         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2802         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2803         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2804         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2805         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2806
2807         char file[1024];
2808
2809         if (strcmp(dump_postfix[0], type)) {
2810                 TBM_ERR("Not supported type:%s'", type);
2811                 return 0;
2812         }
2813
2814         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2815
2816         if (!access(file, 0)) {
2817                 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2818                 return 0;
2819         }
2820
2821         _tbm_surface_internal_dump_file_png(file, ptr, w, h, stride, 0);
2822
2823         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2824
2825         return 1;
2826 }
2827
2828 int
2829 tbm_surface_internal_set_damage(tbm_surface_h surface, int x, int y, int width, int height)
2830 {
2831         struct _tbm_surface *surf;
2832
2833         _tbm_surface_mutex_lock();
2834         _tbm_set_last_result(TBM_ERROR_NONE);
2835
2836         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, 0);
2837         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, 0);
2838         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2839
2840         surf = (struct _tbm_surface *)surface;
2841
2842         surf->damage.x = x;
2843         surf->damage.y = y;
2844         surf->damage.width = width;
2845         surf->damage.height = height;
2846
2847         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2848                                                         surface, x, y, width, height);
2849
2850         _tbm_surface_mutex_unlock();
2851
2852         return 1;
2853 }
2854
2855 int
2856 tbm_surface_internal_get_damage(tbm_surface_h surface, int *x, int *y, int *width, int *height)
2857 {
2858         struct _tbm_surface *surf;
2859
2860         _tbm_surface_mutex_lock();
2861         _tbm_set_last_result(TBM_ERROR_NONE);
2862
2863         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2864
2865         surf = (struct _tbm_surface *)surface;
2866
2867         if (x) *x = surf->damage.x;
2868         if (y) *y = surf->damage.y;
2869         if (width) *width = surf->damage.width;
2870         if (height) *height = surf->damage.height;
2871
2872         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2873                                                         surface, surf->damage.x, surf->damage.y, surf->damage.width, surf->damage.height);
2874
2875         _tbm_surface_mutex_unlock();
2876
2877         return 1;
2878 }
2879
2880 int
2881 tbm_surface_internal_add_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2882 {
2883         struct _tbm_surface *surf;
2884         tbm_surface_destroy_func_info *func_info = NULL;
2885
2886         _tbm_surface_mutex_lock();
2887         _tbm_set_last_result(TBM_ERROR_NONE);
2888
2889         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2890         TBM_SURFACE_RETURN_VAL_IF_FAIL(func != NULL, 0);
2891
2892         surf = (struct _tbm_surface *)surface;
2893         LIST_FOR_EACH_ENTRY(func_info, &surf->destroy_funcs, item_link) {
2894                 if (func_info->destroy_func == func && func_info->user_data == user_data) {
2895                         TBM_ERR("can't add twice");
2896                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
2897                         _tbm_surface_mutex_unlock();
2898                         return 0;
2899                 }
2900         }
2901
2902         func_info = calloc(1, sizeof(tbm_surface_destroy_func_info));
2903         if (func_info == NULL) {
2904                 TBM_ERR("alloc failed");
2905                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
2906                 _tbm_surface_mutex_unlock();
2907                 return 0;
2908         }
2909
2910         func_info->destroy_func = func;
2911         func_info->user_data = user_data;
2912
2913         LIST_ADDTAIL(&func_info->item_link, &surf->destroy_funcs);
2914
2915         _tbm_surface_mutex_unlock();
2916
2917         return 1;
2918 }
2919
2920 void
2921 tbm_surface_internal_remove_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2922 {
2923         struct _tbm_surface *surf;
2924         tbm_surface_destroy_func_info *func_info = NULL, *next = NULL;
2925
2926         _tbm_surface_mutex_lock();
2927         _tbm_set_last_result(TBM_ERROR_NONE);
2928
2929         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
2930         TBM_SURFACE_RETURN_IF_FAIL(func != NULL);
2931
2932         surf = (struct _tbm_surface *)surface;
2933         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &surf->destroy_funcs, item_link) {
2934                 if (func_info->destroy_func != func || func_info->user_data != user_data)
2935                         continue;
2936
2937                 LIST_DEL(&func_info->item_link);
2938                 free(func_info);
2939
2940                 _tbm_surface_mutex_unlock();
2941
2942                 return;
2943         }
2944
2945         _tbm_surface_mutex_unlock();
2946 }
2947
2948 tbm_surface_buffer_data *
2949 tbm_surface_internal_export(tbm_surface_h surface, tbm_error_e *error)
2950 {
2951         tbm_surface_buffer_data *buffer_data = NULL;
2952         struct _tbm_surface *surf;
2953         struct _tbm_bufmgr *bufmgr;
2954
2955         _tbm_surface_mutex_lock();
2956
2957         surf = (struct _tbm_surface *)surface;
2958         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL, *error, TBM_ERROR_INVALID_PARAMETER);
2959
2960         bufmgr = surf->bufmgr;
2961         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr != NULL, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
2962
2963         // this function supports when it comes to be use_hal.
2964         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr->use_hal_tbm, NULL, *error, TBM_ERROR_NOT_SUPPORTED);
2965
2966         // export a surface
2967         buffer_data = (tbm_surface_buffer_data *)hal_tbm_surface_export((hal_tbm_surface *)surf->hal_surface,
2968                                                                                                                                         (hal_tbm_error *)error);
2969         TBM_SURFACE_RETURN_VAL_ERR_IF_FAIL(buffer_data != NULL, NULL, *error);
2970
2971         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) buffer_data(%p)", surface, buffer_data);
2972
2973         if (error)
2974                 *error = TBM_ERROR_NONE;
2975
2976         _tbm_set_last_result(TBM_ERROR_NONE);
2977         _tbm_surface_mutex_unlock();
2978
2979         return buffer_data;
2980 }
2981
2982 tbm_surface_h
2983 tbm_surface_internal_import(tbm_surface_info_s *surface_info, tbm_surface_buffer_data *buffer_data, tbm_error_e *error)
2984 {
2985         struct _tbm_surface *surf;
2986         struct _tbm_bufmgr *bufmgr;
2987
2988         _tbm_surface_mutex_lock();
2989
2990         bufmgr = g_surface_bufmgr;
2991         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr != NULL, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
2992
2993         // this function supports when it comes to be use_hal.
2994         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr->use_hal_tbm, NULL, *error, TBM_ERROR_NOT_SUPPORTED);
2995
2996         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info != NULL, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
2997         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info->width > 0, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
2998         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info->height > 0, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
2999         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(buffer_data != NULL, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
3000
3001         // import a surface
3002         surf = _tbm_surface_internal_hal_tbm_import_surface(bufmgr,
3003                                                                                                         (int)surface_info->width,
3004                                                                                                         (int)surface_info->height,
3005                                                                                                         (int)surface_info->format,
3006                                                                                                         buffer_data,
3007                                                                                                         error);
3008         TBM_SURFACE_RETURN_VAL_ERR_IF_FAIL(surf != NULL, NULL, *error);
3009
3010         LIST_INITHEAD(&surf->user_data_list);
3011         LIST_INITHEAD(&surf->debug_data_list);
3012         LIST_INITHEAD(&surf->destroy_funcs);
3013
3014         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
3015
3016         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)", surf);
3017
3018         if (error)
3019                 *error = TBM_ERROR_NONE;
3020
3021         _tbm_set_last_result(TBM_ERROR_NONE);
3022         _tbm_surface_mutex_unlock();
3023
3024         return (tbm_surface_h)surf;
3025 }
3026
3027 /*LCOV_EXCL_STOP*/