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