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