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