tbm_bo: remove tbm_bo_alloc_with_tiled_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                 if (bufmgr->use_hal_tbm) {
707                         surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, surf->info.bpp/8, flags, error);
708                         if (*error == TBM_ERROR_NOT_SUPPORTED) {
709                                 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
710                                 if (!surf->bos[i]) {
711                                         TBM_ERR("fail to alloc bo idx:%d\n", i);
712                                         *error = tbm_get_last_error();
713                                         goto alloc_bo_fail;
714                                 }
715                         }
716                 } else if (bufmgr->backend_module_data) {
717                         if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format) {
718                                 /* LCOV_EXCL_START */
719                                 surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, surf->info.bpp/8, flags, error);
720                                 if (!surf->bos[i]) {
721                                         TBM_ERR("fail to tbm_bo_alloc_with_format idx:%d\n", i);
722                                         *error = tbm_get_last_error();
723                                         goto alloc_bo_fail;
724                                 }
725                                 /* LCOV_EXCL_STOP */
726                         } else if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format && (flags & TBM_BO_TILED)) {
727                                 /* LCOV_EXCL_START */
728                                 TBM_ERR("NOT SUPPORTED. idx:%d", i);
729                                 *error = TBM_ERROR_NOT_SUPPORTED;
730                                 goto alloc_bo_fail;
731                                 /* LCOV_EXCL_STOP */
732                         } else {
733                                 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
734                                 if (!surf->bos[i]) {
735                                         TBM_ERR("fail to alloc bo idx:%d\n", i);
736                                         *error = tbm_get_last_error();
737                                         goto alloc_bo_fail;
738                                 }
739                         }
740                 } else {
741                         if (bufmgr->backend->surface_bo_alloc) {
742                                 /* LCOV_EXCL_START */
743                                 surf->bos[i] = tbm_bo_alloc_with_surface(bufmgr, width, height, format, flags, i);
744                                 if (!surf->bos[i]) {
745                                         TBM_ERR("fail to tbm_bo_alloc_with_surface idx:%d\n", i);
746                                         *error = tbm_get_last_error();
747                                         goto alloc_bo_fail;
748                                 /* LCOV_EXCL_STOP */
749                                 }
750                         } else {
751                                 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
752                                 if (!surf->bos[i]) {
753                                         TBM_ERR("fail to alloc bo idx:%d\n", i);
754                                         *error = tbm_get_last_error();
755                                         goto alloc_bo_fail;
756                                 }
757                         }
758                 }
759
760                 _tbm_bo_set_surface(surf->bos[i], surf);
761         }
762
763         *error = TBM_ERROR_NONE;
764
765         return surf;
766
767 alloc_bo_fail:
768         for (j = 0; j < i; j++) {
769                 if (surf->bos[j])
770                         tbm_bo_unref(surf->bos[j]);
771         }
772 query_plane_data_fail:
773 bpp_fail:
774 num_planes_fail:
775         free(surf);
776 alloc_surf_fail:
777
778         return NULL;
779 }
780
781 static struct _tbm_surface *
782 _tbm_surface_internal_hal_tbm_create_surface(tbm_bufmgr bufmgr, int width, int height, int format, int flags, tbm_error_e *error)
783 {
784         struct _tbm_surface *surf = NULL;
785         uint32_t size = 0, offset = 0, stride = 0, bo_size = 0;
786         int i, j, bo_idx;
787         hal_tbm_surface *hal_surface = NULL;
788         hal_tbm_bo **hal_bos = NULL;
789         int num_bos = 0;
790
791         surf = calloc(1, sizeof(struct _tbm_surface));
792         if (!surf) {
793                 /* LCOV_EXCL_START */
794                 TBM_ERR("fail to alloc surf");
795                 *error = TBM_ERROR_OUT_OF_MEMORY;
796                 goto alloc_surf_fail;
797                 /* LCOV_EXCL_STOP */
798         }
799         surf->refcnt = 1;
800
801         surf->magic = TBM_SURFACE_MAGIC;
802         surf->bufmgr = bufmgr;
803         surf->info.width = width;
804         surf->info.height = height;
805         surf->info.format = format;
806         surf->info.bpp = _tbm_surface_internal_get_bpp(format);
807         if (!surf->info.bpp) {
808                 TBM_ERR("fail to get bpp from format(%d), error(%s)", format, tbm_error_str(*error));
809                 *error = tbm_get_last_error();
810                 goto bpp_fail;
811         }
812         surf->flags = flags;
813
814         // get number of planes
815         surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
816         if (!surf->info.num_planes) {
817                 TBM_ERR("fail to get num_planes from format(%d), error(%s)", format, tbm_error_str(*error));
818                 *error = tbm_get_last_error();
819                 goto num_planes_fail;
820         }
821
822         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);
823         if (hal_surface) {
824                 // set hal_surface
825                 surf->hal_surface = hal_surface;
826
827                 // set infomation of planes
828                 for (i = 0; i < surf->info.num_planes; i++) {
829                         *error = (tbm_error_e)hal_tbm_surface_get_plane_data(hal_surface, i, &size, &offset, &stride, &bo_idx);
830                         if (*error != TBM_ERROR_NONE) {
831                                 goto query_plane_data_fail;
832                         }
833                         surf->info.planes[i].size = size;
834                         surf->info.planes[i].offset = offset;
835                         surf->info.planes[i].stride = stride;
836                         surf->planes_bo_idx[i] = bo_idx;
837                 }
838
839                 // set infomation of bos
840                 hal_bos = hal_tbm_surface_get_bos(hal_surface, &num_bos, (hal_tbm_error *)error);
841                 if (!hal_bos) {
842                         TBM_ERR("fail to get bos, error(%s)", tbm_error_str(*error));
843                         goto get_bos_fail;
844                 }
845                 surf->num_bos = num_bos;
846
847                 for (i = 0; i < surf->info.num_planes; i++) {
848                         surf->info.size += surf->info.planes[i].size;
849
850                         if (surf->num_bos < surf->planes_bo_idx[i] + 1)
851                                 surf->num_bos = surf->planes_bo_idx[i] + 1;
852                 }
853
854                 for (i = 0; i < num_bos; i++) {
855                         surf->bos[i] = tbm_bo_alloc_with_bo_data(bufmgr, (tbm_backend_bo_data *)hal_bos[i], flags);
856                         if (!surf->bos[i]) {
857                                 TBM_ERR("fail to alloc bo idx:%d", i);
858                                 *error = tbm_get_last_error();
859                                 goto get_bo_fail;
860                         }
861
862                         _tbm_bo_set_surface(surf->bos[i], surf);
863                 }
864         } else {
865                 // set infomation of planes
866                 for (i = 0; i < surf->info.num_planes; i++) {
867                         if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
868                                 TBM_ERR("fail to query plane data");
869                                 *error = tbm_get_last_error();
870                                 goto query_plane_data_fail;
871                         }
872                         surf->info.planes[i].size = size;
873                         surf->info.planes[i].offset = offset;
874                         surf->info.planes[i].stride = stride;
875                         surf->planes_bo_idx[i] = bo_idx;
876                 }
877
878                 // count number of bos
879                 surf->num_bos = 1;
880                 for (i = 0; i < surf->info.num_planes; i++) {
881                         surf->info.size += surf->info.planes[i].size;
882
883                         if (surf->num_bos < surf->planes_bo_idx[i] + 1)
884                                 surf->num_bos = surf->planes_bo_idx[i] + 1;
885                 }
886
887                 // set infomation of bos
888                 for (i = 0; i < surf->num_bos; i++) {
889                         bo_size = 0;
890                         for (j = 0; j < surf->info.num_planes; j++) {
891                                 if (surf->planes_bo_idx[j] == i)
892                                         bo_size += surf->info.planes[j].size;
893                         }
894
895                         surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, surf->info.bpp / 8, flags, error);
896                         if (*error == TBM_ERROR_NOT_SUPPORTED) {
897                                 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
898                                 if (!surf->bos[i]) {
899                                         TBM_ERR("fail to alloc bo idx:%d", i);
900                                         *error = tbm_get_last_error();
901                                         goto get_bo_fail;
902                                 }
903                         }
904
905                         _tbm_bo_set_surface(surf->bos[i], surf);
906                 }
907         }
908
909         *error = TBM_ERROR_NONE;
910
911         return surf;
912
913 get_bo_fail:
914 get_bos_fail:
915 query_plane_data_fail:
916         if (hal_surface) {
917                 hal_tbm_surface_free(hal_surface);
918         } else {
919                 for (j = 0; j < i; j++) {
920                         if (surf->bos[j])
921                                 tbm_bo_unref(surf->bos[j]);
922                 }
923         }
924 num_planes_fail:
925 bpp_fail:
926         if (surf)
927                 free(surf);
928 alloc_surf_fail:
929
930         return NULL;
931 }
932
933 static struct _tbm_surface *
934 _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)
935 {
936         struct _tbm_surface *surf = NULL;
937         uint32_t size = 0, offset = 0, stride = 0;
938         int i, j, bo_idx;
939         hal_tbm_surface *hal_surface = NULL;
940         hal_tbm_bo **hal_bos = NULL;
941         int num_bos = 0;
942         int flags;
943
944         surf = calloc(1, sizeof(struct _tbm_surface));
945         if (!surf) {
946                 /* LCOV_EXCL_START */
947                 TBM_ERR("fail to alloc surf");
948                 *error = TBM_ERROR_OUT_OF_MEMORY;
949                 goto alloc_surf_fail;
950                 /* LCOV_EXCL_STOP */
951         }
952         surf->refcnt = 1;
953
954         surf->magic = TBM_SURFACE_MAGIC;
955         surf->bufmgr = bufmgr;
956         surf->info.width = width;
957         surf->info.height = height;
958         surf->info.format = format;
959         surf->info.bpp = _tbm_surface_internal_get_bpp(format);
960         if (!surf->info.bpp) {
961                 TBM_ERR("fail to get bpp from format(%d), error(%s)", format, tbm_error_str(*error));
962                 *error = tbm_get_last_error();
963                 goto bpp_fail;
964         }
965
966         // get number of planes
967         surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
968         if (!surf->info.num_planes) {
969                 TBM_ERR("fail to get num_planes from format(%d), error(%s)", format, tbm_error_str(*error));
970                 *error = tbm_get_last_error();
971                 goto num_planes_fail;
972         }
973
974         // import surface
975         hal_surface = hal_tbm_bufmgr_import_surface(bufmgr->hal_bufmgr, 
976                                                                                         (uint32_t)width,
977                                                                                         (uint32_t)height,
978                                                                                         (hal_tbm_format)format,
979                                                                                         (hal_tbm_surface_buffer_data *)buffer_data,
980                                                                                         (hal_tbm_error *)error);
981         if (!hal_surface) {
982                 TBM_ERR("hal_tbm_bufmgr_import_surface failed.(width:%d height:%d format:%d error:%s)",
983                                 width, height, format, tbm_error_str(*error));
984                 goto import_surface_fail;
985         }
986         surf->hal_surface = hal_surface;
987
988         // set infomation of planes
989         for (i = 0; i < surf->info.num_planes; i++) {
990                 *error = (tbm_error_e)hal_tbm_surface_get_plane_data(hal_surface, i, &size, &offset, &stride, &bo_idx);
991                 if (*error != TBM_ERROR_NONE) {
992                         goto query_plane_data_fail;
993                 }
994                 surf->info.planes[i].size = size;
995                 surf->info.planes[i].offset = offset;
996                 surf->info.planes[i].stride = stride;
997                 surf->planes_bo_idx[i] = bo_idx;
998         }
999
1000         // set infomation of bos
1001         hal_bos = hal_tbm_surface_get_bos(hal_surface, &num_bos, (hal_tbm_error *)error);
1002         if (!hal_bos) {
1003                 TBM_ERR("fail to get bos, error(%s)", tbm_error_str(*error));
1004                 goto get_bos_fail;
1005         }
1006         surf->num_bos = num_bos;
1007
1008         for (i = 0; i < surf->info.num_planes; i++) {
1009                 surf->info.size += surf->info.planes[i].size;
1010
1011                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
1012                         surf->num_bos = surf->planes_bo_idx[i] + 1;
1013         }
1014
1015         // get memory_types(bo flags)
1016         flags =  (int)hal_tbm_bo_get_memory_types(hal_bos[0], (hal_tbm_error *)error);
1017         if (*error != TBM_ERROR_NONE) {
1018                 TBM_ERR("hal_tbm_bo_get_memory_types failed.");
1019                 goto get_memory_types_fail;
1020         }
1021         surf->flags = flags;
1022
1023         for (i = 0; i < num_bos; i++) {
1024                 surf->bos[i] = tbm_bo_alloc_with_bo_data(bufmgr, (tbm_backend_bo_data *)hal_bos[i], flags);
1025                 if (!surf->bos[i]) {
1026                         TBM_ERR("fail to alloc bo idx:%d", i);
1027                         *error = tbm_get_last_error();
1028                         goto get_bo_fail;
1029                 }
1030
1031                 _tbm_bo_set_surface(surf->bos[i], surf);
1032         }
1033
1034         *error = TBM_ERROR_NONE;
1035
1036         return surf;
1037
1038 get_bo_fail:
1039 get_memory_types_fail:
1040 get_bos_fail:
1041 query_plane_data_fail:
1042         if (hal_surface) {
1043                 hal_tbm_surface_free(hal_surface);
1044         } else {
1045                 for (j = 0; j < i; j++) {
1046                         if (surf->bos[j])
1047                                 tbm_bo_unref(surf->bos[j]);
1048                 }
1049         }
1050 import_surface_fail:
1051 num_planes_fail:
1052 bpp_fail:
1053         if (surf)
1054                 free(surf);
1055 alloc_surf_fail:
1056
1057         return NULL;
1058 }
1059
1060 int
1061 tbm_surface_internal_is_valid(tbm_surface_h surface)
1062 {
1063         int ret = 0;
1064
1065         _tbm_surface_mutex_lock();
1066         _tbm_set_last_result(TBM_ERROR_NONE);
1067
1068         /* Return silently if surface is null. */
1069         if (!surface) {
1070                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1071                 _tbm_surface_mutex_unlock();
1072                 return 0;
1073         }
1074
1075         ret = _tbm_surface_internal_is_valid(surface);
1076
1077         _tbm_surface_mutex_unlock();
1078
1079         return ret;
1080 }
1081
1082 int
1083 tbm_surface_internal_query_supported_formats(uint32_t **formats,
1084                 uint32_t *num)
1085 {
1086         struct _tbm_bufmgr *bufmgr;
1087         int ret = 0;
1088         bool bufmgr_initialized = false;
1089         tbm_error_e error;
1090
1091         _tbm_surface_mutex_lock();
1092         _tbm_set_last_result(TBM_ERROR_NONE);
1093
1094         TBM_SURFACE_RETURN_VAL_IF_FAIL(formats, 0);
1095         TBM_SURFACE_RETURN_VAL_IF_FAIL(num, 0);
1096
1097         if (!g_surface_bufmgr) {
1098                 _init_surface_bufmgr();
1099                 if (!g_surface_bufmgr) {
1100                         TBM_ERR("fail bufmgr initialization\n");
1101                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1102                         goto fail;
1103                 }
1104                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
1105                 bufmgr_initialized = true;
1106         }
1107
1108         bufmgr = g_surface_bufmgr;
1109
1110         if (bufmgr->use_hal_tbm) {
1111                 error = (tbm_error_e)hal_tbm_bufmgr_get_supported_formats(bufmgr->hal_bufmgr, formats, num);
1112                 /* LCOV_EXCL_START */
1113                 if (error == TBM_ERROR_NOT_SUPPORTED) {
1114                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1115                         goto fail;
1116                 } else if (error != TBM_ERROR_NONE) {
1117                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1118                         goto fail;
1119                 }
1120                 /* LCOV_EXCL_STOP */
1121                 ret = 1;
1122         } else if (bufmgr->backend_module_data) {
1123                 if (!bufmgr->bufmgr_func->bufmgr_get_supported_formats) {
1124                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1125                         goto fail;
1126                 }
1127
1128                 error = bufmgr->bufmgr_func->bufmgr_get_supported_formats(bufmgr->bufmgr_data, formats, num);
1129                 if (error != TBM_ERROR_NONE) {
1130                         /* LCOV_EXCL_START */
1131                         TBM_ERR("Fail to surface_supported_format. error(%d)\n", error);
1132                         goto fail;
1133                         /* LCOV_EXCL_START */
1134                 }
1135                 ret = 1;
1136         } else {
1137                 if (!bufmgr->backend->surface_supported_format) {
1138                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
1139                         goto fail;
1140                 }
1141
1142                 ret = bufmgr->backend->surface_supported_format(formats, num);
1143                 if (!ret)  {
1144                         /* LCOV_EXCL_START */
1145                         TBM_ERR("Fail to surface_supported_format.\n");
1146                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1147                         goto fail;
1148                         /* LCOV_EXCL_START */
1149                 }
1150         }
1151
1152         TBM_TRACE_SURFACE_INTERNAL("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
1153
1154         if (bufmgr_initialized) {
1155                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
1156                 _deinit_surface_bufmgr();
1157         }
1158
1159         _tbm_surface_mutex_unlock();
1160
1161         return ret;
1162
1163 /* LCOV_EXCL_START */
1164 fail:
1165         if (bufmgr_initialized) {
1166                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
1167                 _deinit_surface_bufmgr();
1168         }
1169         _tbm_surface_mutex_unlock();
1170
1171         TBM_ERR("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
1172
1173         return 0;
1174 /* LCOV_EXCL_STOP */
1175 }
1176
1177 int
1178 tbm_surface_internal_get_num_planes(tbm_format format)
1179 {
1180         int num_planes = 0;
1181
1182         _tbm_surface_mutex_lock();
1183         _tbm_set_last_result(TBM_ERROR_NONE);
1184
1185         num_planes = _tbm_surface_internal_get_num_planes(format);
1186         if (!num_planes) {
1187                 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
1188                 _tbm_surface_mutex_unlock();
1189                 return 0;
1190         }
1191
1192         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
1193
1194         _tbm_surface_mutex_unlock();
1195
1196         return num_planes;
1197 }
1198
1199 int
1200 tbm_surface_internal_get_bpp(tbm_format format)
1201 {
1202         int bpp = 0;
1203
1204         _tbm_surface_mutex_lock();
1205         _tbm_set_last_result(TBM_ERROR_NONE);
1206
1207         bpp = _tbm_surface_internal_get_bpp(format);
1208         if (!bpp) {
1209                 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
1210                 _tbm_surface_mutex_unlock();
1211                 return 0;
1212         }
1213
1214         _tbm_surface_mutex_unlock();
1215
1216         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
1217
1218         return bpp;
1219 }
1220
1221 tbm_surface_h
1222 tbm_surface_internal_create_with_flags(int width, int height,
1223                                        int format, int flags)
1224 {
1225         struct _tbm_bufmgr *bufmgr;
1226         struct _tbm_surface *surf = NULL;
1227         tbm_error_e error = TBM_ERROR_INVALID_OPERATION;
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(width > 0, NULL);
1234         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, NULL);
1235
1236         if (!g_surface_bufmgr) {
1237                 _init_surface_bufmgr();
1238                 if (!g_surface_bufmgr) {
1239                         TBM_ERR("fail bufmgr initialization\n");
1240                         error = TBM_ERROR_INVALID_OPERATION;
1241                         goto check_valid_fail;
1242                 }
1243                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
1244                 bufmgr_initialized = true;
1245         }
1246
1247         bufmgr = g_surface_bufmgr;
1248         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
1249                 TBM_ERR("The bufmgr is invalid\n");
1250                 error = TBM_ERROR_INVALID_PARAMETER;
1251                 goto check_valid_fail;
1252         }
1253
1254         if (bufmgr->use_hal_tbm) {
1255                 surf = _tbm_surface_internal_hal_tbm_create_surface(bufmgr, width, height, format, flags, &error);
1256                 if (!surf) {
1257                         TBM_ERR("_tbm_surface_internal_hal_tbm_create_surface failed.");
1258                         goto surface_alloc_fail;
1259                 }
1260         } else {
1261                 surf = _tbm_surface_internal_create_surface(bufmgr, width, height, format, flags, &error);
1262                 if (!surf) {
1263                         TBM_ERR("_tbm_surface_internal_create_surface failed.");
1264                         goto surface_alloc_fail;
1265                 }
1266         }
1267
1268         TBM_TRACE_SURFACE_INTERNAL("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n",
1269                         width, height, _tbm_surface_internal_format_to_str(format), flags, surf);
1270
1271         LIST_INITHEAD(&surf->user_data_list);
1272         LIST_INITHEAD(&surf->debug_data_list);
1273         LIST_INITHEAD(&surf->destroy_funcs);
1274
1275         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1276
1277         _tbm_set_last_result(error);
1278         _tbm_surface_mutex_unlock();
1279
1280         return surf;
1281
1282 /* LCOV_EXCL_START */
1283
1284 surface_alloc_fail:
1285 check_valid_fail:
1286         if (bufmgr_initialized && bufmgr) {
1287                 LIST_DELINIT(&bufmgr->surf_list);
1288                 _deinit_surface_bufmgr();
1289         }
1290
1291         TBM_ERR("error: width(%d) height(%d) format(%s) flags(%d)\n",
1292                 width, height, _tbm_surface_internal_format_to_str(format), flags);
1293
1294         _tbm_set_last_result(error);
1295         _tbm_surface_mutex_unlock();
1296
1297 /* LCOV_EXCL_STOP */
1298
1299         return NULL;
1300 }
1301
1302 tbm_surface_h
1303 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
1304                                      tbm_bo *bos, int num)
1305 {
1306         struct _tbm_bufmgr *bufmgr;
1307         struct _tbm_surface *surf = NULL;
1308         int i;
1309         bool bufmgr_initialized = false;
1310
1311         _tbm_surface_mutex_lock();
1312         _tbm_set_last_result(TBM_ERROR_NONE);
1313
1314         TBM_SURFACE_RETURN_VAL_IF_FAIL(bos, NULL);
1315         TBM_SURFACE_RETURN_VAL_IF_FAIL(info, NULL);
1316         TBM_SURFACE_RETURN_VAL_IF_FAIL(info->num_planes > 0, NULL);
1317         TBM_SURFACE_RETURN_VAL_IF_FAIL(num > 0, NULL);
1318         TBM_SURFACE_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
1319
1320         if (!g_surface_bufmgr) {
1321                 _init_surface_bufmgr();
1322                 if (!g_surface_bufmgr) {
1323                         TBM_ERR("fail bufmgr initialization\n");
1324                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1325                         goto check_valid_fail;
1326                 }
1327                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
1328                 bufmgr_initialized = true;
1329         }
1330
1331         bufmgr = g_surface_bufmgr;
1332         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
1333                 TBM_ERR("fail to validate the Bufmgr.\n");
1334                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1335                 goto check_valid_fail;
1336         }
1337
1338         surf = calloc(1, sizeof(struct _tbm_surface));
1339         if (!surf) {
1340                 /* LCOV_EXCL_START */
1341                 TBM_ERR("fail to allocate struct _tbm_surface.\n");
1342                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1343                 goto alloc_surf_fail;
1344                 /* LCOV_EXCL_STOP */
1345         }
1346
1347         surf->magic = TBM_SURFACE_MAGIC;
1348         surf->bufmgr = bufmgr;
1349         surf->info.width = info->width;
1350         surf->info.height = info->height;
1351         surf->info.format = info->format;
1352         if (info->bpp > 0)
1353                 surf->info.bpp = info->bpp;
1354         else {
1355                 surf->info.bpp = _tbm_surface_internal_get_bpp(info->format);
1356                 if (!surf->info.bpp) {
1357                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1358                         goto bpp_fail;
1359                 }
1360         }
1361         surf->info.num_planes = info->num_planes;
1362         surf->refcnt = 1;
1363
1364         /* get size, stride and offset */
1365         for (i = 0; i < info->num_planes; i++) {
1366                 surf->info.planes[i].offset = info->planes[i].offset;
1367                 surf->info.planes[i].stride = info->planes[i].stride;
1368
1369                 if (info->planes[i].size > 0)
1370                         surf->info.planes[i].size = info->planes[i].size;
1371                 else {
1372                         uint32_t size = 0, offset = 0, stride = 0;
1373                         int32_t bo_idx = 0;
1374
1375                         if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
1376                                 TBM_ERR("fail to get plane_data. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1377                                 goto plane_data_fail;
1378                         }
1379                         surf->info.planes[i].size = size;
1380                 }
1381
1382                 if (num == 1)
1383                         surf->planes_bo_idx[i] = 0;
1384                 else
1385                         surf->planes_bo_idx[i] = i;
1386         }
1387
1388         if (info->size > 0) {
1389                 surf->info.size = info->size;
1390         } else {
1391                 surf->info.size = 0;
1392                 for (i = 0; i < info->num_planes; i++)
1393                         surf->info.size += surf->info.planes[i].size;
1394         }
1395
1396         surf->flags = TBM_BO_DEFAULT;
1397
1398         /* create only one bo */
1399         surf->num_bos = num;
1400         for (i = 0; i < num; i++) {
1401                 if (bos[i] == NULL) {
1402                         TBM_ERR("bos[%d] is null.\n", i);
1403                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1404                         goto check_bo_fail;
1405                 }
1406
1407                 surf->bos[i] = tbm_bo_ref(bos[i]);
1408                 _tbm_bo_set_surface(bos[i], surf);
1409         }
1410
1411         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
1412                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
1413
1414         LIST_INITHEAD(&surf->user_data_list);
1415         LIST_INITHEAD(&surf->debug_data_list);
1416         LIST_INITHEAD(&surf->destroy_funcs);
1417
1418         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1419
1420         _tbm_surface_mutex_unlock();
1421
1422         return surf;
1423
1424 /* LCOV_EXCL_START */
1425 check_bo_fail:
1426 plane_data_fail:
1427 bpp_fail:
1428         for (i = 0; i < num; i++) {
1429                 if (surf->bos[i])
1430                         tbm_bo_unref(surf->bos[i]);
1431         }
1432         free(surf);
1433 alloc_surf_fail:
1434 check_valid_fail:
1435         if (bufmgr_initialized && bufmgr) {
1436                 LIST_DELINIT(&bufmgr->surf_list);
1437                 _deinit_surface_bufmgr();
1438         }
1439         _tbm_surface_mutex_unlock();
1440
1441         TBM_ERR("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
1442                         info->width, info->height,
1443                         _tbm_surface_internal_format_to_str(info->format), num);
1444 /* LCOV_EXCL_STOP */
1445
1446         return NULL;
1447 }
1448
1449 void
1450 tbm_surface_internal_destroy(tbm_surface_h surface)
1451 {
1452         _tbm_surface_mutex_lock();
1453         _tbm_set_last_result(TBM_ERROR_NONE);
1454
1455         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1456
1457         surface->refcnt--;
1458
1459         if (surface->refcnt > 0) {
1460                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1461                 _tbm_surface_mutex_unlock();
1462                 return;
1463         }
1464
1465         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1466
1467         if (surface->refcnt == 0)
1468                 _tbm_surface_internal_destroy(surface);
1469         else // if (surface->refcnt < 0)
1470                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1471
1472         _tbm_surface_mutex_unlock();
1473 }
1474
1475 void
1476 tbm_surface_internal_ref(tbm_surface_h surface)
1477 {
1478         _tbm_surface_mutex_lock();
1479         _tbm_set_last_result(TBM_ERROR_NONE);
1480
1481         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1482
1483         surface->refcnt++;
1484
1485         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1486
1487         _tbm_surface_mutex_unlock();
1488 }
1489
1490 void
1491 tbm_surface_internal_unref(tbm_surface_h surface)
1492 {
1493         _tbm_surface_mutex_lock();
1494         _tbm_set_last_result(TBM_ERROR_NONE);
1495
1496         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1497
1498         surface->refcnt--;
1499
1500         if (surface->refcnt > 0) {
1501                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1502                 _tbm_surface_mutex_unlock();
1503                 return;
1504         }
1505
1506         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1507
1508         if (surface->refcnt == 0)
1509                 _tbm_surface_internal_destroy(surface);
1510
1511         _tbm_surface_mutex_unlock();
1512 }
1513
1514 int
1515 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
1516 {
1517         struct _tbm_surface *surf;
1518         int num;
1519
1520         _tbm_surface_mutex_lock();
1521         _tbm_set_last_result(TBM_ERROR_NONE);
1522
1523         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1524
1525         surf = (struct _tbm_surface *)surface;
1526         num = surf->num_bos;
1527
1528         if (!num)
1529                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1530
1531         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) num_bos(%d)\n", surface, num);
1532
1533         _tbm_surface_mutex_unlock();
1534
1535         return num;
1536 }
1537
1538 tbm_bo
1539 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
1540 {
1541         struct _tbm_surface *surf;
1542         tbm_bo bo;
1543
1544         _tbm_surface_mutex_lock();
1545         _tbm_set_last_result(TBM_ERROR_NONE);
1546
1547         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
1548         TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
1549
1550         surf = (struct _tbm_surface *)surface;
1551         bo = surf->bos[bo_idx];
1552
1553         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
1554
1555         _tbm_surface_mutex_unlock();
1556
1557         return bo;
1558 }
1559
1560 unsigned int
1561 tbm_surface_internal_get_size(tbm_surface_h surface)
1562 {
1563         struct _tbm_surface *surf;
1564         unsigned int size;
1565
1566         _tbm_surface_mutex_lock();
1567         _tbm_set_last_result(TBM_ERROR_NONE);
1568
1569         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1570
1571         surf = (struct _tbm_surface *)surface;
1572         size = surf->info.size;
1573
1574         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) size(%u)\n", surface, size);
1575
1576         _tbm_surface_mutex_unlock();
1577
1578         return size;
1579 }
1580
1581 int
1582 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1583                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
1584 {
1585         struct _tbm_surface *surf;
1586
1587         _tbm_surface_mutex_lock();
1588         _tbm_set_last_result(TBM_ERROR_NONE);
1589
1590         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1591         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1592
1593         surf = (struct _tbm_surface *)surface;
1594
1595         if (plane_idx >= surf->info.num_planes) {
1596                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1597                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1598                 _tbm_surface_mutex_unlock();
1599                 return 0;
1600         }
1601
1602         if (size)
1603                 *size = surf->info.planes[plane_idx].size;
1604
1605         if (offset)
1606                 *offset = surf->info.planes[plane_idx].offset;
1607
1608         if (pitch)
1609                 *pitch = surf->info.planes[plane_idx].stride;
1610
1611         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1612                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1613                                 surf->info.planes[plane_idx].stride);
1614
1615         _tbm_surface_mutex_unlock();
1616
1617         return 1;
1618 }
1619
1620 int
1621 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1622                               tbm_surface_info_s *info, int map)
1623 {
1624         struct _tbm_surface *surf;
1625         tbm_bo_handle bo_handles[4];
1626         int num_bos = 0;
1627         tbm_bo bos[4];
1628         int planes_bo_idx[TBM_SURF_PLANE_MAX];
1629         int i, j;
1630
1631         _tbm_surface_mutex_lock();
1632         _tbm_set_last_result(TBM_ERROR_NONE);
1633
1634         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1635
1636         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1637
1638         surf = (struct _tbm_surface *)surface;
1639
1640         memset(info, 0x00, sizeof(tbm_surface_info_s));
1641         info->width = surf->info.width;
1642         info->height = surf->info.height;
1643         info->format = surf->info.format;
1644         info->bpp = surf->info.bpp;
1645         info->size = surf->info.size;
1646         info->num_planes = surf->info.num_planes;
1647
1648         for (i = 0; i < surf->info.num_planes; i++) {
1649                 info->planes[i].size = surf->info.planes[i].size;
1650                 info->planes[i].offset = surf->info.planes[i].offset;
1651                 info->planes[i].stride = surf->info.planes[i].stride;
1652                 planes_bo_idx[i] = surf->planes_bo_idx[i];
1653         }
1654
1655         for (i = 0; i < surf->num_bos; i++)
1656                 bos[i] = surf->bos[i];
1657
1658         num_bos = surf->num_bos;
1659
1660         if (map == 1) {
1661                 _tbm_surface_mutex_unlock();
1662                 for (i = 0; i < num_bos; i++) {
1663                         bo_handles[i] = tbm_bo_map(bos[i], TBM_DEVICE_CPU, opt);
1664                         if (bo_handles[i].ptr == NULL) {
1665                                 for (j = 0; j < i; j++)
1666                                         tbm_bo_unmap(bos[j]);
1667
1668                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1669                                 return 0;
1670                         }
1671                 }
1672                 _tbm_surface_mutex_lock();
1673         } else {
1674                 for (i = 0; i < num_bos; i++) {
1675                         bo_handles[i] = tbm_bo_get_handle(bos[i], TBM_DEVICE_CPU);
1676                         if (bo_handles[i].ptr == NULL) {
1677                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1678                                 _tbm_surface_mutex_unlock();
1679                                 return 0;
1680                         }
1681                 }
1682         }
1683
1684         for (i = 0; i < info->num_planes; i++) {
1685                 if (bo_handles[planes_bo_idx[i]].ptr)
1686                         info->planes[i].ptr = bo_handles[planes_bo_idx[i]].ptr + info->planes[i].offset;
1687         }
1688
1689         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1690
1691         _tbm_surface_mutex_unlock();
1692
1693         return 1;
1694 }
1695
1696 void
1697 tbm_surface_internal_unmap(tbm_surface_h surface)
1698 {
1699         struct _tbm_surface *surf;
1700         int i;
1701
1702         _tbm_surface_mutex_lock();
1703         _tbm_set_last_result(TBM_ERROR_NONE);
1704
1705         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1706
1707         surf = (struct _tbm_surface *)surface;
1708
1709         for (i = 0; i < surf->num_bos; i++)
1710                 tbm_bo_unmap(surf->bos[i]);
1711
1712         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)\n", surface);
1713
1714         _tbm_surface_mutex_unlock();
1715 }
1716
1717 unsigned int
1718 tbm_surface_internal_get_width(tbm_surface_h surface)
1719 {
1720         struct _tbm_surface *surf;
1721         unsigned int width;
1722
1723         _tbm_surface_mutex_lock();
1724         _tbm_set_last_result(TBM_ERROR_NONE);
1725
1726         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1727
1728         surf = (struct _tbm_surface *)surface;
1729         width = surf->info.width;
1730
1731         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u)\n", surface, width);
1732
1733         _tbm_surface_mutex_unlock();
1734
1735         return width;
1736 }
1737
1738 unsigned int
1739 tbm_surface_internal_get_height(tbm_surface_h surface)
1740 {
1741         struct _tbm_surface *surf;
1742         unsigned int height;
1743
1744         _tbm_surface_mutex_lock();
1745         _tbm_set_last_result(TBM_ERROR_NONE);
1746
1747         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1748
1749         surf = (struct _tbm_surface *)surface;
1750         height = surf->info.height;
1751
1752         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) height(%u)\n", surface, height);
1753
1754         _tbm_surface_mutex_unlock();
1755
1756         return height;
1757
1758 }
1759
1760 tbm_format
1761 tbm_surface_internal_get_format(tbm_surface_h surface)
1762 {
1763         struct _tbm_surface *surf;
1764         tbm_format format;
1765
1766         _tbm_surface_mutex_lock();
1767         _tbm_set_last_result(TBM_ERROR_NONE);
1768
1769         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1770
1771         surf = (struct _tbm_surface *)surface;
1772         format = surf->info.format;
1773
1774         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1775
1776         _tbm_surface_mutex_unlock();
1777
1778         return format;
1779 }
1780
1781 int
1782 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1783 {
1784         struct _tbm_surface *surf;
1785         int bo_idx;
1786
1787         _tbm_surface_mutex_lock();
1788         _tbm_set_last_result(TBM_ERROR_NONE);
1789
1790         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1791         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1792
1793         surf = (struct _tbm_surface *)surface;
1794         bo_idx = surf->planes_bo_idx[plane_idx];
1795
1796         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1797
1798         _tbm_surface_mutex_unlock();
1799
1800         return bo_idx;
1801 }
1802
1803 int
1804 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1805                                    tbm_data_free data_free_func)
1806 {
1807         tbm_user_data *data;
1808
1809         _tbm_surface_mutex_lock();
1810         _tbm_set_last_result(TBM_ERROR_NONE);
1811
1812         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1813
1814         /* check if the data according to the key exist if so, return false. */
1815         data = user_data_lookup(&surface->user_data_list, key);
1816         if (data) {
1817                 TBM_TRACE_SURFACE_INTERNAL("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1818                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1819                 _tbm_surface_mutex_unlock();
1820                 return 0;
1821         }
1822
1823         data = user_data_create(key, data_free_func);
1824         if (!data) {
1825                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1826                 _tbm_surface_mutex_unlock();
1827                 return 0;
1828         }
1829
1830         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1831
1832         LIST_ADD(&data->item_link, &surface->user_data_list);
1833
1834         _tbm_surface_mutex_unlock();
1835
1836         return 1;
1837 }
1838
1839 int
1840 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1841                                    void *data)
1842 {
1843         tbm_user_data *old_data;
1844
1845         _tbm_surface_mutex_lock();
1846         _tbm_set_last_result(TBM_ERROR_NONE);
1847
1848         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1849
1850         old_data = user_data_lookup(&surface->user_data_list, key);
1851         if (!old_data) {
1852                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1853                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1854                 _tbm_surface_mutex_unlock();
1855                 return 0;
1856         }
1857
1858         if (old_data->data && old_data->free_func)
1859                 old_data->free_func(old_data->data);
1860
1861         old_data->data = data;
1862
1863         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1864
1865         _tbm_surface_mutex_unlock();
1866
1867         return 1;
1868 }
1869
1870 int
1871 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1872                                    void **data)
1873 {
1874         tbm_user_data *old_data;
1875
1876         _tbm_surface_mutex_lock();
1877         _tbm_set_last_result(TBM_ERROR_NONE);
1878
1879         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1880
1881         if (!data) {
1882                 TBM_ERR("error: tbm_surface(%p) key(%lu)\n", surface, key);
1883                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1884                 _tbm_surface_mutex_unlock();
1885                 return 0;
1886         }
1887         *data = NULL;
1888
1889         old_data = user_data_lookup(&surface->user_data_list, key);
1890         if (!old_data) {
1891                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1892                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1893                 _tbm_surface_mutex_unlock();
1894                 return 0;
1895         }
1896
1897         *data = old_data->data;
1898
1899         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1900
1901         _tbm_surface_mutex_unlock();
1902
1903         return 1;
1904 }
1905
1906 int
1907 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1908                                       unsigned long key)
1909 {
1910         tbm_user_data *old_data = (void *)0;
1911
1912         _tbm_surface_mutex_lock();
1913         _tbm_set_last_result(TBM_ERROR_NONE);
1914
1915         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1916
1917         old_data = user_data_lookup(&surface->user_data_list, key);
1918         if (!old_data) {
1919                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1920                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1921                 _tbm_surface_mutex_unlock();
1922                 return 0;
1923         }
1924
1925         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1926
1927         user_data_delete(old_data);
1928
1929         _tbm_surface_mutex_unlock();
1930
1931         return 1;
1932 }
1933
1934 /* LCOV_EXCL_START */
1935 unsigned int
1936 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1937 {
1938         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1939
1940         return surface->debug_pid;
1941 }
1942
1943 void
1944 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1945 {
1946         _tbm_surface_mutex_lock();
1947         _tbm_set_last_result(TBM_ERROR_NONE);
1948
1949         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1950
1951         surface->debug_pid = pid;
1952
1953         _tbm_surface_mutex_unlock();
1954 }
1955
1956 static tbm_surface_debug_data *
1957 _tbm_surface_internal_debug_data_create(char *key, char *value)
1958 {
1959         tbm_surface_debug_data *debug_data = NULL;
1960
1961         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1962         if (!debug_data) {
1963                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1964                 TBM_ERR("fail to allocate the debug_data.");
1965                 return NULL;
1966         }
1967
1968         if (key) debug_data->key = strdup(key);
1969         if (value) debug_data->value = strdup(value);
1970
1971         return debug_data;
1972 }
1973
1974 static void
1975 _tbm_surface_internal_debug_data_value_update(tbm_surface_debug_data *debug_data, char *value)
1976 {
1977         if (!debug_data->value && !value)
1978                 return;
1979
1980         if (debug_data->value && value && !strncmp(debug_data->value, value, strlen(debug_data->value)))
1981                 return;
1982
1983         if (debug_data->value)
1984                 free(debug_data->value);
1985
1986         if (value)
1987                 debug_data->value = strdup(value);
1988         else
1989                 debug_data->value = NULL;
1990 }
1991
1992 static tbm_surface_debug_data *
1993 _tbm_surface_internal_debug_data_find(struct list_head *list, char *key)
1994 {
1995         tbm_surface_debug_data *debug_data = NULL;
1996
1997         if (LIST_IS_EMPTY(list))
1998                 return NULL;
1999
2000         LIST_FOR_EACH_ENTRY(debug_data, list, item_link) {
2001                 if (!strncmp(debug_data->key, key, strlen(debug_data->key)))
2002                         return debug_data;
2003         }
2004
2005         return NULL;
2006 }
2007
2008 int
2009 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
2010 {
2011         tbm_surface_debug_data *debug_data = NULL;
2012         tbm_bufmgr bufmgr = NULL;
2013
2014         _tbm_surface_mutex_lock();
2015         _tbm_set_last_result(TBM_ERROR_NONE);
2016
2017         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2018         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
2019
2020         bufmgr = surface->bufmgr;
2021
2022         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
2023
2024         debug_data = _tbm_surface_internal_debug_data_find(&surface->debug_data_list, key);
2025         if (debug_data) {
2026                 _tbm_surface_internal_debug_data_value_update(debug_data, value);
2027         } else {
2028                 debug_data = _tbm_surface_internal_debug_data_create(key, value);
2029                 if (!debug_data) {
2030                         TBM_ERR("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
2031                         _tbm_surface_mutex_unlock();
2032                         return 0;
2033                 }
2034
2035                 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
2036         }
2037
2038         /* add new debug key to list */
2039         debug_data = _tbm_surface_internal_debug_data_find(&bufmgr->debug_key_list, key);
2040         if (!debug_data) {
2041                 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
2042                 if (debug_data)
2043                         LIST_ADDTAIL(&debug_data->item_link, &bufmgr->debug_key_list);
2044         }
2045
2046         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
2047
2048         _tbm_surface_mutex_unlock();
2049
2050         return 1;
2051 }
2052
2053 char *
2054 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
2055 {
2056         tbm_surface_debug_data *old_data = NULL;
2057
2058         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
2059
2060         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
2061                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
2062                         if (!strcmp(old_data->key, key))
2063                                 return old_data->value;
2064                 }
2065         }
2066
2067         return NULL;
2068 }
2069
2070 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
2071 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
2072
2073 struct _tbm_surface_dump_buf_info {
2074         int index;
2075         tbm_bo bo;
2076         int size;
2077         int dirty;
2078         int dirty_shm;
2079         int shm_stride;
2080         int shm_h;
2081         char name[1024];
2082
2083         tbm_surface_info_s info;
2084
2085         struct list_head link;
2086 };
2087
2088 struct _tbm_surface_dump_info {
2089         char *path;  // copy???
2090         int dump_max;
2091         int count;
2092         struct list_head *link;
2093         struct list_head surface_list; /* link of surface */
2094 };
2095
2096 static tbm_surface_dump_info *g_dump_info = NULL;
2097 static const char *dump_postfix[2] = {"png", "yuv"};
2098 static double scale_factor;
2099
2100 static void
2101 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
2102                                 void *data2, int size2, void *data3, int size3)
2103 {
2104         FILE *fp;
2105         unsigned int *blocks;
2106
2107         if (_tbm_surface_check_file_is_symbolic_link(file))
2108                 TBM_ERR("%s is symbolic link\n", file);
2109
2110         fp = fopen(file, "w+");
2111         TBM_RETURN_IF_FAIL(fp != NULL);
2112
2113         blocks = (unsigned int *)data1;
2114         fwrite(blocks, 1, size1, fp);
2115
2116         if (size2 > 0) {
2117                 blocks = (unsigned int *)data2;
2118                 fwrite(blocks, 1, size2, fp);
2119         }
2120
2121         if (size3 > 0) {
2122                 blocks = (unsigned int *)data3;
2123                 fwrite(blocks, 1, size3, fp);
2124         }
2125
2126         fclose(fp);
2127 }
2128
2129 static void
2130 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height, int stride, int format)
2131 {
2132         unsigned int *blocks = (unsigned int *)data;
2133         FILE *fp;
2134         int pixel_size;
2135         png_bytep *row_pointers;
2136         int depth = 8, y;
2137
2138         if (_tbm_surface_check_file_is_symbolic_link(file))
2139                 TBM_ERR("%s is symbolic link\n", file);
2140
2141         fp = fopen(file, "wb");
2142         TBM_RETURN_IF_FAIL(fp != NULL);
2143
2144         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
2145                                                         NULL, NULL, NULL);
2146         if (!pPngStruct) {
2147                 TBM_ERR("fail to create a png write structure.\n");
2148                 fclose(fp);
2149                 return;
2150         }
2151
2152         png_infop pPngInfo = png_create_info_struct(pPngStruct);
2153         if (!pPngInfo) {
2154                 TBM_ERR("fail to create a png info structure.\n");
2155                 png_destroy_write_struct(&pPngStruct, NULL);
2156                 fclose(fp);
2157                 return;
2158         }
2159
2160         if (setjmp(png_jmpbuf(pPngStruct))) {
2161                 /* if png has problem of writing the file, we get here */
2162                 TBM_ERR("fail to write png file.\n");
2163                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
2164                 fclose(fp);
2165                 return;
2166         }
2167
2168         png_init_io(pPngStruct, fp);
2169         if (format == TBM_FORMAT_XRGB8888) {
2170                 pixel_size = 3;
2171                 png_set_IHDR(pPngStruct,
2172                                 pPngInfo,
2173                                 width,
2174                                 height,
2175                                 depth,
2176                                 PNG_COLOR_TYPE_RGB,
2177                                 PNG_INTERLACE_NONE,
2178                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
2179         } else {
2180                 pixel_size = 4;
2181                 png_set_IHDR(pPngStruct,
2182                                 pPngInfo,
2183                                 width,
2184                                 height,
2185                                 depth,
2186                                 PNG_COLOR_TYPE_RGBA,
2187                                 PNG_INTERLACE_NONE,
2188                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
2189         }
2190
2191         png_set_bgr(pPngStruct);
2192         png_write_info(pPngStruct, pPngInfo);
2193
2194         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
2195         if (!row_pointers) {
2196                 TBM_ERR("fail to allocate the png row_pointers.\n");
2197                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
2198                 fclose(fp);
2199                 return;
2200         }
2201
2202         for (y = 0; y < height; ++y) {
2203                 png_bytep row;
2204                 int x = 0;
2205
2206                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
2207                 if (!row) {
2208                         TBM_ERR("fail to allocate the png row.\n");
2209                         for (x = 0; x < y; x++)
2210                                 png_free(pPngStruct, row_pointers[x]);
2211                         png_free(pPngStruct, row_pointers);
2212                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
2213                         fclose(fp);
2214                         return;
2215                 }
2216                 row_pointers[y] = (png_bytep)row;
2217
2218                 for (x = 0; x < width; ++x) {
2219                         unsigned int curBlock = blocks[(y * (stride >> 2)) + x];
2220
2221                         if (pixel_size == 3) { // XRGB8888
2222                                 row[x * pixel_size] = (curBlock & 0xFF);
2223                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
2224                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
2225                         } else { // ARGB8888
2226                                 row[x * pixel_size] = (curBlock & 0xFF);
2227                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
2228                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
2229                                 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
2230                         }
2231                 }
2232         }
2233
2234         png_write_image(pPngStruct, row_pointers);
2235         png_write_end(pPngStruct, pPngInfo);
2236
2237         for (y = 0; y < height; y++)
2238                 png_free(pPngStruct, row_pointers[y]);
2239         png_free(pPngStruct, row_pointers);
2240
2241         png_destroy_write_struct(&pPngStruct, &pPngInfo);
2242
2243         fclose(fp);
2244 }
2245
2246 void
2247 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
2248 {
2249         TBM_RETURN_IF_FAIL(path != NULL);
2250         TBM_RETURN_IF_FAIL(w > 0);
2251         TBM_RETURN_IF_FAIL(h > 0);
2252         TBM_RETURN_IF_FAIL(count > 0);
2253
2254         tbm_surface_dump_buf_info *buf_info = NULL;
2255         tbm_surface_h tbm_surface;
2256         tbm_surface_info_s info;
2257         int buffer_size, i;
2258
2259         /* check running */
2260         if (g_dump_info) {
2261                 TBM_WRN("waring already running the tbm_surface_internal_dump.\n");
2262                 return;
2263         }
2264
2265         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
2266         TBM_RETURN_IF_FAIL(g_dump_info);
2267
2268         LIST_INITHEAD(&g_dump_info->surface_list);
2269         g_dump_info->count = 0;
2270         g_dump_info->dump_max = count;
2271
2272         /* get buffer size */
2273         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
2274         if (tbm_surface == NULL) {
2275                 TBM_ERR("tbm_surface_create fail\n");
2276                 free(g_dump_info);
2277                 g_dump_info = NULL;
2278                 return;
2279         }
2280
2281         if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
2282                 TBM_ERR("tbm_surface_get_info fail\n");
2283                 tbm_surface_destroy(tbm_surface);
2284                 free(g_dump_info);
2285                 g_dump_info = NULL;
2286                 return;
2287         }
2288         buffer_size = info.size;
2289         tbm_surface_destroy(tbm_surface);
2290
2291         /* create dump lists */
2292         for (i = 0; i < count; i++) {
2293                 tbm_bo bo = NULL;
2294
2295                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
2296                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
2297
2298                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
2299                 if (bo == NULL) {
2300                         TBM_ERR("fail to allocate the tbm_bo[%d]\n", i);
2301                         free(buf_info);
2302                         goto fail;
2303                 }
2304
2305                 buf_info->index = i;
2306                 buf_info->bo = bo;
2307                 buf_info->size = buffer_size;
2308
2309                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
2310         }
2311
2312         g_dump_info->path = path;
2313         g_dump_info->link = &g_dump_info->surface_list;
2314
2315         scale_factor = 0.0;
2316
2317         TBM_INFO("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
2318
2319         return;
2320
2321 fail:
2322         /* free resources */
2323         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2324                 tbm_surface_dump_buf_info *tmp;
2325
2326                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2327                         tbm_bo_unref(buf_info->bo);
2328                         LIST_DEL(&buf_info->link);
2329                         free(buf_info);
2330                 }
2331         }
2332
2333         TBM_ERR("Dump Start fail.. path:%s\n", g_dump_info->path);
2334
2335         free(g_dump_info);
2336         g_dump_info = NULL;
2337
2338         return;
2339 }
2340
2341 void
2342 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
2343 {
2344         if (scale > 0.0) {
2345                 w *= scale;
2346                 h *= scale;
2347         }
2348
2349         tbm_surface_internal_dump_start(path, w, h, count);
2350         scale_factor = scale;
2351 }
2352
2353 void
2354 tbm_surface_internal_dump_end(void)
2355 {
2356         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
2357         tbm_bo_handle bo_handle;
2358
2359         if (!g_dump_info)
2360                 return;
2361
2362         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2363                 free(g_dump_info);
2364                 g_dump_info = NULL;
2365                 return;
2366         }
2367
2368         /* make files */
2369         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2370                 char file[2048];
2371
2372                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
2373                 if (bo_handle.ptr == NULL) {
2374                         tbm_bo_unref(buf_info->bo);
2375                         LIST_DEL(&buf_info->link);
2376                         free(buf_info);
2377                         continue;
2378                 }
2379
2380                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
2381                 TBM_INFO("Dump File.. %s generated.\n", file);
2382
2383                 if (buf_info->dirty) {
2384                         void *ptr1 = NULL, *ptr2 = NULL;
2385
2386                         switch (buf_info->info.format) {
2387                         case TBM_FORMAT_ARGB8888:
2388                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2389                                                         buf_info->info.planes[0].stride >> 2,
2390                                                         buf_info->info.height,
2391                                                         buf_info->info.planes[0].stride,
2392                                                         TBM_FORMAT_ARGB8888);
2393                                 break;
2394                         case TBM_FORMAT_XRGB8888:
2395                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2396                                                         buf_info->info.planes[0].stride >> 2,
2397                                                         buf_info->info.height,
2398                                                         buf_info->info.planes[0].stride,
2399                                                         TBM_FORMAT_XRGB8888);
2400                                 break;
2401                         case TBM_FORMAT_YVU420:
2402                         case TBM_FORMAT_YUV420:
2403                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2404                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
2405                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2406                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2407                                                         ptr1,
2408                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2409                                                         ptr2,
2410                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
2411                                 break;
2412                         case TBM_FORMAT_NV12:
2413                         case TBM_FORMAT_NV21:
2414                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2415                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2416                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2417                                                         ptr1,
2418                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2419                                                         NULL, 0);
2420                                 break;
2421                         case TBM_FORMAT_YUYV:
2422                         case TBM_FORMAT_UYVY:
2423                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2424                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2425                                                         NULL, 0, NULL, 0);
2426                                 break;
2427                         default:
2428                                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
2429                                 break;
2430                         }
2431                 } else if (buf_info->dirty_shm)
2432                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2433                                                         buf_info->shm_stride >> 2,
2434                                                         buf_info->shm_h,
2435                                                         buf_info->shm_stride, 0);
2436
2437                 tbm_bo_unmap(buf_info->bo);
2438                 tbm_bo_unref(buf_info->bo);
2439                 LIST_DEL(&buf_info->link);
2440                 free(buf_info);
2441         }
2442
2443         free(g_dump_info);
2444         g_dump_info = NULL;
2445
2446         TBM_INFO("Dump End..\n");
2447 }
2448
2449 static pixman_format_code_t
2450 _tbm_surface_internal_pixman_format_get(tbm_format format)
2451 {
2452         switch (format) {
2453         case TBM_FORMAT_ARGB8888:
2454                 return PIXMAN_a8r8g8b8;
2455         case TBM_FORMAT_XRGB8888:
2456                 return PIXMAN_x8r8g8b8;
2457         default:
2458                 return 0;
2459         }
2460
2461         return 0;
2462 }
2463
2464 /**
2465  * This function supports only if a buffer has below formats.
2466  * - TBM_FORMAT_ARGB8888
2467  * - TBM_FORMAT_XRGB8888
2468  */
2469 static tbm_surface_error_e
2470 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
2471                                                                    int format, int src_stride, int src_w, int src_h,
2472                                                                    int dst_stride, int dst_w, int dst_h)
2473 {
2474         pixman_image_t *src_img = NULL, *dst_img = NULL;
2475         pixman_format_code_t pixman_format;
2476         pixman_transform_t t;
2477         struct pixman_f_transform ft;
2478         double scale_x, scale_y;
2479
2480         TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2481         TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2482
2483         pixman_format = _tbm_surface_internal_pixman_format_get(format);
2484         TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2485
2486         /* src */
2487         src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2488                                                                            (uint32_t*)src_ptr, src_stride);
2489         TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2490
2491         /* dst */
2492         dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2493                                                                            (uint32_t*)dst_ptr, dst_stride);
2494         TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2495
2496         pixman_f_transform_init_identity(&ft);
2497
2498         scale_x = (double)src_w / dst_w;
2499         scale_y = (double)src_h / dst_h;
2500
2501         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2502         pixman_f_transform_translate(&ft, NULL, 0, 0);
2503         pixman_transform_from_pixman_f_transform(&t, &ft);
2504         pixman_image_set_transform(src_img, &t);
2505
2506         pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2507                                                    0, 0, 0, 0, 0, 0, dst_w, dst_h);
2508
2509         pixman_image_unref(src_img);
2510         pixman_image_unref(dst_img);
2511
2512         return TBM_SURFACE_ERROR_NONE;
2513
2514 cant_convert:
2515         if (src_img)
2516                 pixman_image_unref(src_img);
2517
2518         return TBM_SURFACE_ERROR_INVALID_OPERATION;
2519 }
2520
2521 #define MAX_BOS         4       // This value is came from bos[4] in struct _tbm_surface
2522 #define KEY_LEN         5       // "_XXXX"
2523 #define KEYS_LEN        KEY_LEN * MAX_BOS
2524
2525 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2526 {
2527         char *keys, temp_key[KEY_LEN + 1];
2528         struct _tbm_surface *surf;
2529         int i, num_bos;
2530         tbm_bo bo;
2531
2532         _tbm_surface_mutex_lock();
2533
2534         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2535
2536         surf = (struct _tbm_surface *)surface;
2537
2538         num_bos = surf->num_bos;
2539         if (num_bos > MAX_BOS)
2540                 num_bos = MAX_BOS;
2541
2542         keys = calloc(KEYS_LEN + 1, sizeof(char));
2543         if (!keys) {
2544                 TBM_ERR("Failed to alloc memory");
2545                 _tbm_surface_mutex_unlock();
2546                 return NULL;
2547         }
2548
2549         for (i = 0; i < num_bos; i++) {
2550                 memset(temp_key, 0x00, KEY_LEN + 1);
2551                 bo = surf->bos[i];
2552                 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2553                 strncat(keys, temp_key, KEY_LEN + 1);
2554         }
2555
2556         _tbm_surface_mutex_unlock();
2557
2558         return keys;
2559 }
2560
2561 static void _tbm_surface_internal_put_keys(char *keys)
2562 {
2563         if (keys)
2564                 free(keys);
2565 }
2566
2567 void
2568 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2569 {
2570         TBM_RETURN_IF_FAIL(surface != NULL);
2571         TBM_RETURN_IF_FAIL(type != NULL);
2572
2573         tbm_surface_dump_buf_info *buf_info;
2574         struct list_head *next_link;
2575         tbm_surface_info_s info;
2576         tbm_bo_handle bo_handle;
2577         const char *postfix;
2578         const char *format = NULL;
2579         char *keys;
2580         int ret;
2581
2582         if (!g_dump_info)
2583                 return;
2584
2585         next_link = g_dump_info->link->next;
2586         TBM_RETURN_IF_FAIL(next_link != NULL);
2587
2588         if (next_link == &g_dump_info->surface_list) {
2589                 next_link = next_link->next;
2590                 TBM_RETURN_IF_FAIL(next_link != NULL);
2591         }
2592
2593         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2594         TBM_RETURN_IF_FAIL(buf_info != NULL);
2595
2596         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2597         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2598
2599         if (scale_factor > 0.0) {
2600                 const int bpp = 4;
2601
2602                 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
2603                         TBM_WRN("Dump with scale skip. unsupported format(%s)\n",
2604                                           _tbm_surface_internal_format_to_str(info.format));
2605                         tbm_surface_unmap(surface);
2606                         return;
2607                 }
2608
2609                 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2610
2611                 buf_info->info.width = info.width * scale_factor;
2612                 buf_info->info.height = info.height * scale_factor;
2613                 buf_info->info.format = info.format;
2614                 buf_info->info.bpp = _tbm_surface_internal_get_bpp(buf_info->info.format);
2615                 if (!buf_info->info.bpp) {
2616                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
2617                         tbm_surface_unmap(surface);
2618                         return;
2619                 }
2620                 buf_info->info.num_planes = 1;
2621                 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2622                 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2623
2624                 if (buf_info->info.size > buf_info->size) {
2625                         TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)\n",
2626                                         buf_info->info.size, buf_info->size);
2627                         tbm_surface_unmap(surface);
2628                         return;
2629                 }
2630         } else {
2631                 if (info.size > buf_info->size) {
2632                         TBM_WRN("Dump skip. surface over created buffer size(%u, %d)\n",
2633                                         info.size, buf_info->size);
2634                         tbm_surface_unmap(surface);
2635                         return;
2636                 }
2637
2638                 /* make the file information */
2639                 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2640         }
2641
2642         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888) {
2643                 postfix = dump_postfix[0];
2644                 format = _tbm_surface_internal_format_to_str(info.format);
2645         } else
2646                 postfix = dump_postfix[1];
2647
2648         keys = _tbm_surface_internal_get_keys(surface);
2649         if (!keys) {
2650                 TBM_ERR("fail to get keys");
2651                 tbm_surface_unmap(surface);
2652                 return;
2653         }
2654
2655         /* dump */
2656         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2657         if (!bo_handle.ptr) {
2658                 TBM_ERR("fail to map bo");
2659                 _tbm_surface_internal_put_keys(keys);
2660                 tbm_surface_unmap(surface);
2661                 return;
2662         }
2663         memset(bo_handle.ptr, 0x00, buf_info->size);
2664
2665         switch (info.format) {
2666         case TBM_FORMAT_ARGB8888:
2667         case TBM_FORMAT_XRGB8888:
2668                 snprintf(buf_info->name, sizeof(buf_info->name),
2669                                 "%10.3f_%03d%s_%p_%s-%s.%s",
2670                                  _tbm_surface_internal_get_time(),
2671                                  g_dump_info->count++, keys, surface, format, type, postfix);
2672
2673                 if (scale_factor > 0.0) {
2674                         ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2675                                                                                                          bo_handle.ptr,
2676                                                                                                          buf_info->info.format,
2677                                                                                                          info.planes[0].stride,
2678                                                                                                          info.width, info.height,
2679                                                                                                          buf_info->info.planes[0].stride,
2680                                                                                                          buf_info->info.width,
2681                                                                                                          buf_info->info.height);
2682                         if (ret != TBM_SURFACE_ERROR_NONE) {
2683                                 TBM_ERR("fail to scale buffer");
2684                                 tbm_bo_unmap(buf_info->bo);
2685                                 _tbm_surface_internal_put_keys(keys);
2686                                 tbm_surface_unmap(surface);
2687                                 return;
2688                         }
2689                 } else
2690                         memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2691                 break;
2692         case TBM_FORMAT_YVU420:
2693         case TBM_FORMAT_YUV420:
2694                 snprintf(buf_info->name, sizeof(buf_info->name),
2695                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2696                                  _tbm_surface_internal_get_time(),
2697                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2698                                 info.height, FOURCC_STR(info.format), postfix);
2699                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2700                 bo_handle.ptr += info.planes[0].stride * info.height;
2701                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2702                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2703                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2704                 break;
2705         case TBM_FORMAT_NV12:
2706         case TBM_FORMAT_NV21:
2707                 snprintf(buf_info->name, sizeof(buf_info->name),
2708                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2709                                  _tbm_surface_internal_get_time(),
2710                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2711                                 info.height, FOURCC_STR(info.format), postfix);
2712                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2713                 bo_handle.ptr += info.planes[0].stride * info.height;
2714                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2715                 break;
2716         case TBM_FORMAT_YUYV:
2717         case TBM_FORMAT_UYVY:
2718                 snprintf(buf_info->name, sizeof(buf_info->name),
2719                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2720                                  _tbm_surface_internal_get_time(),
2721                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2722                                 info.height, FOURCC_STR(info.format), postfix);
2723                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2724                 break;
2725         default:
2726                 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2727                 tbm_bo_unmap(buf_info->bo);
2728                 _tbm_surface_internal_put_keys(keys);
2729                 tbm_surface_unmap(surface);
2730                 return;
2731         }
2732
2733         tbm_bo_unmap(buf_info->bo);
2734
2735         _tbm_surface_internal_put_keys(keys);
2736
2737         tbm_surface_unmap(surface);
2738
2739         buf_info->dirty = 1;
2740         buf_info->dirty_shm = 0;
2741
2742         if (g_dump_info->count == 1000)
2743                 g_dump_info->count = 0;
2744
2745         g_dump_info->link = next_link;
2746
2747         TBM_INFO("Dump %s \n", buf_info->name);
2748 }
2749
2750 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2751                                                 const char *type)
2752 {
2753         TBM_RETURN_IF_FAIL(ptr != NULL);
2754         TBM_RETURN_IF_FAIL(w > 0);
2755         TBM_RETURN_IF_FAIL(h > 0);
2756         TBM_RETURN_IF_FAIL(stride > 0);
2757         TBM_RETURN_IF_FAIL(type != NULL);
2758
2759         tbm_surface_dump_buf_info *buf_info;
2760         struct list_head *next_link;
2761         tbm_bo_handle bo_handle;
2762         int ret, size, dw = 0, dh = 0, dstride = 0;
2763
2764         if (!g_dump_info)
2765                 return;
2766
2767         next_link = g_dump_info->link->next;
2768         TBM_RETURN_IF_FAIL(next_link != NULL);
2769
2770         if (next_link == &g_dump_info->surface_list) {
2771                 next_link = next_link->next;
2772                 TBM_RETURN_IF_FAIL(next_link != NULL);
2773         }
2774
2775         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2776         TBM_RETURN_IF_FAIL(buf_info != NULL);
2777
2778         if (scale_factor > 0.0) {
2779                 const int bpp = 4;
2780
2781                 dw = w * scale_factor;
2782                 dh = h * scale_factor;
2783                 dstride = dw * bpp;
2784                 size = dstride * dh;
2785         } else
2786                 size = stride * h;
2787
2788         if (size > buf_info->size) {
2789                 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2790                                 size, buf_info->size);
2791                 return;
2792         }
2793
2794         /* dump */
2795         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2796         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2797
2798         memset(bo_handle.ptr, 0x00, buf_info->size);
2799         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2800
2801         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2802                          _tbm_surface_internal_get_time(),
2803                          g_dump_info->count++, type, dump_postfix[0]);
2804         if (scale_factor > 0.0) {
2805                 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2806                                                                                                  TBM_FORMAT_ARGB8888, stride,
2807                                                                                                  w, h, dstride, dw, dh);
2808                 if (ret != TBM_SURFACE_ERROR_NONE) {
2809                         TBM_ERR("fail to scale buffer");
2810                         tbm_bo_unmap(buf_info->bo);
2811                         return;
2812                 }
2813                 buf_info->shm_stride = dstride;
2814                 buf_info->shm_h = dh;
2815         } else {
2816                 memcpy(bo_handle.ptr, ptr, size);
2817                 buf_info->shm_stride = stride;
2818                 buf_info->shm_h = h;
2819         }
2820
2821         tbm_bo_unmap(buf_info->bo);
2822
2823         buf_info->dirty = 0;
2824         buf_info->dirty_shm = 1;
2825
2826         if (g_dump_info->count == 1000)
2827                 g_dump_info->count = 0;
2828
2829         g_dump_info->link = next_link;
2830
2831         TBM_INFO("Dump %s \n", buf_info->name);
2832 }
2833
2834 int
2835 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2836 {
2837         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2838         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2839         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2840
2841         tbm_surface_info_s info;
2842         const char *postfix;
2843         int ret;
2844         char file[1024];
2845
2846         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2847         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2848
2849         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2850                 postfix = dump_postfix[0];
2851         else
2852                 postfix = dump_postfix[1];
2853
2854         if (strcmp(postfix, type)) {
2855                 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2856                 tbm_surface_unmap(surface);
2857                 return 0;
2858         }
2859
2860         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2861
2862         if (!access(file, 0)) {
2863                 TBM_ERR("can't capture  buffer, exist file %s", file);
2864                 tbm_surface_unmap(surface);
2865                 return 0;
2866         }
2867
2868         switch (info.format) {
2869         case TBM_FORMAT_ARGB8888:
2870                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2871                                                         info.width,
2872                                                         info.height,
2873                                                         info.planes[0].stride,
2874                                                         TBM_FORMAT_ARGB8888);
2875                 break;
2876         case TBM_FORMAT_XRGB8888:
2877                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2878                                                         info.width,
2879                                                         info.height,
2880                                                         info.planes[0].stride,
2881                                                         TBM_FORMAT_XRGB8888);
2882                 break;
2883         case TBM_FORMAT_YVU420:
2884         case TBM_FORMAT_YUV420:
2885                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2886                                 info.planes[0].stride * info.height,
2887                                 info.planes[1].ptr,
2888                                 info.planes[1].stride * (info.height >> 1),
2889                                 info.planes[2].ptr,
2890                                 info.planes[2].stride * (info.height >> 1));
2891                 break;
2892         case TBM_FORMAT_NV12:
2893         case TBM_FORMAT_NV21:
2894                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2895                                         info.planes[0].stride * info.height,
2896                                         info.planes[1].ptr,
2897                                         info.planes[1].stride * (info.height >> 1),
2898                                         NULL, 0);
2899                 break;
2900         case TBM_FORMAT_YUYV:
2901         case TBM_FORMAT_UYVY:
2902                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2903                                         info.planes[0].stride * info.height,
2904                                         NULL, 0, NULL, 0);
2905                 break;
2906         default:
2907                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2908                 tbm_surface_unmap(surface);
2909                 return 0;
2910         }
2911
2912         tbm_surface_unmap(surface);
2913
2914         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2915
2916         return 1;
2917 }
2918
2919 int
2920 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2921                                                 const char *path, const char *name, const char *type)
2922 {
2923         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2924         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2925         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2926         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2927         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2928         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2929
2930         char file[1024];
2931
2932         if (strcmp(dump_postfix[0], type)) {
2933                 TBM_ERR("Not supported type:%s'", type);
2934                 return 0;
2935         }
2936
2937         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2938
2939         if (!access(file, 0)) {
2940                 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2941                 return 0;
2942         }
2943
2944         _tbm_surface_internal_dump_file_png(file, ptr, w, h, stride, 0);
2945
2946         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2947
2948         return 1;
2949 }
2950
2951 int
2952 tbm_surface_internal_set_damage(tbm_surface_h surface, int x, int y, int width, int height)
2953 {
2954         struct _tbm_surface *surf;
2955
2956         _tbm_surface_mutex_lock();
2957         _tbm_set_last_result(TBM_ERROR_NONE);
2958
2959         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, 0);
2960         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, 0);
2961         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2962
2963         surf = (struct _tbm_surface *)surface;
2964
2965         surf->damage.x = x;
2966         surf->damage.y = y;
2967         surf->damage.width = width;
2968         surf->damage.height = height;
2969
2970         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2971                                                         surface, x, y, width, height);
2972
2973         _tbm_surface_mutex_unlock();
2974
2975         return 1;
2976 }
2977
2978 int
2979 tbm_surface_internal_get_damage(tbm_surface_h surface, int *x, int *y, int *width, int *height)
2980 {
2981         struct _tbm_surface *surf;
2982
2983         _tbm_surface_mutex_lock();
2984         _tbm_set_last_result(TBM_ERROR_NONE);
2985
2986         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2987
2988         surf = (struct _tbm_surface *)surface;
2989
2990         if (x) *x = surf->damage.x;
2991         if (y) *y = surf->damage.y;
2992         if (width) *width = surf->damage.width;
2993         if (height) *height = surf->damage.height;
2994
2995         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2996                                                         surface, surf->damage.x, surf->damage.y, surf->damage.width, surf->damage.height);
2997
2998         _tbm_surface_mutex_unlock();
2999
3000         return 1;
3001 }
3002
3003 int
3004 tbm_surface_internal_add_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
3005 {
3006         struct _tbm_surface *surf;
3007         tbm_surface_destroy_func_info *func_info = NULL;
3008
3009         _tbm_surface_mutex_lock();
3010         _tbm_set_last_result(TBM_ERROR_NONE);
3011
3012         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
3013         TBM_SURFACE_RETURN_VAL_IF_FAIL(func != NULL, 0);
3014
3015         surf = (struct _tbm_surface *)surface;
3016         LIST_FOR_EACH_ENTRY(func_info, &surf->destroy_funcs, item_link) {
3017                 if (func_info->destroy_func == func && func_info->user_data == user_data) {
3018                         TBM_ERR("can't add twice");
3019                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
3020                         _tbm_surface_mutex_unlock();
3021                         return 0;
3022                 }
3023         }
3024
3025         func_info = calloc(1, sizeof(tbm_surface_destroy_func_info));
3026         if (func_info == NULL) {
3027                 TBM_ERR("alloc failed");
3028                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
3029                 _tbm_surface_mutex_unlock();
3030                 return 0;
3031         }
3032
3033         func_info->destroy_func = func;
3034         func_info->user_data = user_data;
3035
3036         LIST_ADDTAIL(&func_info->item_link, &surf->destroy_funcs);
3037
3038         _tbm_surface_mutex_unlock();
3039
3040         return 1;
3041 }
3042
3043 void
3044 tbm_surface_internal_remove_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
3045 {
3046         struct _tbm_surface *surf;
3047         tbm_surface_destroy_func_info *func_info = NULL, *next = NULL;
3048
3049         _tbm_surface_mutex_lock();
3050         _tbm_set_last_result(TBM_ERROR_NONE);
3051
3052         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
3053         TBM_SURFACE_RETURN_IF_FAIL(func != NULL);
3054
3055         surf = (struct _tbm_surface *)surface;
3056         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &surf->destroy_funcs, item_link) {
3057                 if (func_info->destroy_func != func || func_info->user_data != user_data)
3058                         continue;
3059
3060                 LIST_DEL(&func_info->item_link);
3061                 free(func_info);
3062
3063                 _tbm_surface_mutex_unlock();
3064
3065                 return;
3066         }
3067
3068         _tbm_surface_mutex_unlock();
3069 }
3070
3071 tbm_surface_buffer_data *
3072 tbm_surface_internal_export(tbm_surface_h surface, tbm_error_e *error)
3073 {
3074         tbm_surface_buffer_data *buffer_data = NULL;
3075         struct _tbm_surface *surf;
3076         struct _tbm_bufmgr *bufmgr;
3077
3078         _tbm_surface_mutex_lock();
3079
3080         surf = (struct _tbm_surface *)surface;
3081         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL, *error, TBM_ERROR_INVALID_PARAMETER);
3082
3083         bufmgr = surf->bufmgr;
3084         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr != NULL, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
3085
3086         // this function supports when it comes to be use_hal.
3087         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr->use_hal_tbm, NULL, *error, TBM_ERROR_NOT_SUPPORTED);
3088
3089         // export a surface
3090         buffer_data = (tbm_surface_buffer_data *)hal_tbm_surface_export((hal_tbm_surface *)surf->hal_surface,
3091                                                                                                                                         (hal_tbm_error *)error);
3092         TBM_SURFACE_RETURN_VAL_ERR_IF_FAIL(buffer_data != NULL, NULL, *error);
3093
3094         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) buffer_data(%p)", surface, buffer_data);
3095
3096         if (error)
3097                 *error = TBM_ERROR_NONE;
3098
3099         _tbm_set_last_result(TBM_ERROR_NONE);
3100         _tbm_surface_mutex_unlock();
3101
3102         return buffer_data;
3103 }
3104
3105 tbm_surface_h
3106 tbm_surface_internal_import(tbm_surface_info_s *surface_info, tbm_surface_buffer_data *buffer_data, tbm_error_e *error)
3107 {
3108         struct _tbm_surface *surf;
3109         struct _tbm_bufmgr *bufmgr;
3110
3111         _tbm_surface_mutex_lock();
3112
3113         bufmgr = g_surface_bufmgr;
3114         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr != NULL, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
3115
3116         // this function supports when it comes to be use_hal.
3117         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr->use_hal_tbm, NULL, *error, TBM_ERROR_NOT_SUPPORTED);
3118
3119         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info != NULL, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
3120         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info->width > 0, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
3121         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info->height > 0, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
3122         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(buffer_data != NULL, NULL, *error, TBM_ERROR_INVALID_PARAMETER);
3123
3124         // import a surface
3125         surf = _tbm_surface_internal_hal_tbm_import_surface(bufmgr,
3126                                                                                                         (int)surface_info->width,
3127                                                                                                         (int)surface_info->height,
3128                                                                                                         (int)surface_info->format,
3129                                                                                                         buffer_data,
3130                                                                                                         error);
3131         TBM_SURFACE_RETURN_VAL_ERR_IF_FAIL(surf != NULL, NULL, *error);
3132
3133         LIST_INITHEAD(&surf->user_data_list);
3134         LIST_INITHEAD(&surf->debug_data_list);
3135         LIST_INITHEAD(&surf->destroy_funcs);
3136
3137         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
3138
3139         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)", surf);
3140
3141         if (error)
3142                 *error = TBM_ERROR_NONE;
3143
3144         _tbm_set_last_result(TBM_ERROR_NONE);
3145         _tbm_surface_mutex_unlock();
3146
3147         return (tbm_surface_h)surf;
3148 }
3149
3150 /*LCOV_EXCL_STOP*/