Revert "tbm_surface_internal: Removes avoidable malloc() for png dump"
[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, const void *data, int width, int height, int format)
1771 {
1772         unsigned int *blocks = (unsigned int *)data;
1773         FILE *fp;
1774         int pixel_size;
1775         png_bytep *row_pointers;
1776         int depth = 8, y;
1777
1778         if (_tbm_surface_check_file_is_symbolic_link(file))
1779                 TBM_ERR("%s is symbolic link\n", file);
1780
1781         fp = fopen(file, "wb");
1782         TBM_RETURN_IF_FAIL(fp != NULL);
1783
1784         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1785                                                         NULL, NULL, NULL);
1786         if (!pPngStruct) {
1787                 TBM_ERR("fail to create a png write structure.\n");
1788                 fclose(fp);
1789                 return;
1790         }
1791
1792         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1793         if (!pPngInfo) {
1794                 TBM_ERR("fail to create a png info structure.\n");
1795                 png_destroy_write_struct(&pPngStruct, NULL);
1796                 fclose(fp);
1797                 return;
1798         }
1799
1800         png_init_io(pPngStruct, fp);
1801         if (format == TBM_FORMAT_XRGB8888) {
1802                 pixel_size = 3;
1803                 png_set_IHDR(pPngStruct,
1804                                 pPngInfo,
1805                                 width,
1806                                 height,
1807                                 depth,
1808                                 PNG_COLOR_TYPE_RGB,
1809                                 PNG_INTERLACE_NONE,
1810                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1811         } else {
1812                 pixel_size = 4;
1813                 png_set_IHDR(pPngStruct,
1814                                 pPngInfo,
1815                                 width,
1816                                 height,
1817                                 depth,
1818                                 PNG_COLOR_TYPE_RGBA,
1819                                 PNG_INTERLACE_NONE,
1820                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1821         }
1822
1823         png_set_bgr(pPngStruct);
1824         png_write_info(pPngStruct, pPngInfo);
1825
1826         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1827         if (!row_pointers) {
1828                 TBM_ERR("fail to allocate the png row_pointers.\n");
1829                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1830                 fclose(fp);
1831                 return;
1832         }
1833
1834         for (y = 0; y < height; ++y) {
1835                 png_bytep row;
1836                 int x = 0;
1837
1838                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1839                 if (!row) {
1840                         TBM_ERR("fail to allocate the png row.\n");
1841                         for (x = 0; x < y; x++)
1842                                 png_free(pPngStruct, row_pointers[x]);
1843                         png_free(pPngStruct, row_pointers);
1844                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1845                         fclose(fp);
1846                         return;
1847                 }
1848                 row_pointers[y] = (png_bytep)row;
1849
1850                 for (x = 0; x < width; ++x) {
1851                         unsigned int curBlock = blocks[y * width + x];
1852
1853                         if (pixel_size == 3) { // XRGB8888
1854                                 row[x * pixel_size] = (curBlock & 0xFF);
1855                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1856                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1857                         } else { // ARGB8888
1858                                 row[x * pixel_size] = (curBlock & 0xFF);
1859                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1860                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1861                                 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1862                         }
1863                 }
1864         }
1865
1866         png_write_image(pPngStruct, row_pointers);
1867         png_write_end(pPngStruct, pPngInfo);
1868
1869         for (y = 0; y < height; y++)
1870                 png_free(pPngStruct, row_pointers[y]);
1871         png_free(pPngStruct, row_pointers);
1872
1873         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1874
1875         fclose(fp);
1876 }
1877
1878 void
1879 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1880 {
1881         TBM_RETURN_IF_FAIL(path != NULL);
1882         TBM_RETURN_IF_FAIL(w > 0);
1883         TBM_RETURN_IF_FAIL(h > 0);
1884         TBM_RETURN_IF_FAIL(count > 0);
1885
1886         tbm_surface_dump_buf_info *buf_info = NULL;
1887         tbm_surface_h tbm_surface;
1888         tbm_surface_info_s info;
1889         int buffer_size, i;
1890
1891         /* check running */
1892         if (g_dump_info) {
1893                 TBM_WRN("waring already running the tbm_surface_internal_dump.\n");
1894                 return;
1895         }
1896
1897         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1898         TBM_RETURN_IF_FAIL(g_dump_info);
1899
1900         LIST_INITHEAD(&g_dump_info->surface_list);
1901         g_dump_info->count = 0;
1902         g_dump_info->dump_max = count;
1903
1904         /* get buffer size */
1905         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1906         if (tbm_surface == NULL) {
1907                 TBM_ERR("tbm_surface_create fail\n");
1908                 free(g_dump_info);
1909                 g_dump_info = NULL;
1910                 return;
1911         }
1912
1913         if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
1914                 TBM_ERR("tbm_surface_get_info fail\n");
1915                 tbm_surface_destroy(tbm_surface);
1916                 free(g_dump_info);
1917                 g_dump_info = NULL;
1918                 return;
1919         }
1920         buffer_size = info.size;
1921         tbm_surface_destroy(tbm_surface);
1922
1923         /* create dump lists */
1924         for (i = 0; i < count; i++) {
1925                 tbm_bo bo = NULL;
1926
1927                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1928                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1929
1930                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1931                 if (bo == NULL) {
1932                         TBM_ERR("fail to allocate the tbm_bo[%d]\n", i);
1933                         free(buf_info);
1934                         goto fail;
1935                 }
1936
1937                 buf_info->index = i;
1938                 buf_info->bo = bo;
1939                 buf_info->size = buffer_size;
1940
1941                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1942         }
1943
1944         g_dump_info->path = path;
1945         g_dump_info->link = &g_dump_info->surface_list;
1946
1947         scale_factor = 0.0;
1948
1949         TBM_INFO("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1950
1951         return;
1952
1953 fail:
1954         /* free resources */
1955         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1956                 tbm_surface_dump_buf_info *tmp;
1957
1958                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1959                         tbm_bo_unref(buf_info->bo);
1960                         LIST_DEL(&buf_info->link);
1961                         free(buf_info);
1962                 }
1963         }
1964
1965         TBM_ERR("Dump Start fail.. path:%s\n", g_dump_info->path);
1966
1967         free(g_dump_info);
1968         g_dump_info = NULL;
1969
1970         return;
1971 }
1972
1973 void
1974 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
1975 {
1976         if (scale > 0.0) {
1977                 w *= scale;
1978                 h *= scale;
1979         }
1980
1981         tbm_surface_internal_dump_start(path, w, h, count);
1982         scale_factor = scale;
1983 }
1984
1985 void
1986 tbm_surface_internal_dump_end(void)
1987 {
1988         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1989         tbm_bo_handle bo_handle;
1990
1991         if (!g_dump_info)
1992                 return;
1993
1994         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1995                 free(g_dump_info);
1996                 g_dump_info = NULL;
1997                 return;
1998         }
1999
2000         /* make files */
2001         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2002                 char file[2048];
2003
2004                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
2005                 if (bo_handle.ptr == NULL) {
2006                         tbm_bo_unref(buf_info->bo);
2007                         LIST_DEL(&buf_info->link);
2008                         free(buf_info);
2009                         continue;
2010                 }
2011
2012                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
2013                 TBM_INFO("Dump File.. %s generated.\n", file);
2014
2015                 if (buf_info->dirty) {
2016                         void *ptr1 = NULL, *ptr2 = NULL;
2017
2018                         switch (buf_info->info.format) {
2019                         case TBM_FORMAT_ARGB8888:
2020                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2021                                                         buf_info->info.planes[0].stride >> 2,
2022                                                         buf_info->info.height, TBM_FORMAT_ARGB8888);
2023                                 break;
2024                         case TBM_FORMAT_XRGB8888:
2025                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2026                                                         buf_info->info.planes[0].stride >> 2,
2027                                                         buf_info->info.height, TBM_FORMAT_XRGB8888);
2028                                 break;
2029                         case TBM_FORMAT_YVU420:
2030                         case TBM_FORMAT_YUV420:
2031                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2032                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
2033                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2034                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2035                                                         ptr1,
2036                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2037                                                         ptr2,
2038                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
2039                                 break;
2040                         case TBM_FORMAT_NV12:
2041                         case TBM_FORMAT_NV21:
2042                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2043                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2044                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2045                                                         ptr1,
2046                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2047                                                         NULL, 0);
2048                                 break;
2049                         case TBM_FORMAT_YUYV:
2050                         case TBM_FORMAT_UYVY:
2051                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2052                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2053                                                         NULL, 0, NULL, 0);
2054                                 break;
2055                         default:
2056                                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
2057                                 break;
2058                         }
2059                 } else if (buf_info->dirty_shm)
2060                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2061                                                         buf_info->shm_stride >> 2,
2062                                                         buf_info->shm_h, 0);
2063
2064                 tbm_bo_unmap(buf_info->bo);
2065                 tbm_bo_unref(buf_info->bo);
2066                 LIST_DEL(&buf_info->link);
2067                 free(buf_info);
2068         }
2069
2070         free(g_dump_info);
2071         g_dump_info = NULL;
2072
2073         TBM_INFO("Dump End..\n");
2074 }
2075
2076 static pixman_format_code_t
2077 _tbm_surface_internal_pixman_format_get(tbm_format format)
2078 {
2079         switch (format) {
2080         case TBM_FORMAT_ARGB8888:
2081                 return PIXMAN_a8r8g8b8;
2082         case TBM_FORMAT_XRGB8888:
2083                 return PIXMAN_x8r8g8b8;
2084         default:
2085                 return 0;
2086         }
2087
2088         return 0;
2089 }
2090
2091 /**
2092  * This function supports only if a buffer has below formats.
2093  * - TBM_FORMAT_ARGB8888
2094  * - TBM_FORMAT_XRGB8888
2095  */
2096 static tbm_surface_error_e
2097 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
2098                                                                    int format, int src_stride, int src_w, int src_h,
2099                                                                    int dst_stride, int dst_w, int dst_h)
2100 {
2101         pixman_image_t *src_img = NULL, *dst_img = NULL;
2102         pixman_format_code_t pixman_format;
2103         pixman_transform_t t;
2104         struct pixman_f_transform ft;
2105         double scale_x, scale_y;
2106
2107         TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2108         TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2109
2110         pixman_format = _tbm_surface_internal_pixman_format_get(format);
2111         TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2112
2113         /* src */
2114         src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2115                                                                            (uint32_t*)src_ptr, src_stride);
2116         TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2117
2118         /* dst */
2119         dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2120                                                                            (uint32_t*)dst_ptr, dst_stride);
2121         TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2122
2123         pixman_f_transform_init_identity(&ft);
2124
2125         scale_x = (double)src_w / dst_w;
2126         scale_y = (double)src_h / dst_h;
2127
2128         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2129         pixman_f_transform_translate(&ft, NULL, 0, 0);
2130         pixman_transform_from_pixman_f_transform(&t, &ft);
2131         pixman_image_set_transform(src_img, &t);
2132
2133         pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2134                                                    0, 0, 0, 0, 0, 0, dst_w, dst_h);
2135
2136         pixman_image_unref(src_img);
2137         pixman_image_unref(dst_img);
2138
2139         return TBM_SURFACE_ERROR_NONE;
2140
2141 cant_convert:
2142         if (src_img)
2143                 pixman_image_unref(src_img);
2144
2145         return TBM_SURFACE_ERROR_INVALID_OPERATION;
2146 }
2147
2148 #define MAX_BOS         4       // This value is came from bos[4] in struct _tbm_surface
2149 #define KEY_LEN         5       // "_XXXX"
2150 #define KEYS_LEN        KEY_LEN * MAX_BOS
2151
2152 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2153 {
2154         char *keys, temp_key[KEY_LEN + 1];
2155         struct _tbm_surface *surf;
2156         int i, num_bos;
2157         tbm_bo bo;
2158
2159         _tbm_surface_mutex_lock();
2160
2161         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2162
2163         surf = (struct _tbm_surface *)surface;
2164
2165         num_bos = surf->num_bos;
2166         if (num_bos > MAX_BOS)
2167                 num_bos = MAX_BOS;
2168
2169         keys = calloc(KEYS_LEN + 1, sizeof(char));
2170         if (!keys) {
2171                 TBM_ERR("Failed to alloc memory");
2172                 _tbm_surface_mutex_unlock();
2173                 return NULL;
2174         }
2175
2176         for (i = 0; i < num_bos; i++) {
2177                 memset(temp_key, 0x00, KEY_LEN + 1);
2178                 bo = surf->bos[i];
2179                 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2180                 strncat(keys, temp_key, KEY_LEN);
2181         }
2182
2183         _tbm_surface_mutex_unlock();
2184
2185         return keys;
2186 }
2187
2188 static void _tbm_surface_internal_put_keys(char *keys)
2189 {
2190         if (keys)
2191                 free(keys);
2192 }
2193
2194 void
2195 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2196 {
2197         TBM_RETURN_IF_FAIL(surface != NULL);
2198         TBM_RETURN_IF_FAIL(type != NULL);
2199
2200         tbm_surface_dump_buf_info *buf_info;
2201         struct list_head *next_link;
2202         tbm_surface_info_s info;
2203         tbm_bo_handle bo_handle;
2204         const char *postfix;
2205         const char *format = NULL;
2206         char *keys;
2207         int ret;
2208
2209         if (!g_dump_info)
2210                 return;
2211
2212         next_link = g_dump_info->link->next;
2213         TBM_RETURN_IF_FAIL(next_link != NULL);
2214
2215         if (next_link == &g_dump_info->surface_list) {
2216                 next_link = next_link->next;
2217                 TBM_RETURN_IF_FAIL(next_link != NULL);
2218         }
2219
2220         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2221         TBM_RETURN_IF_FAIL(buf_info != NULL);
2222
2223         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2224         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2225
2226         if (scale_factor > 0.0) {
2227                 const int bpp = 4;
2228
2229                 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
2230                         TBM_WRN("Dump with scale skip. unsupported format(%s)\n",
2231                                           _tbm_surface_internal_format_to_str(info.format));
2232                         tbm_surface_unmap(surface);
2233                         return;
2234                 }
2235
2236                 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2237
2238                 buf_info->info.width = info.width * scale_factor;
2239                 buf_info->info.height = info.height * scale_factor;
2240                 buf_info->info.format = info.format;
2241                 buf_info->info.bpp = _tbm_surface_internal_get_bpp(buf_info->info.format);
2242                 if (!buf_info->info.bpp) {
2243                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
2244                         tbm_surface_unmap(surface);
2245                         return;
2246                 }
2247                 buf_info->info.num_planes = 1;
2248                 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2249                 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2250
2251                 if (buf_info->info.size > buf_info->size) {
2252                         TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)\n",
2253                                         buf_info->info.size, buf_info->size);
2254                         tbm_surface_unmap(surface);
2255                         return;
2256                 }
2257         } else {
2258                 if (info.size > buf_info->size) {
2259                         TBM_WRN("Dump skip. surface over created buffer size(%u, %d)\n",
2260                                         info.size, buf_info->size);
2261                         tbm_surface_unmap(surface);
2262                         return;
2263                 }
2264
2265                 /* make the file information */
2266                 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2267         }
2268
2269         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888) {
2270                 postfix = dump_postfix[0];
2271                 format = _tbm_surface_internal_format_to_str(info.format);
2272         } else
2273                 postfix = dump_postfix[1];
2274
2275         keys = _tbm_surface_internal_get_keys(surface);
2276         if (!keys) {
2277                 TBM_ERR("fail to get keys");
2278                 tbm_surface_unmap(surface);
2279                 return;
2280         }
2281
2282         /* dump */
2283         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2284         if (!bo_handle.ptr) {
2285                 TBM_ERR("fail to map bo");
2286                 _tbm_surface_internal_put_keys(keys);
2287                 tbm_surface_unmap(surface);
2288                 return;
2289         }
2290         memset(bo_handle.ptr, 0x00, buf_info->size);
2291
2292         switch (info.format) {
2293         case TBM_FORMAT_ARGB8888:
2294         case TBM_FORMAT_XRGB8888:
2295                 snprintf(buf_info->name, sizeof(buf_info->name),
2296                                 "%10.3f_%03d%s_%p_%s-%s.%s",
2297                                  _tbm_surface_internal_get_time(),
2298                                  g_dump_info->count++, keys, surface, format, type, postfix);
2299
2300                 if (scale_factor > 0.0) {
2301                         ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2302                                                                                                          bo_handle.ptr,
2303                                                                                                          buf_info->info.format,
2304                                                                                                          info.planes[0].stride,
2305                                                                                                          info.width, info.height,
2306                                                                                                          buf_info->info.planes[0].stride,
2307                                                                                                          buf_info->info.width,
2308                                                                                                          buf_info->info.height);
2309                         if (ret != TBM_SURFACE_ERROR_NONE) {
2310                                 TBM_ERR("fail to scale buffer");
2311                                 tbm_bo_unmap(buf_info->bo);
2312                                 _tbm_surface_internal_put_keys(keys);
2313                                 tbm_surface_unmap(surface);
2314                                 return;
2315                         }
2316                 } else
2317                         memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2318                 break;
2319         case TBM_FORMAT_YVU420:
2320         case TBM_FORMAT_YUV420:
2321                 snprintf(buf_info->name, sizeof(buf_info->name),
2322                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2323                                  _tbm_surface_internal_get_time(),
2324                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2325                                 info.height, FOURCC_STR(info.format), postfix);
2326                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2327                 bo_handle.ptr += info.planes[0].stride * info.height;
2328                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2329                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2330                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2331                 break;
2332         case TBM_FORMAT_NV12:
2333         case TBM_FORMAT_NV21:
2334                 snprintf(buf_info->name, sizeof(buf_info->name),
2335                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2336                                  _tbm_surface_internal_get_time(),
2337                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2338                                 info.height, FOURCC_STR(info.format), postfix);
2339                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2340                 bo_handle.ptr += info.planes[0].stride * info.height;
2341                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2342                 break;
2343         case TBM_FORMAT_YUYV:
2344         case TBM_FORMAT_UYVY:
2345                 snprintf(buf_info->name, sizeof(buf_info->name),
2346                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2347                                  _tbm_surface_internal_get_time(),
2348                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2349                                 info.height, FOURCC_STR(info.format), postfix);
2350                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2351                 break;
2352         default:
2353                 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2354                 tbm_bo_unmap(buf_info->bo);
2355                 _tbm_surface_internal_put_keys(keys);
2356                 tbm_surface_unmap(surface);
2357                 return;
2358         }
2359
2360         tbm_bo_unmap(buf_info->bo);
2361
2362         _tbm_surface_internal_put_keys(keys);
2363
2364         tbm_surface_unmap(surface);
2365
2366         buf_info->dirty = 1;
2367         buf_info->dirty_shm = 0;
2368
2369         if (g_dump_info->count == 1000)
2370                 g_dump_info->count = 0;
2371
2372         g_dump_info->link = next_link;
2373
2374         TBM_INFO("Dump %s \n", buf_info->name);
2375 }
2376
2377 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2378                                                 const char *type)
2379 {
2380         TBM_RETURN_IF_FAIL(ptr != NULL);
2381         TBM_RETURN_IF_FAIL(w > 0);
2382         TBM_RETURN_IF_FAIL(h > 0);
2383         TBM_RETURN_IF_FAIL(stride > 0);
2384         TBM_RETURN_IF_FAIL(type != NULL);
2385
2386         tbm_surface_dump_buf_info *buf_info;
2387         struct list_head *next_link;
2388         tbm_bo_handle bo_handle;
2389         int ret, size, dw = 0, dh = 0, dstride = 0;
2390
2391         if (!g_dump_info)
2392                 return;
2393
2394         next_link = g_dump_info->link->next;
2395         TBM_RETURN_IF_FAIL(next_link != NULL);
2396
2397         if (next_link == &g_dump_info->surface_list) {
2398                 next_link = next_link->next;
2399                 TBM_RETURN_IF_FAIL(next_link != NULL);
2400         }
2401
2402         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2403         TBM_RETURN_IF_FAIL(buf_info != NULL);
2404
2405         if (scale_factor > 0.0) {
2406                 const int bpp = 4;
2407
2408                 dw = w * scale_factor;
2409                 dh = h * scale_factor;
2410                 dstride = dw * bpp;
2411                 size = dstride * dh;
2412         } else
2413                 size = stride * h;
2414
2415         if (size > buf_info->size) {
2416                 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2417                                 size, buf_info->size);
2418                 return;
2419         }
2420
2421         /* dump */
2422         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2423         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2424
2425         memset(bo_handle.ptr, 0x00, buf_info->size);
2426         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2427
2428         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2429                          _tbm_surface_internal_get_time(),
2430                          g_dump_info->count++, type, dump_postfix[0]);
2431         if (scale_factor > 0.0) {
2432                 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2433                                                                                                  TBM_FORMAT_ARGB8888, stride,
2434                                                                                                  w, h, dstride, dw, dh);
2435                 if (ret != TBM_SURFACE_ERROR_NONE) {
2436                         TBM_ERR("fail to scale buffer");
2437                         tbm_bo_unmap(buf_info->bo);
2438                         return;
2439                 }
2440                 buf_info->shm_stride = dstride;
2441                 buf_info->shm_h = dh;
2442         } else {
2443                 memcpy(bo_handle.ptr, ptr, size);
2444                 buf_info->shm_stride = stride;
2445                 buf_info->shm_h = h;
2446         }
2447
2448         tbm_bo_unmap(buf_info->bo);
2449
2450         buf_info->dirty = 0;
2451         buf_info->dirty_shm = 1;
2452
2453         if (g_dump_info->count == 1000)
2454                 g_dump_info->count = 0;
2455
2456         g_dump_info->link = next_link;
2457
2458         TBM_INFO("Dump %s \n", buf_info->name);
2459 }
2460
2461 int
2462 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2463 {
2464         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2465         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2466         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2467
2468         tbm_surface_info_s info;
2469         const char *postfix;
2470         int ret;
2471         char file[1024];
2472
2473         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2474         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2475
2476         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2477                 postfix = dump_postfix[0];
2478         else
2479                 postfix = dump_postfix[1];
2480
2481         if (strcmp(postfix, type)) {
2482                 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2483                 tbm_surface_unmap(surface);
2484                 return 0;
2485         }
2486
2487         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2488
2489         if (!access(file, 0)) {
2490                 TBM_ERR("can't capture  buffer, exist file %s", file);
2491                 tbm_surface_unmap(surface);
2492                 return 0;
2493         }
2494
2495         switch (info.format) {
2496         case TBM_FORMAT_ARGB8888:
2497                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2498                                                         info.planes[0].stride >> 2,
2499                                                         info.height, TBM_FORMAT_ARGB8888);
2500                 break;
2501         case TBM_FORMAT_XRGB8888:
2502                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2503                                                         info.planes[0].stride >> 2,
2504                                                         info.height, TBM_FORMAT_XRGB8888);
2505                 break;
2506         case TBM_FORMAT_YVU420:
2507         case TBM_FORMAT_YUV420:
2508                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2509                                 info.planes[0].stride * info.height,
2510                                 info.planes[1].ptr,
2511                                 info.planes[1].stride * (info.height >> 1),
2512                                 info.planes[2].ptr,
2513                                 info.planes[2].stride * (info.height >> 1));
2514                 break;
2515         case TBM_FORMAT_NV12:
2516         case TBM_FORMAT_NV21:
2517                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2518                                         info.planes[0].stride * info.height,
2519                                         info.planes[1].ptr,
2520                                         info.planes[1].stride * (info.height >> 1),
2521                                         NULL, 0);
2522                 break;
2523         case TBM_FORMAT_YUYV:
2524         case TBM_FORMAT_UYVY:
2525                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2526                                         info.planes[0].stride * info.height,
2527                                         NULL, 0, NULL, 0);
2528                 break;
2529         default:
2530                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2531                 tbm_surface_unmap(surface);
2532                 return 0;
2533         }
2534
2535         tbm_surface_unmap(surface);
2536
2537         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2538
2539         return 1;
2540 }
2541
2542 int
2543 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2544                                                 const char *path, const char *name, const char *type)
2545 {
2546         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2547         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2548         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2549         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2550         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2551         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2552
2553         char file[1024];
2554
2555         if (strcmp(dump_postfix[0], type)) {
2556                 TBM_ERR("Not supported type:%s'", type);
2557                 return 0;
2558         }
2559
2560         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2561
2562         if (!access(file, 0)) {
2563                 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2564                 return 0;
2565         }
2566
2567         _tbm_surface_internal_dump_file_png(file, ptr, w, h, 0);
2568
2569         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2570
2571         return 1;
2572 }
2573
2574 int
2575 tbm_surface_internal_set_damage(tbm_surface_h surface, int x, int y, int width, int height)
2576 {
2577         struct _tbm_surface *surf;
2578
2579         _tbm_surface_mutex_lock();
2580         _tbm_set_last_result(TBM_ERROR_NONE);
2581
2582         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, 0);
2583         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, 0);
2584         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2585
2586         surf = (struct _tbm_surface *)surface;
2587
2588         surf->damage.x = x;
2589         surf->damage.y = y;
2590         surf->damage.width = width;
2591         surf->damage.height = height;
2592
2593         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2594                                                         surface, x, y, width, height);
2595
2596         _tbm_surface_mutex_unlock();
2597
2598         return 1;
2599 }
2600
2601 int
2602 tbm_surface_internal_get_damage(tbm_surface_h surface, int *x, int *y, int *width, int *height)
2603 {
2604         struct _tbm_surface *surf;
2605
2606         _tbm_surface_mutex_lock();
2607         _tbm_set_last_result(TBM_ERROR_NONE);
2608
2609         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2610
2611         surf = (struct _tbm_surface *)surface;
2612
2613         if (x) *x = surf->damage.x;
2614         if (y) *y = surf->damage.y;
2615         if (width) *width = surf->damage.width;
2616         if (height) *height = surf->damage.height;
2617
2618         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2619                                                         surface, surf->damage.x, surf->damage.y, surf->damage.width, surf->damage.height);
2620
2621         _tbm_surface_mutex_unlock();
2622
2623         return 1;
2624 }
2625 /*LCOV_EXCL_STOP*/