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