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