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