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