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