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