tbm_surface_internal: make an internal function for creating a surface
[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
1143         _tbm_surface_mutex_unlock();
1144 }
1145
1146 void
1147 tbm_surface_internal_ref(tbm_surface_h surface)
1148 {
1149         _tbm_surface_mutex_lock();
1150         _tbm_set_last_result(TBM_ERROR_NONE);
1151
1152         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1153
1154         surface->refcnt++;
1155
1156         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1157
1158         _tbm_surface_mutex_unlock();
1159 }
1160
1161 void
1162 tbm_surface_internal_unref(tbm_surface_h surface)
1163 {
1164         _tbm_surface_mutex_lock();
1165         _tbm_set_last_result(TBM_ERROR_NONE);
1166
1167         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1168
1169         surface->refcnt--;
1170
1171         if (surface->refcnt > 0) {
1172                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1173                 _tbm_surface_mutex_unlock();
1174                 return;
1175         }
1176
1177         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1178
1179         if (surface->refcnt == 0)
1180                 _tbm_surface_internal_destroy(surface);
1181
1182         _tbm_surface_mutex_unlock();
1183 }
1184
1185 int
1186 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
1187 {
1188         struct _tbm_surface *surf;
1189         int num;
1190
1191         _tbm_surface_mutex_lock();
1192         _tbm_set_last_result(TBM_ERROR_NONE);
1193
1194         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1195
1196         surf = (struct _tbm_surface *)surface;
1197         num = surf->num_bos;
1198
1199         if (!num)
1200                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1201
1202         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) num_bos(%d)\n", surface, num);
1203
1204         _tbm_surface_mutex_unlock();
1205
1206         return num;
1207 }
1208
1209 tbm_bo
1210 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
1211 {
1212         struct _tbm_surface *surf;
1213         tbm_bo bo;
1214
1215         _tbm_surface_mutex_lock();
1216         _tbm_set_last_result(TBM_ERROR_NONE);
1217
1218         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
1219         TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
1220
1221         surf = (struct _tbm_surface *)surface;
1222         bo = surf->bos[bo_idx];
1223
1224         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
1225
1226         _tbm_surface_mutex_unlock();
1227
1228         return bo;
1229 }
1230
1231 unsigned int
1232 tbm_surface_internal_get_size(tbm_surface_h surface)
1233 {
1234         struct _tbm_surface *surf;
1235         unsigned int size;
1236
1237         _tbm_surface_mutex_lock();
1238         _tbm_set_last_result(TBM_ERROR_NONE);
1239
1240         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1241
1242         surf = (struct _tbm_surface *)surface;
1243         size = surf->info.size;
1244
1245         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) size(%u)\n", surface, size);
1246
1247         _tbm_surface_mutex_unlock();
1248
1249         return size;
1250 }
1251
1252 int
1253 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1254                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
1255 {
1256         struct _tbm_surface *surf;
1257
1258         _tbm_surface_mutex_lock();
1259         _tbm_set_last_result(TBM_ERROR_NONE);
1260
1261         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1262         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1263
1264         surf = (struct _tbm_surface *)surface;
1265
1266         if (plane_idx >= surf->info.num_planes) {
1267                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1268                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1269                 _tbm_surface_mutex_unlock();
1270                 return 0;
1271         }
1272
1273         if (size)
1274                 *size = surf->info.planes[plane_idx].size;
1275
1276         if (offset)
1277                 *offset = surf->info.planes[plane_idx].offset;
1278
1279         if (pitch)
1280                 *pitch = surf->info.planes[plane_idx].stride;
1281
1282         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1283                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1284                                 surf->info.planes[plane_idx].stride);
1285
1286         _tbm_surface_mutex_unlock();
1287
1288         return 1;
1289 }
1290
1291 int
1292 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1293                               tbm_surface_info_s *info, int map)
1294 {
1295         struct _tbm_surface *surf;
1296         tbm_bo_handle bo_handles[4];
1297         int num_bos = 0;
1298         tbm_bo bos[4];
1299         int planes_bo_idx[TBM_SURF_PLANE_MAX];
1300         int i, j;
1301
1302         _tbm_surface_mutex_lock();
1303         _tbm_set_last_result(TBM_ERROR_NONE);
1304
1305         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1306
1307         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1308
1309         surf = (struct _tbm_surface *)surface;
1310
1311         memset(info, 0x00, sizeof(tbm_surface_info_s));
1312         info->width = surf->info.width;
1313         info->height = surf->info.height;
1314         info->format = surf->info.format;
1315         info->bpp = surf->info.bpp;
1316         info->size = surf->info.size;
1317         info->num_planes = surf->info.num_planes;
1318
1319         for (i = 0; i < surf->info.num_planes; i++) {
1320                 info->planes[i].size = surf->info.planes[i].size;
1321                 info->planes[i].offset = surf->info.planes[i].offset;
1322                 info->planes[i].stride = surf->info.planes[i].stride;
1323                 planes_bo_idx[i] = surf->planes_bo_idx[i];
1324         }
1325
1326         for (i = 0; i < surf->num_bos; i++)
1327                 bos[i] = surf->bos[i];
1328
1329         num_bos = surf->num_bos;
1330
1331         if (map == 1) {
1332                 _tbm_surface_mutex_unlock();
1333                 for (i = 0; i < num_bos; i++) {
1334                         bo_handles[i] = tbm_bo_map(bos[i], TBM_DEVICE_CPU, opt);
1335                         if (bo_handles[i].ptr == NULL) {
1336                                 for (j = 0; j < i; j++)
1337                                         tbm_bo_unmap(bos[j]);
1338
1339                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1340                                 return 0;
1341                         }
1342                 }
1343                 _tbm_surface_mutex_lock();
1344         } else {
1345                 for (i = 0; i < num_bos; i++) {
1346                         bo_handles[i] = tbm_bo_get_handle(bos[i], TBM_DEVICE_CPU);
1347                         if (bo_handles[i].ptr == NULL) {
1348                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1349                                 _tbm_surface_mutex_unlock();
1350                                 return 0;
1351                         }
1352                 }
1353         }
1354
1355         for (i = 0; i < info->num_planes; i++) {
1356                 if (bo_handles[planes_bo_idx[i]].ptr)
1357                         info->planes[i].ptr = bo_handles[planes_bo_idx[i]].ptr + info->planes[i].offset;
1358         }
1359
1360         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1361
1362         _tbm_surface_mutex_unlock();
1363
1364         return 1;
1365 }
1366
1367 void
1368 tbm_surface_internal_unmap(tbm_surface_h surface)
1369 {
1370         struct _tbm_surface *surf;
1371         int i;
1372
1373         _tbm_surface_mutex_lock();
1374         _tbm_set_last_result(TBM_ERROR_NONE);
1375
1376         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1377
1378         surf = (struct _tbm_surface *)surface;
1379
1380         for (i = 0; i < surf->num_bos; i++)
1381                 tbm_bo_unmap(surf->bos[i]);
1382
1383         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)\n", surface);
1384
1385         _tbm_surface_mutex_unlock();
1386 }
1387
1388 unsigned int
1389 tbm_surface_internal_get_width(tbm_surface_h surface)
1390 {
1391         struct _tbm_surface *surf;
1392         unsigned int width;
1393
1394         _tbm_surface_mutex_lock();
1395         _tbm_set_last_result(TBM_ERROR_NONE);
1396
1397         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1398
1399         surf = (struct _tbm_surface *)surface;
1400         width = surf->info.width;
1401
1402         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u)\n", surface, width);
1403
1404         _tbm_surface_mutex_unlock();
1405
1406         return width;
1407 }
1408
1409 unsigned int
1410 tbm_surface_internal_get_height(tbm_surface_h surface)
1411 {
1412         struct _tbm_surface *surf;
1413         unsigned int height;
1414
1415         _tbm_surface_mutex_lock();
1416         _tbm_set_last_result(TBM_ERROR_NONE);
1417
1418         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1419
1420         surf = (struct _tbm_surface *)surface;
1421         height = surf->info.height;
1422
1423         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) height(%u)\n", surface, height);
1424
1425         _tbm_surface_mutex_unlock();
1426
1427         return height;
1428
1429 }
1430
1431 tbm_format
1432 tbm_surface_internal_get_format(tbm_surface_h surface)
1433 {
1434         struct _tbm_surface *surf;
1435         tbm_format format;
1436
1437         _tbm_surface_mutex_lock();
1438         _tbm_set_last_result(TBM_ERROR_NONE);
1439
1440         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1441
1442         surf = (struct _tbm_surface *)surface;
1443         format = surf->info.format;
1444
1445         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1446
1447         _tbm_surface_mutex_unlock();
1448
1449         return format;
1450 }
1451
1452 int
1453 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1454 {
1455         struct _tbm_surface *surf;
1456         int bo_idx;
1457
1458         _tbm_surface_mutex_lock();
1459         _tbm_set_last_result(TBM_ERROR_NONE);
1460
1461         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1462         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1463
1464         surf = (struct _tbm_surface *)surface;
1465         bo_idx = surf->planes_bo_idx[plane_idx];
1466
1467         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1468
1469         _tbm_surface_mutex_unlock();
1470
1471         return bo_idx;
1472 }
1473
1474 int
1475 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1476                                    tbm_data_free data_free_func)
1477 {
1478         tbm_user_data *data;
1479
1480         _tbm_surface_mutex_lock();
1481         _tbm_set_last_result(TBM_ERROR_NONE);
1482
1483         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1484
1485         /* check if the data according to the key exist if so, return false. */
1486         data = user_data_lookup(&surface->user_data_list, key);
1487         if (data) {
1488                 TBM_TRACE_SURFACE_INTERNAL("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1489                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1490                 _tbm_surface_mutex_unlock();
1491                 return 0;
1492         }
1493
1494         data = user_data_create(key, data_free_func);
1495         if (!data) {
1496                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1497                 _tbm_surface_mutex_unlock();
1498                 return 0;
1499         }
1500
1501         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1502
1503         LIST_ADD(&data->item_link, &surface->user_data_list);
1504
1505         _tbm_surface_mutex_unlock();
1506
1507         return 1;
1508 }
1509
1510 int
1511 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1512                                    void *data)
1513 {
1514         tbm_user_data *old_data;
1515
1516         _tbm_surface_mutex_lock();
1517         _tbm_set_last_result(TBM_ERROR_NONE);
1518
1519         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1520
1521         old_data = user_data_lookup(&surface->user_data_list, key);
1522         if (!old_data) {
1523                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1524                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1525                 _tbm_surface_mutex_unlock();
1526                 return 0;
1527         }
1528
1529         if (old_data->data && old_data->free_func)
1530                 old_data->free_func(old_data->data);
1531
1532         old_data->data = data;
1533
1534         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1535
1536         _tbm_surface_mutex_unlock();
1537
1538         return 1;
1539 }
1540
1541 int
1542 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1543                                    void **data)
1544 {
1545         tbm_user_data *old_data;
1546
1547         _tbm_surface_mutex_lock();
1548         _tbm_set_last_result(TBM_ERROR_NONE);
1549
1550         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1551
1552         if (!data) {
1553                 TBM_ERR("error: tbm_surface(%p) key(%lu)\n", surface, key);
1554                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1555                 _tbm_surface_mutex_unlock();
1556                 return 0;
1557         }
1558         *data = NULL;
1559
1560         old_data = user_data_lookup(&surface->user_data_list, key);
1561         if (!old_data) {
1562                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1563                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1564                 _tbm_surface_mutex_unlock();
1565                 return 0;
1566         }
1567
1568         *data = old_data->data;
1569
1570         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1571
1572         _tbm_surface_mutex_unlock();
1573
1574         return 1;
1575 }
1576
1577 int
1578 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1579                                       unsigned long key)
1580 {
1581         tbm_user_data *old_data = (void *)0;
1582
1583         _tbm_surface_mutex_lock();
1584         _tbm_set_last_result(TBM_ERROR_NONE);
1585
1586         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1587
1588         old_data = user_data_lookup(&surface->user_data_list, key);
1589         if (!old_data) {
1590                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1591                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1592                 _tbm_surface_mutex_unlock();
1593                 return 0;
1594         }
1595
1596         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1597
1598         user_data_delete(old_data);
1599
1600         _tbm_surface_mutex_unlock();
1601
1602         return 1;
1603 }
1604
1605 /* LCOV_EXCL_START */
1606 unsigned int
1607 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1608 {
1609         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1610
1611         return surface->debug_pid;
1612 }
1613
1614 void
1615 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1616 {
1617         _tbm_surface_mutex_lock();
1618         _tbm_set_last_result(TBM_ERROR_NONE);
1619
1620         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1621
1622         surface->debug_pid = pid;
1623
1624         _tbm_surface_mutex_unlock();
1625 }
1626
1627 static tbm_surface_debug_data *
1628 _tbm_surface_internal_debug_data_create(char *key, char *value)
1629 {
1630         tbm_surface_debug_data *debug_data = NULL;
1631
1632         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1633         if (!debug_data) {
1634                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1635                 TBM_ERR("fail to allocate the debug_data.");
1636                 return NULL;
1637         }
1638
1639         if (key) debug_data->key = strdup(key);
1640         if (value) debug_data->value = strdup(value);
1641
1642         return debug_data;
1643 }
1644
1645 static void
1646 _tbm_surface_internal_debug_data_value_update(tbm_surface_debug_data *debug_data, char *value)
1647 {
1648         if (!debug_data->value && !value)
1649                 return;
1650
1651         if (debug_data->value && value && !strncmp(debug_data->value, value, strlen(debug_data->value)))
1652                 return;
1653
1654         if (debug_data->value)
1655                 free(debug_data->value);
1656
1657         if (value)
1658                 debug_data->value = strdup(value);
1659         else
1660                 debug_data->value = NULL;
1661 }
1662
1663 static tbm_surface_debug_data *
1664 _tbm_surface_internal_debug_data_find(struct list_head *list, char *key)
1665 {
1666         tbm_surface_debug_data *debug_data = NULL;
1667
1668         if (LIST_IS_EMPTY(list))
1669                 return NULL;
1670
1671         LIST_FOR_EACH_ENTRY(debug_data, list, item_link) {
1672                 if (!strncmp(debug_data->key, key, strlen(debug_data->key)))
1673                         return debug_data;
1674         }
1675
1676         return NULL;
1677 }
1678
1679 int
1680 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1681 {
1682         tbm_surface_debug_data *debug_data = NULL;
1683         tbm_bufmgr bufmgr = NULL;
1684
1685         _tbm_surface_mutex_lock();
1686         _tbm_set_last_result(TBM_ERROR_NONE);
1687
1688         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1689         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1690
1691         bufmgr = surface->bufmgr;
1692
1693         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1694
1695         debug_data = _tbm_surface_internal_debug_data_find(&surface->debug_data_list, key);
1696         if (debug_data) {
1697                 _tbm_surface_internal_debug_data_value_update(debug_data, value);
1698         } else {
1699                 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1700                 if (!debug_data) {
1701                         TBM_ERR("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1702                         _tbm_surface_mutex_unlock();
1703                         return 0;
1704                 }
1705
1706                 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1707         }
1708
1709         /* add new debug key to list */
1710         debug_data = _tbm_surface_internal_debug_data_find(&bufmgr->debug_key_list, key);
1711         if (!debug_data) {
1712                 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1713                 if (debug_data)
1714                         LIST_ADDTAIL(&debug_data->item_link, &bufmgr->debug_key_list);
1715         }
1716
1717         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1718
1719         _tbm_surface_mutex_unlock();
1720
1721         return 1;
1722 }
1723
1724 char *
1725 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1726 {
1727         tbm_surface_debug_data *old_data = NULL;
1728
1729         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1730
1731         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1732                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1733                         if (!strcmp(old_data->key, key))
1734                                 return old_data->value;
1735                 }
1736         }
1737
1738         return NULL;
1739 }
1740
1741 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1742 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1743
1744 struct _tbm_surface_dump_buf_info {
1745         int index;
1746         tbm_bo bo;
1747         int size;
1748         int dirty;
1749         int dirty_shm;
1750         int shm_stride;
1751         int shm_h;
1752         char name[1024];
1753
1754         tbm_surface_info_s info;
1755
1756         struct list_head link;
1757 };
1758
1759 struct _tbm_surface_dump_info {
1760         char *path;  // copy???
1761         int dump_max;
1762         int count;
1763         struct list_head *link;
1764         struct list_head surface_list; /* link of surface */
1765 };
1766
1767 static tbm_surface_dump_info *g_dump_info = NULL;
1768 static const char *dump_postfix[2] = {"png", "yuv"};
1769 static double scale_factor;
1770
1771 static void
1772 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1773                                 void *data2, int size2, void *data3, int size3)
1774 {
1775         FILE *fp;
1776         unsigned int *blocks;
1777
1778         if (_tbm_surface_check_file_is_symbolic_link(file))
1779                 TBM_ERR("%s is symbolic link\n", file);
1780
1781         fp = fopen(file, "w+");
1782         TBM_RETURN_IF_FAIL(fp != NULL);
1783
1784         blocks = (unsigned int *)data1;
1785         fwrite(blocks, 1, size1, fp);
1786
1787         if (size2 > 0) {
1788                 blocks = (unsigned int *)data2;
1789                 fwrite(blocks, 1, size2, fp);
1790         }
1791
1792         if (size3 > 0) {
1793                 blocks = (unsigned int *)data3;
1794                 fwrite(blocks, 1, size3, fp);
1795         }
1796
1797         fclose(fp);
1798 }
1799
1800 static void
1801 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height, int stride, int format)
1802 {
1803         unsigned int *blocks = (unsigned int *)data;
1804         FILE *fp;
1805         int pixel_size;
1806         png_bytep *row_pointers;
1807         int depth = 8, y;
1808
1809         if (_tbm_surface_check_file_is_symbolic_link(file))
1810                 TBM_ERR("%s is symbolic link\n", file);
1811
1812         fp = fopen(file, "wb");
1813         TBM_RETURN_IF_FAIL(fp != NULL);
1814
1815         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1816                                                         NULL, NULL, NULL);
1817         if (!pPngStruct) {
1818                 TBM_ERR("fail to create a png write structure.\n");
1819                 fclose(fp);
1820                 return;
1821         }
1822
1823         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1824         if (!pPngInfo) {
1825                 TBM_ERR("fail to create a png info structure.\n");
1826                 png_destroy_write_struct(&pPngStruct, NULL);
1827                 fclose(fp);
1828                 return;
1829         }
1830
1831         if (setjmp(png_jmpbuf(pPngStruct))) {
1832                 /* if png has problem of writing the file, we get here */
1833                 TBM_ERR("fail to write png file.\n");
1834                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1835                 fclose(fp);
1836                 return;
1837         }
1838
1839         png_init_io(pPngStruct, fp);
1840         if (format == TBM_FORMAT_XRGB8888) {
1841                 pixel_size = 3;
1842                 png_set_IHDR(pPngStruct,
1843                                 pPngInfo,
1844                                 width,
1845                                 height,
1846                                 depth,
1847                                 PNG_COLOR_TYPE_RGB,
1848                                 PNG_INTERLACE_NONE,
1849                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1850         } else {
1851                 pixel_size = 4;
1852                 png_set_IHDR(pPngStruct,
1853                                 pPngInfo,
1854                                 width,
1855                                 height,
1856                                 depth,
1857                                 PNG_COLOR_TYPE_RGBA,
1858                                 PNG_INTERLACE_NONE,
1859                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1860         }
1861
1862         png_set_bgr(pPngStruct);
1863         png_write_info(pPngStruct, pPngInfo);
1864
1865         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1866         if (!row_pointers) {
1867                 TBM_ERR("fail to allocate the png row_pointers.\n");
1868                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1869                 fclose(fp);
1870                 return;
1871         }
1872
1873         for (y = 0; y < height; ++y) {
1874                 png_bytep row;
1875                 int x = 0;
1876
1877                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1878                 if (!row) {
1879                         TBM_ERR("fail to allocate the png row.\n");
1880                         for (x = 0; x < y; x++)
1881                                 png_free(pPngStruct, row_pointers[x]);
1882                         png_free(pPngStruct, row_pointers);
1883                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1884                         fclose(fp);
1885                         return;
1886                 }
1887                 row_pointers[y] = (png_bytep)row;
1888
1889                 for (x = 0; x < width; ++x) {
1890                         unsigned int curBlock = blocks[(y * (stride >> 2)) + x];
1891
1892                         if (pixel_size == 3) { // XRGB8888
1893                                 row[x * pixel_size] = (curBlock & 0xFF);
1894                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1895                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1896                         } else { // ARGB8888
1897                                 row[x * pixel_size] = (curBlock & 0xFF);
1898                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1899                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1900                                 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1901                         }
1902                 }
1903         }
1904
1905         png_write_image(pPngStruct, row_pointers);
1906         png_write_end(pPngStruct, pPngInfo);
1907
1908         for (y = 0; y < height; y++)
1909                 png_free(pPngStruct, row_pointers[y]);
1910         png_free(pPngStruct, row_pointers);
1911
1912         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1913
1914         fclose(fp);
1915 }
1916
1917 void
1918 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1919 {
1920         TBM_RETURN_IF_FAIL(path != NULL);
1921         TBM_RETURN_IF_FAIL(w > 0);
1922         TBM_RETURN_IF_FAIL(h > 0);
1923         TBM_RETURN_IF_FAIL(count > 0);
1924
1925         tbm_surface_dump_buf_info *buf_info = NULL;
1926         tbm_surface_h tbm_surface;
1927         tbm_surface_info_s info;
1928         int buffer_size, i;
1929
1930         /* check running */
1931         if (g_dump_info) {
1932                 TBM_WRN("waring already running the tbm_surface_internal_dump.\n");
1933                 return;
1934         }
1935
1936         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1937         TBM_RETURN_IF_FAIL(g_dump_info);
1938
1939         LIST_INITHEAD(&g_dump_info->surface_list);
1940         g_dump_info->count = 0;
1941         g_dump_info->dump_max = count;
1942
1943         /* get buffer size */
1944         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1945         if (tbm_surface == NULL) {
1946                 TBM_ERR("tbm_surface_create fail\n");
1947                 free(g_dump_info);
1948                 g_dump_info = NULL;
1949                 return;
1950         }
1951
1952         if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
1953                 TBM_ERR("tbm_surface_get_info fail\n");
1954                 tbm_surface_destroy(tbm_surface);
1955                 free(g_dump_info);
1956                 g_dump_info = NULL;
1957                 return;
1958         }
1959         buffer_size = info.size;
1960         tbm_surface_destroy(tbm_surface);
1961
1962         /* create dump lists */
1963         for (i = 0; i < count; i++) {
1964                 tbm_bo bo = NULL;
1965
1966                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1967                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1968
1969                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1970                 if (bo == NULL) {
1971                         TBM_ERR("fail to allocate the tbm_bo[%d]\n", i);
1972                         free(buf_info);
1973                         goto fail;
1974                 }
1975
1976                 buf_info->index = i;
1977                 buf_info->bo = bo;
1978                 buf_info->size = buffer_size;
1979
1980                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1981         }
1982
1983         g_dump_info->path = path;
1984         g_dump_info->link = &g_dump_info->surface_list;
1985
1986         scale_factor = 0.0;
1987
1988         TBM_INFO("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1989
1990         return;
1991
1992 fail:
1993         /* free resources */
1994         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1995                 tbm_surface_dump_buf_info *tmp;
1996
1997                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1998                         tbm_bo_unref(buf_info->bo);
1999                         LIST_DEL(&buf_info->link);
2000                         free(buf_info);
2001                 }
2002         }
2003
2004         TBM_ERR("Dump Start fail.. path:%s\n", g_dump_info->path);
2005
2006         free(g_dump_info);
2007         g_dump_info = NULL;
2008
2009         return;
2010 }
2011
2012 void
2013 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
2014 {
2015         if (scale > 0.0) {
2016                 w *= scale;
2017                 h *= scale;
2018         }
2019
2020         tbm_surface_internal_dump_start(path, w, h, count);
2021         scale_factor = scale;
2022 }
2023
2024 void
2025 tbm_surface_internal_dump_end(void)
2026 {
2027         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
2028         tbm_bo_handle bo_handle;
2029
2030         if (!g_dump_info)
2031                 return;
2032
2033         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2034                 free(g_dump_info);
2035                 g_dump_info = NULL;
2036                 return;
2037         }
2038
2039         /* make files */
2040         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2041                 char file[2048];
2042
2043                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
2044                 if (bo_handle.ptr == NULL) {
2045                         tbm_bo_unref(buf_info->bo);
2046                         LIST_DEL(&buf_info->link);
2047                         free(buf_info);
2048                         continue;
2049                 }
2050
2051                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
2052                 TBM_INFO("Dump File.. %s generated.\n", file);
2053
2054                 if (buf_info->dirty) {
2055                         void *ptr1 = NULL, *ptr2 = NULL;
2056
2057                         switch (buf_info->info.format) {
2058                         case TBM_FORMAT_ARGB8888:
2059                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2060                                                         buf_info->info.planes[0].stride >> 2,
2061                                                         buf_info->info.height,
2062                                                         buf_info->info.planes[0].stride,
2063                                                         TBM_FORMAT_ARGB8888);
2064                                 break;
2065                         case TBM_FORMAT_XRGB8888:
2066                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2067                                                         buf_info->info.planes[0].stride >> 2,
2068                                                         buf_info->info.height,
2069                                                         buf_info->info.planes[0].stride,
2070                                                         TBM_FORMAT_XRGB8888);
2071                                 break;
2072                         case TBM_FORMAT_YVU420:
2073                         case TBM_FORMAT_YUV420:
2074                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2075                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
2076                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2077                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2078                                                         ptr1,
2079                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2080                                                         ptr2,
2081                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
2082                                 break;
2083                         case TBM_FORMAT_NV12:
2084                         case TBM_FORMAT_NV21:
2085                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2086                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2087                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2088                                                         ptr1,
2089                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2090                                                         NULL, 0);
2091                                 break;
2092                         case TBM_FORMAT_YUYV:
2093                         case TBM_FORMAT_UYVY:
2094                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2095                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2096                                                         NULL, 0, NULL, 0);
2097                                 break;
2098                         default:
2099                                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
2100                                 break;
2101                         }
2102                 } else if (buf_info->dirty_shm)
2103                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2104                                                         buf_info->shm_stride >> 2,
2105                                                         buf_info->shm_h,
2106                                                         buf_info->shm_stride, 0);
2107
2108                 tbm_bo_unmap(buf_info->bo);
2109                 tbm_bo_unref(buf_info->bo);
2110                 LIST_DEL(&buf_info->link);
2111                 free(buf_info);
2112         }
2113
2114         free(g_dump_info);
2115         g_dump_info = NULL;
2116
2117         TBM_INFO("Dump End..\n");
2118 }
2119
2120 static pixman_format_code_t
2121 _tbm_surface_internal_pixman_format_get(tbm_format format)
2122 {
2123         switch (format) {
2124         case TBM_FORMAT_ARGB8888:
2125                 return PIXMAN_a8r8g8b8;
2126         case TBM_FORMAT_XRGB8888:
2127                 return PIXMAN_x8r8g8b8;
2128         default:
2129                 return 0;
2130         }
2131
2132         return 0;
2133 }
2134
2135 /**
2136  * This function supports only if a buffer has below formats.
2137  * - TBM_FORMAT_ARGB8888
2138  * - TBM_FORMAT_XRGB8888
2139  */
2140 static tbm_surface_error_e
2141 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
2142                                                                    int format, int src_stride, int src_w, int src_h,
2143                                                                    int dst_stride, int dst_w, int dst_h)
2144 {
2145         pixman_image_t *src_img = NULL, *dst_img = NULL;
2146         pixman_format_code_t pixman_format;
2147         pixman_transform_t t;
2148         struct pixman_f_transform ft;
2149         double scale_x, scale_y;
2150
2151         TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2152         TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2153
2154         pixman_format = _tbm_surface_internal_pixman_format_get(format);
2155         TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2156
2157         /* src */
2158         src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2159                                                                            (uint32_t*)src_ptr, src_stride);
2160         TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2161
2162         /* dst */
2163         dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2164                                                                            (uint32_t*)dst_ptr, dst_stride);
2165         TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2166
2167         pixman_f_transform_init_identity(&ft);
2168
2169         scale_x = (double)src_w / dst_w;
2170         scale_y = (double)src_h / dst_h;
2171
2172         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2173         pixman_f_transform_translate(&ft, NULL, 0, 0);
2174         pixman_transform_from_pixman_f_transform(&t, &ft);
2175         pixman_image_set_transform(src_img, &t);
2176
2177         pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2178                                                    0, 0, 0, 0, 0, 0, dst_w, dst_h);
2179
2180         pixman_image_unref(src_img);
2181         pixman_image_unref(dst_img);
2182
2183         return TBM_SURFACE_ERROR_NONE;
2184
2185 cant_convert:
2186         if (src_img)
2187                 pixman_image_unref(src_img);
2188
2189         return TBM_SURFACE_ERROR_INVALID_OPERATION;
2190 }
2191
2192 #define MAX_BOS         4       // This value is came from bos[4] in struct _tbm_surface
2193 #define KEY_LEN         5       // "_XXXX"
2194 #define KEYS_LEN        KEY_LEN * MAX_BOS
2195
2196 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2197 {
2198         char *keys, temp_key[KEY_LEN + 1];
2199         struct _tbm_surface *surf;
2200         int i, num_bos;
2201         tbm_bo bo;
2202
2203         _tbm_surface_mutex_lock();
2204
2205         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2206
2207         surf = (struct _tbm_surface *)surface;
2208
2209         num_bos = surf->num_bos;
2210         if (num_bos > MAX_BOS)
2211                 num_bos = MAX_BOS;
2212
2213         keys = calloc(KEYS_LEN + 1, sizeof(char));
2214         if (!keys) {
2215                 TBM_ERR("Failed to alloc memory");
2216                 _tbm_surface_mutex_unlock();
2217                 return NULL;
2218         }
2219
2220         for (i = 0; i < num_bos; i++) {
2221                 memset(temp_key, 0x00, KEY_LEN + 1);
2222                 bo = surf->bos[i];
2223                 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2224                 strncat(keys, temp_key, KEY_LEN + 1);
2225         }
2226
2227         _tbm_surface_mutex_unlock();
2228
2229         return keys;
2230 }
2231
2232 static void _tbm_surface_internal_put_keys(char *keys)
2233 {
2234         if (keys)
2235                 free(keys);
2236 }
2237
2238 void
2239 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2240 {
2241         TBM_RETURN_IF_FAIL(surface != NULL);
2242         TBM_RETURN_IF_FAIL(type != NULL);
2243
2244         tbm_surface_dump_buf_info *buf_info;
2245         struct list_head *next_link;
2246         tbm_surface_info_s info;
2247         tbm_bo_handle bo_handle;
2248         const char *postfix;
2249         const char *format = NULL;
2250         char *keys;
2251         int ret;
2252
2253         if (!g_dump_info)
2254                 return;
2255
2256         next_link = g_dump_info->link->next;
2257         TBM_RETURN_IF_FAIL(next_link != NULL);
2258
2259         if (next_link == &g_dump_info->surface_list) {
2260                 next_link = next_link->next;
2261                 TBM_RETURN_IF_FAIL(next_link != NULL);
2262         }
2263
2264         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2265         TBM_RETURN_IF_FAIL(buf_info != NULL);
2266
2267         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2268         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2269
2270         if (scale_factor > 0.0) {
2271                 const int bpp = 4;
2272
2273                 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
2274                         TBM_WRN("Dump with scale skip. unsupported format(%s)\n",
2275                                           _tbm_surface_internal_format_to_str(info.format));
2276                         tbm_surface_unmap(surface);
2277                         return;
2278                 }
2279
2280                 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2281
2282                 buf_info->info.width = info.width * scale_factor;
2283                 buf_info->info.height = info.height * scale_factor;
2284                 buf_info->info.format = info.format;
2285                 buf_info->info.bpp = _tbm_surface_internal_get_bpp(buf_info->info.format);
2286                 if (!buf_info->info.bpp) {
2287                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
2288                         tbm_surface_unmap(surface);
2289                         return;
2290                 }
2291                 buf_info->info.num_planes = 1;
2292                 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2293                 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2294
2295                 if (buf_info->info.size > buf_info->size) {
2296                         TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)\n",
2297                                         buf_info->info.size, buf_info->size);
2298                         tbm_surface_unmap(surface);
2299                         return;
2300                 }
2301         } else {
2302                 if (info.size > buf_info->size) {
2303                         TBM_WRN("Dump skip. surface over created buffer size(%u, %d)\n",
2304                                         info.size, buf_info->size);
2305                         tbm_surface_unmap(surface);
2306                         return;
2307                 }
2308
2309                 /* make the file information */
2310                 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2311         }
2312
2313         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888) {
2314                 postfix = dump_postfix[0];
2315                 format = _tbm_surface_internal_format_to_str(info.format);
2316         } else
2317                 postfix = dump_postfix[1];
2318
2319         keys = _tbm_surface_internal_get_keys(surface);
2320         if (!keys) {
2321                 TBM_ERR("fail to get keys");
2322                 tbm_surface_unmap(surface);
2323                 return;
2324         }
2325
2326         /* dump */
2327         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2328         if (!bo_handle.ptr) {
2329                 TBM_ERR("fail to map bo");
2330                 _tbm_surface_internal_put_keys(keys);
2331                 tbm_surface_unmap(surface);
2332                 return;
2333         }
2334         memset(bo_handle.ptr, 0x00, buf_info->size);
2335
2336         switch (info.format) {
2337         case TBM_FORMAT_ARGB8888:
2338         case TBM_FORMAT_XRGB8888:
2339                 snprintf(buf_info->name, sizeof(buf_info->name),
2340                                 "%10.3f_%03d%s_%p_%s-%s.%s",
2341                                  _tbm_surface_internal_get_time(),
2342                                  g_dump_info->count++, keys, surface, format, type, postfix);
2343
2344                 if (scale_factor > 0.0) {
2345                         ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2346                                                                                                          bo_handle.ptr,
2347                                                                                                          buf_info->info.format,
2348                                                                                                          info.planes[0].stride,
2349                                                                                                          info.width, info.height,
2350                                                                                                          buf_info->info.planes[0].stride,
2351                                                                                                          buf_info->info.width,
2352                                                                                                          buf_info->info.height);
2353                         if (ret != TBM_SURFACE_ERROR_NONE) {
2354                                 TBM_ERR("fail to scale buffer");
2355                                 tbm_bo_unmap(buf_info->bo);
2356                                 _tbm_surface_internal_put_keys(keys);
2357                                 tbm_surface_unmap(surface);
2358                                 return;
2359                         }
2360                 } else
2361                         memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2362                 break;
2363         case TBM_FORMAT_YVU420:
2364         case TBM_FORMAT_YUV420:
2365                 snprintf(buf_info->name, sizeof(buf_info->name),
2366                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2367                                  _tbm_surface_internal_get_time(),
2368                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2369                                 info.height, FOURCC_STR(info.format), postfix);
2370                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2371                 bo_handle.ptr += info.planes[0].stride * info.height;
2372                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2373                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2374                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2375                 break;
2376         case TBM_FORMAT_NV12:
2377         case TBM_FORMAT_NV21:
2378                 snprintf(buf_info->name, sizeof(buf_info->name),
2379                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2380                                  _tbm_surface_internal_get_time(),
2381                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2382                                 info.height, FOURCC_STR(info.format), postfix);
2383                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2384                 bo_handle.ptr += info.planes[0].stride * info.height;
2385                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2386                 break;
2387         case TBM_FORMAT_YUYV:
2388         case TBM_FORMAT_UYVY:
2389                 snprintf(buf_info->name, sizeof(buf_info->name),
2390                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2391                                  _tbm_surface_internal_get_time(),
2392                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2393                                 info.height, FOURCC_STR(info.format), postfix);
2394                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2395                 break;
2396         default:
2397                 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2398                 tbm_bo_unmap(buf_info->bo);
2399                 _tbm_surface_internal_put_keys(keys);
2400                 tbm_surface_unmap(surface);
2401                 return;
2402         }
2403
2404         tbm_bo_unmap(buf_info->bo);
2405
2406         _tbm_surface_internal_put_keys(keys);
2407
2408         tbm_surface_unmap(surface);
2409
2410         buf_info->dirty = 1;
2411         buf_info->dirty_shm = 0;
2412
2413         if (g_dump_info->count == 1000)
2414                 g_dump_info->count = 0;
2415
2416         g_dump_info->link = next_link;
2417
2418         TBM_INFO("Dump %s \n", buf_info->name);
2419 }
2420
2421 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2422                                                 const char *type)
2423 {
2424         TBM_RETURN_IF_FAIL(ptr != NULL);
2425         TBM_RETURN_IF_FAIL(w > 0);
2426         TBM_RETURN_IF_FAIL(h > 0);
2427         TBM_RETURN_IF_FAIL(stride > 0);
2428         TBM_RETURN_IF_FAIL(type != NULL);
2429
2430         tbm_surface_dump_buf_info *buf_info;
2431         struct list_head *next_link;
2432         tbm_bo_handle bo_handle;
2433         int ret, size, dw = 0, dh = 0, dstride = 0;
2434
2435         if (!g_dump_info)
2436                 return;
2437
2438         next_link = g_dump_info->link->next;
2439         TBM_RETURN_IF_FAIL(next_link != NULL);
2440
2441         if (next_link == &g_dump_info->surface_list) {
2442                 next_link = next_link->next;
2443                 TBM_RETURN_IF_FAIL(next_link != NULL);
2444         }
2445
2446         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2447         TBM_RETURN_IF_FAIL(buf_info != NULL);
2448
2449         if (scale_factor > 0.0) {
2450                 const int bpp = 4;
2451
2452                 dw = w * scale_factor;
2453                 dh = h * scale_factor;
2454                 dstride = dw * bpp;
2455                 size = dstride * dh;
2456         } else
2457                 size = stride * h;
2458
2459         if (size > buf_info->size) {
2460                 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2461                                 size, buf_info->size);
2462                 return;
2463         }
2464
2465         /* dump */
2466         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2467         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2468
2469         memset(bo_handle.ptr, 0x00, buf_info->size);
2470         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2471
2472         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2473                          _tbm_surface_internal_get_time(),
2474                          g_dump_info->count++, type, dump_postfix[0]);
2475         if (scale_factor > 0.0) {
2476                 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2477                                                                                                  TBM_FORMAT_ARGB8888, stride,
2478                                                                                                  w, h, dstride, dw, dh);
2479                 if (ret != TBM_SURFACE_ERROR_NONE) {
2480                         TBM_ERR("fail to scale buffer");
2481                         tbm_bo_unmap(buf_info->bo);
2482                         return;
2483                 }
2484                 buf_info->shm_stride = dstride;
2485                 buf_info->shm_h = dh;
2486         } else {
2487                 memcpy(bo_handle.ptr, ptr, size);
2488                 buf_info->shm_stride = stride;
2489                 buf_info->shm_h = h;
2490         }
2491
2492         tbm_bo_unmap(buf_info->bo);
2493
2494         buf_info->dirty = 0;
2495         buf_info->dirty_shm = 1;
2496
2497         if (g_dump_info->count == 1000)
2498                 g_dump_info->count = 0;
2499
2500         g_dump_info->link = next_link;
2501
2502         TBM_INFO("Dump %s \n", buf_info->name);
2503 }
2504
2505 int
2506 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2507 {
2508         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2509         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2510         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2511
2512         tbm_surface_info_s info;
2513         const char *postfix;
2514         int ret;
2515         char file[1024];
2516
2517         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2518         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2519
2520         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2521                 postfix = dump_postfix[0];
2522         else
2523                 postfix = dump_postfix[1];
2524
2525         if (strcmp(postfix, type)) {
2526                 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2527                 tbm_surface_unmap(surface);
2528                 return 0;
2529         }
2530
2531         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2532
2533         if (!access(file, 0)) {
2534                 TBM_ERR("can't capture  buffer, exist file %s", file);
2535                 tbm_surface_unmap(surface);
2536                 return 0;
2537         }
2538
2539         switch (info.format) {
2540         case TBM_FORMAT_ARGB8888:
2541                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2542                                                         info.width,
2543                                                         info.height,
2544                                                         info.planes[0].stride,
2545                                                         TBM_FORMAT_ARGB8888);
2546                 break;
2547         case TBM_FORMAT_XRGB8888:
2548                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2549                                                         info.width,
2550                                                         info.height,
2551                                                         info.planes[0].stride,
2552                                                         TBM_FORMAT_XRGB8888);
2553                 break;
2554         case TBM_FORMAT_YVU420:
2555         case TBM_FORMAT_YUV420:
2556                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2557                                 info.planes[0].stride * info.height,
2558                                 info.planes[1].ptr,
2559                                 info.planes[1].stride * (info.height >> 1),
2560                                 info.planes[2].ptr,
2561                                 info.planes[2].stride * (info.height >> 1));
2562                 break;
2563         case TBM_FORMAT_NV12:
2564         case TBM_FORMAT_NV21:
2565                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2566                                         info.planes[0].stride * info.height,
2567                                         info.planes[1].ptr,
2568                                         info.planes[1].stride * (info.height >> 1),
2569                                         NULL, 0);
2570                 break;
2571         case TBM_FORMAT_YUYV:
2572         case TBM_FORMAT_UYVY:
2573                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2574                                         info.planes[0].stride * info.height,
2575                                         NULL, 0, NULL, 0);
2576                 break;
2577         default:
2578                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2579                 tbm_surface_unmap(surface);
2580                 return 0;
2581         }
2582
2583         tbm_surface_unmap(surface);
2584
2585         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2586
2587         return 1;
2588 }
2589
2590 int
2591 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2592                                                 const char *path, const char *name, const char *type)
2593 {
2594         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2595         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2596         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2597         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2598         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2599         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2600
2601         char file[1024];
2602
2603         if (strcmp(dump_postfix[0], type)) {
2604                 TBM_ERR("Not supported type:%s'", type);
2605                 return 0;
2606         }
2607
2608         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2609
2610         if (!access(file, 0)) {
2611                 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2612                 return 0;
2613         }
2614
2615         _tbm_surface_internal_dump_file_png(file, ptr, w, h, stride, 0);
2616
2617         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2618
2619         return 1;
2620 }
2621
2622 int
2623 tbm_surface_internal_set_damage(tbm_surface_h surface, int x, int y, int width, int height)
2624 {
2625         struct _tbm_surface *surf;
2626
2627         _tbm_surface_mutex_lock();
2628         _tbm_set_last_result(TBM_ERROR_NONE);
2629
2630         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, 0);
2631         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, 0);
2632         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2633
2634         surf = (struct _tbm_surface *)surface;
2635
2636         surf->damage.x = x;
2637         surf->damage.y = y;
2638         surf->damage.width = width;
2639         surf->damage.height = height;
2640
2641         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2642                                                         surface, x, y, width, height);
2643
2644         _tbm_surface_mutex_unlock();
2645
2646         return 1;
2647 }
2648
2649 int
2650 tbm_surface_internal_get_damage(tbm_surface_h surface, int *x, int *y, int *width, int *height)
2651 {
2652         struct _tbm_surface *surf;
2653
2654         _tbm_surface_mutex_lock();
2655         _tbm_set_last_result(TBM_ERROR_NONE);
2656
2657         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2658
2659         surf = (struct _tbm_surface *)surface;
2660
2661         if (x) *x = surf->damage.x;
2662         if (y) *y = surf->damage.y;
2663         if (width) *width = surf->damage.width;
2664         if (height) *height = surf->damage.height;
2665
2666         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2667                                                         surface, surf->damage.x, surf->damage.y, surf->damage.width, surf->damage.height);
2668
2669         _tbm_surface_mutex_unlock();
2670
2671         return 1;
2672 }
2673
2674 int
2675 tbm_surface_internal_add_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2676 {
2677         struct _tbm_surface *surf;
2678         tbm_surface_destroy_func_info *func_info = NULL;
2679
2680         _tbm_surface_mutex_lock();
2681         _tbm_set_last_result(TBM_ERROR_NONE);
2682
2683         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2684         TBM_SURFACE_RETURN_VAL_IF_FAIL(func != NULL, 0);
2685
2686         surf = (struct _tbm_surface *)surface;
2687         LIST_FOR_EACH_ENTRY(func_info, &surf->destroy_funcs, item_link) {
2688                 if (func_info->destroy_func == func && func_info->user_data == user_data) {
2689                         TBM_ERR("can't add twice");
2690                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
2691                         _tbm_surface_mutex_unlock();
2692                         return 0;
2693                 }
2694         }
2695
2696         func_info = calloc(1, sizeof(tbm_surface_destroy_func_info));
2697         if (func_info == NULL) {
2698                 TBM_ERR("alloc failed");
2699                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
2700                 _tbm_surface_mutex_unlock();
2701                 return 0;
2702         }
2703
2704         func_info->destroy_func = func;
2705         func_info->user_data = user_data;
2706
2707         LIST_ADDTAIL(&func_info->item_link, &surf->destroy_funcs);
2708
2709         _tbm_surface_mutex_unlock();
2710
2711         return 1;
2712 }
2713
2714 void
2715 tbm_surface_internal_remove_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2716 {
2717         struct _tbm_surface *surf;
2718         tbm_surface_destroy_func_info *func_info = NULL, *next = NULL;
2719
2720         _tbm_surface_mutex_lock();
2721         _tbm_set_last_result(TBM_ERROR_NONE);
2722
2723         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
2724         TBM_SURFACE_RETURN_IF_FAIL(func != NULL);
2725
2726         surf = (struct _tbm_surface *)surface;
2727         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &surf->destroy_funcs, item_link) {
2728                 if (func_info->destroy_func != func || func_info->user_data != user_data)
2729                         continue;
2730
2731                 LIST_DEL(&func_info->item_link);
2732                 free(func_info);
2733
2734                 _tbm_surface_mutex_unlock();
2735
2736                 return;
2737         }
2738
2739         _tbm_surface_mutex_unlock();
2740 }
2741
2742 tbm_surface_buffer_data *
2743 tbm_surface_internal_export(tbm_surface_h surface, tbm_error_e *error)
2744 {
2745         // TODO: implement
2746         return NULL;
2747 }
2748
2749 tbm_surface_h
2750 tbm_surface_internal_import(tbm_surface_info_s *surface_info, tbm_surface_buffer_data *buffer_data, tbm_error_e *error)
2751 {
2752         // TODO: implement
2753         return NULL;
2754 }
2755
2756 /*LCOV_EXCL_STOP*/