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