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