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