add dump prefix time value
[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 #include <stdio.h>
34 #include <time.h>
35 #include <sys/time.h>
36 #include "tbm_bufmgr.h"
37 #include "tbm_bufmgr_int.h"
38 #include "tbm_surface_internal.h"
39 #include "list.h"
40 #include <png.h>
41
42 #define C(b, m)              (((b) >> (m)) & 0xFF)
43 #define B(c, s)              ((((unsigned int)(c)) & 0xff) << (s))
44 #define FOURCC(a, b, c, d)     (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0))
45 #define FOURCC_STR(id)      C(id, 0), C(id, 8), C(id, 16), C(id, 24)
46 #define FOURCC_ID(str)      FOURCC(((char*)str)[0], ((char*)str)[1], ((char*)str)[2], ((char*)str)[3])
47
48 static tbm_bufmgr g_surface_bufmgr;
49 static pthread_mutex_t tbm_surface_lock;
50
51 /* LCOV_EXCL_START */
52 #define USE_REALTIME 1
53
54 static double
55 _tbm_surface_internal_get_time(void)
56 {
57         struct timespec tp;
58         unsigned int time;
59
60 #if USE_REALTIME
61         clock_gettime(CLOCK_REALTIME, &tp);
62 #else /* USE_MONOTONIC */
63         clock_gettime(CLOCK_MONOTONIC, &tp);
64 #endif
65         time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
66
67         return time / 1000.0;
68 }
69
70 char *
71 _tbm_surface_internal_format_to_str(tbm_format format)
72 {
73         switch (format) {
74         case TBM_FORMAT_C8:
75                 return "TBM_FORMAT_C8";
76         case TBM_FORMAT_RGB332:
77                 return "TBM_FORMAT_RGB332";
78         case TBM_FORMAT_BGR233:
79                 return "TBM_FORMAT_BGR233";
80         case TBM_FORMAT_XRGB4444:
81                 return "TBM_FORMAT_XRGB4444";
82         case TBM_FORMAT_XBGR4444:
83                 return "TBM_FORMAT_XBGR4444";
84         case TBM_FORMAT_RGBX4444:
85                 return "TBM_FORMAT_RGBX4444";
86         case TBM_FORMAT_BGRX4444:
87                 return "TBM_FORMAT_BGRX4444";
88         case TBM_FORMAT_ARGB4444:
89                 return "TBM_FORMAT_ARGB4444";
90         case TBM_FORMAT_ABGR4444:
91                 return "TBM_FORMAT_ABGR4444";
92         case TBM_FORMAT_RGBA4444:
93                 return "TBM_FORMAT_RGBA4444";
94         case TBM_FORMAT_BGRA4444:
95                 return "TBM_FORMAT_BGRA4444";
96         case TBM_FORMAT_XRGB1555:
97                 return "TBM_FORMAT_XRGB1555";
98         case TBM_FORMAT_XBGR1555:
99                 return "TBM_FORMAT_XBGR1555";
100         case TBM_FORMAT_RGBX5551:
101                 return "TBM_FORMAT_RGBX5551";
102         case TBM_FORMAT_BGRX5551:
103                 return "TBM_FORMAT_BGRX5551";
104         case TBM_FORMAT_ARGB1555:
105                 return "TBM_FORMAT_ARGB1555";
106         case TBM_FORMAT_ABGR1555:
107                 return "TBM_FORMAT_ABGR1555";
108         case TBM_FORMAT_RGBA5551:
109                 return "TBM_FORMAT_RGBA5551";
110         case TBM_FORMAT_BGRA5551:
111                 return "TBM_FORMAT_BGRA5551";
112         case TBM_FORMAT_RGB565:
113                 return "TBM_FORMAT_RGB565";
114         case TBM_FORMAT_BGR565:
115                 return "TBM_FORMAT_BGR565";
116         case TBM_FORMAT_RGB888:
117                 return "TBM_FORMAT_RGB888";
118         case TBM_FORMAT_BGR888:
119                 return "TBM_FORMAT_BGR888";
120         case TBM_FORMAT_XRGB8888:
121                 return "TBM_FORMAT_XRGB8888";
122         case TBM_FORMAT_XBGR8888:
123                 return "TBM_FORMAT_XBGR8888";
124         case TBM_FORMAT_RGBX8888:
125                 return "TBM_FORMAT_RGBX8888";
126         case TBM_FORMAT_BGRX8888:
127                 return "TBM_FORMAT_BGRX8888";
128         case TBM_FORMAT_ARGB8888:
129                 return "TBM_FORMAT_ARGB8888";
130         case TBM_FORMAT_ABGR8888:
131                 return "TBM_FORMAT_ABGR8888";
132         case TBM_FORMAT_RGBA8888:
133                 return "TBM_FORMAT_RGBA8888";
134         case TBM_FORMAT_BGRA8888:
135                 return "TBM_FORMAT_BGRA8888";
136         case TBM_FORMAT_XRGB2101010:
137                 return "TBM_FORMAT_XRGB2101010";
138         case TBM_FORMAT_XBGR2101010:
139                 return "TBM_FORMAT_XBGR2101010";
140         case TBM_FORMAT_RGBX1010102:
141                 return "TBM_FORMAT_RGBX1010102";
142         case TBM_FORMAT_BGRX1010102:
143                 return "TBM_FORMAT_BGRX1010102";
144         case TBM_FORMAT_ARGB2101010:
145                 return "TBM_FORMAT_ARGB2101010";
146         case TBM_FORMAT_ABGR2101010:
147                 return "TBM_FORMAT_ABGR2101010";
148         case TBM_FORMAT_RGBA1010102:
149                 return "TBM_FORMAT_RGBA1010102";
150         case TBM_FORMAT_BGRA1010102:
151                 return "TBM_FORMAT_BGRA1010102";
152         case TBM_FORMAT_YUYV:
153                 return "TBM_FORMAT_YUYV";
154         case TBM_FORMAT_YVYU:
155                 return "TBM_FORMAT_YVYU";
156         case TBM_FORMAT_UYVY:
157                 return "TBM_FORMAT_UYVY";
158         case TBM_FORMAT_VYUY:
159                 return "TBM_FORMAT_VYUY";
160         case TBM_FORMAT_AYUV:
161                 return "TBM_FORMAT_AYUV";
162         case TBM_FORMAT_NV12:
163                 return "TBM_FORMAT_NV12";
164         case TBM_FORMAT_NV21:
165                 return "TBM_FORMAT_NV21";
166         case TBM_FORMAT_NV16:
167                 return "TBM_FORMAT_NV16";
168         case TBM_FORMAT_NV61:
169                 return "TBM_FORMAT_NV61";
170         case TBM_FORMAT_YUV410:
171                 return "TBM_FORMAT_YUV410";
172         case TBM_FORMAT_YVU410:
173                 return "TBM_FORMAT_YVU410";
174         case TBM_FORMAT_YUV411:
175                 return "TBM_FORMAT_YUV411";
176         case TBM_FORMAT_YVU411:
177                 return "TBM_FORMAT_YVU411";
178         case TBM_FORMAT_YUV420:
179                 return "TBM_FORMAT_YUV420";
180         case TBM_FORMAT_YVU420:
181                 return "TBM_FORMAT_YVU420";
182         case TBM_FORMAT_YUV422:
183                 return "TBM_FORMAT_YUV422";
184         case TBM_FORMAT_YVU422:
185                 return "TBM_FORMAT_YVU422";
186         case TBM_FORMAT_YUV444:
187                 return "TBM_FORMAT_YUV444";
188         case TBM_FORMAT_YVU444:
189                 return "TBM_FORMAT_YVU444";
190         case TBM_FORMAT_NV12MT:
191                 return "TBM_FORMAT_NV12MT";
192         default:
193                 return "unknwon";
194         }
195 }
196 /* LCOV_EXCL_STOP */
197
198 static bool
199 _tbm_surface_mutex_init(void)
200 {
201         static bool tbm_surface_mutex_init = false;
202
203         if (tbm_surface_mutex_init)
204                 return true;
205
206         if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
207                 TBM_LOG_E("fail: tbm_surface mutex init\n");
208                 return false;
209         }
210
211         tbm_surface_mutex_init = true;
212
213         return true;
214 }
215
216 void
217 _tbm_surface_mutex_lock(void)
218 {
219         if (!_tbm_surface_mutex_init())
220                 return;
221
222         pthread_mutex_lock(&tbm_surface_lock);
223 }
224
225 void
226 _tbm_surface_mutex_unlock(void)
227 {
228         pthread_mutex_unlock(&tbm_surface_lock);
229 }
230
231 static void
232 _init_surface_bufmgr(void)
233 {
234         g_surface_bufmgr = tbm_bufmgr_init(-1);
235 }
236
237 static void
238 _deinit_surface_bufmgr(void)
239 {
240         if (!g_surface_bufmgr)
241                 return;
242
243         tbm_bufmgr_deinit(g_surface_bufmgr);
244         g_surface_bufmgr = NULL;
245 }
246
247 static int
248 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
249                                        int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
250 {
251         TBM_RETURN_VAL_IF_FAIL(surface, 0);
252         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
253
254         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
255         struct _tbm_bufmgr *mgr = surf->bufmgr;
256         int ret = 0;
257
258         TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
259         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
260         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
261         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
262
263         if (!mgr->backend->surface_get_plane_data)
264                 return 0;
265
266         ret = mgr->backend->surface_get_plane_data(surf->info.width,
267                         surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
268         if (!ret)
269                 return 0;
270
271         return 1;
272 }
273
274 static void
275 _tbm_surface_internal_destroy(tbm_surface_h surface)
276 {
277         int i;
278         tbm_bufmgr bufmgr = surface->bufmgr;
279         tbm_user_data *old_data = NULL, *tmp = NULL;
280
281         /* destory the user_data_list */
282         if (!LIST_IS_EMPTY(&surface->user_data_list)) {
283                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
284                         DBG("free user_data\n");
285                         user_data_delete(old_data);
286                 }
287         }
288
289         for (i = 0; i < surface->num_bos; i++) {
290                 surface->bos[i]->surface = NULL;
291
292                 tbm_bo_unref(surface->bos[i]);
293                 surface->bos[i] = NULL;
294         }
295
296         LIST_DEL(&surface->item_link);
297
298         free(surface);
299         surface = NULL;
300
301         if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
302                 LIST_DELINIT(&bufmgr->surf_list);
303                 _deinit_surface_bufmgr();
304         }
305 }
306
307 static int
308 _tbm_surface_get_max_size(int * w, int * h)
309 {
310         int count = 0;
311         tbm_surface_h surface = NULL, tmp = NULL;
312         tbm_surface_info_s info;
313
314         *w = 0;
315         *h = 0;
316
317         if (g_surface_bufmgr == NULL)
318                 return count;
319
320         if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
321                 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &g_surface_bufmgr->surf_list, item_link) {
322                         if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
323                                 count++;
324                                 if (*w < info.width) *w = info.width;
325                                 if (*h < info.height) *h = info.height;
326                         }
327                 }
328         }
329
330         return count;
331 }
332
333 int
334 tbm_surface_internal_is_valid(tbm_surface_h surface)
335 {
336         tbm_surface_h old_data = NULL, tmp = NULL;
337
338         if (surface == NULL || g_surface_bufmgr == NULL) {
339                 TBM_TRACE("error: tbm_surface(%p)\n", surface);
340                 return 0;
341         }
342
343         if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
344                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &g_surface_bufmgr->surf_list, item_link) {
345                         if (old_data == surface) {
346                                 TBM_TRACE("tbm_surface(%p)\n", surface);
347                                 return 1;
348                         }
349                 }
350         }
351         TBM_TRACE("error: tbm_surface(%p)\n", surface);
352         return 0;
353 }
354
355 int
356 tbm_surface_internal_query_supported_formats(uint32_t **formats,
357                 uint32_t *num)
358 {
359         struct _tbm_bufmgr *mgr;
360         int ret = 0;
361
362         _tbm_surface_mutex_lock();
363
364         if (!g_surface_bufmgr) {
365                 _init_surface_bufmgr();
366                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
367         }
368
369         mgr = g_surface_bufmgr;
370
371         if (!mgr->backend->surface_supported_format) {
372                 TBM_TRACE("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
373                 _tbm_surface_mutex_unlock();
374                 return 0;
375         }
376
377         ret = mgr->backend->surface_supported_format(formats, num);
378
379         TBM_TRACE("tbm_bufmgr(%p) format num(%d)\n", g_surface_bufmgr, *num);
380
381         _tbm_surface_mutex_unlock();
382
383         return ret;
384 }
385
386 int
387 tbm_surface_internal_get_num_planes(tbm_format format)
388 {
389         int num_planes = 0;
390
391         switch (format) {
392         case TBM_FORMAT_C8:
393         case TBM_FORMAT_RGB332:
394         case TBM_FORMAT_BGR233:
395         case TBM_FORMAT_XRGB4444:
396         case TBM_FORMAT_XBGR4444:
397         case TBM_FORMAT_RGBX4444:
398         case TBM_FORMAT_BGRX4444:
399         case TBM_FORMAT_ARGB4444:
400         case TBM_FORMAT_ABGR4444:
401         case TBM_FORMAT_RGBA4444:
402         case TBM_FORMAT_BGRA4444:
403         case TBM_FORMAT_XRGB1555:
404         case TBM_FORMAT_XBGR1555:
405         case TBM_FORMAT_RGBX5551:
406         case TBM_FORMAT_BGRX5551:
407         case TBM_FORMAT_ARGB1555:
408         case TBM_FORMAT_ABGR1555:
409         case TBM_FORMAT_RGBA5551:
410         case TBM_FORMAT_BGRA5551:
411         case TBM_FORMAT_RGB565:
412         case TBM_FORMAT_BGR565:
413         case TBM_FORMAT_RGB888:
414         case TBM_FORMAT_BGR888:
415         case TBM_FORMAT_XRGB8888:
416         case TBM_FORMAT_XBGR8888:
417         case TBM_FORMAT_RGBX8888:
418         case TBM_FORMAT_BGRX8888:
419         case TBM_FORMAT_ARGB8888:
420         case TBM_FORMAT_ABGR8888:
421         case TBM_FORMAT_RGBA8888:
422         case TBM_FORMAT_BGRA8888:
423         case TBM_FORMAT_XRGB2101010:
424         case TBM_FORMAT_XBGR2101010:
425         case TBM_FORMAT_RGBX1010102:
426         case TBM_FORMAT_BGRX1010102:
427         case TBM_FORMAT_ARGB2101010:
428         case TBM_FORMAT_ABGR2101010:
429         case TBM_FORMAT_RGBA1010102:
430         case TBM_FORMAT_BGRA1010102:
431         case TBM_FORMAT_YUYV:
432         case TBM_FORMAT_YVYU:
433         case TBM_FORMAT_UYVY:
434         case TBM_FORMAT_VYUY:
435         case TBM_FORMAT_AYUV:
436                 num_planes = 1;
437                 break;
438         case TBM_FORMAT_NV12:
439         case TBM_FORMAT_NV12MT:
440         case TBM_FORMAT_NV21:
441         case TBM_FORMAT_NV16:
442         case TBM_FORMAT_NV61:
443                 num_planes = 2;
444                 break;
445         case TBM_FORMAT_YUV410:
446         case TBM_FORMAT_YVU410:
447         case TBM_FORMAT_YUV411:
448         case TBM_FORMAT_YVU411:
449         case TBM_FORMAT_YUV420:
450         case TBM_FORMAT_YVU420:
451         case TBM_FORMAT_YUV422:
452         case TBM_FORMAT_YVU422:
453         case TBM_FORMAT_YUV444:
454         case TBM_FORMAT_YVU444:
455                 num_planes = 3;
456                 break;
457
458         default:
459                 break;
460         }
461
462         TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
463
464         return num_planes;
465 }
466
467 int
468 tbm_surface_internal_get_bpp(tbm_format format)
469 {
470
471         int bpp = 0;
472
473         switch (format) {
474         case TBM_FORMAT_C8:
475         case TBM_FORMAT_RGB332:
476         case TBM_FORMAT_BGR233:
477                 bpp = 8;
478                 break;
479         case TBM_FORMAT_XRGB4444:
480         case TBM_FORMAT_XBGR4444:
481         case TBM_FORMAT_RGBX4444:
482         case TBM_FORMAT_BGRX4444:
483         case TBM_FORMAT_ARGB4444:
484         case TBM_FORMAT_ABGR4444:
485         case TBM_FORMAT_RGBA4444:
486         case TBM_FORMAT_BGRA4444:
487         case TBM_FORMAT_XRGB1555:
488         case TBM_FORMAT_XBGR1555:
489         case TBM_FORMAT_RGBX5551:
490         case TBM_FORMAT_BGRX5551:
491         case TBM_FORMAT_ARGB1555:
492         case TBM_FORMAT_ABGR1555:
493         case TBM_FORMAT_RGBA5551:
494         case TBM_FORMAT_BGRA5551:
495         case TBM_FORMAT_RGB565:
496         case TBM_FORMAT_BGR565:
497                 bpp = 16;
498                 break;
499         case TBM_FORMAT_RGB888:
500         case TBM_FORMAT_BGR888:
501                 bpp = 24;
502                 break;
503         case TBM_FORMAT_XRGB8888:
504         case TBM_FORMAT_XBGR8888:
505         case TBM_FORMAT_RGBX8888:
506         case TBM_FORMAT_BGRX8888:
507         case TBM_FORMAT_ARGB8888:
508         case TBM_FORMAT_ABGR8888:
509         case TBM_FORMAT_RGBA8888:
510         case TBM_FORMAT_BGRA8888:
511         case TBM_FORMAT_XRGB2101010:
512         case TBM_FORMAT_XBGR2101010:
513         case TBM_FORMAT_RGBX1010102:
514         case TBM_FORMAT_BGRX1010102:
515         case TBM_FORMAT_ARGB2101010:
516         case TBM_FORMAT_ABGR2101010:
517         case TBM_FORMAT_RGBA1010102:
518         case TBM_FORMAT_BGRA1010102:
519         case TBM_FORMAT_YUYV:
520         case TBM_FORMAT_YVYU:
521         case TBM_FORMAT_UYVY:
522         case TBM_FORMAT_VYUY:
523         case TBM_FORMAT_AYUV:
524                 bpp = 32;
525                 break;
526         case TBM_FORMAT_NV12:
527         case TBM_FORMAT_NV12MT:
528         case TBM_FORMAT_NV21:
529                 bpp = 12;
530                 break;
531         case TBM_FORMAT_NV16:
532         case TBM_FORMAT_NV61:
533                 bpp = 16;
534                 break;
535         case TBM_FORMAT_YUV410:
536         case TBM_FORMAT_YVU410:
537                 bpp = 9;
538                 break;
539         case TBM_FORMAT_YUV411:
540         case TBM_FORMAT_YVU411:
541         case TBM_FORMAT_YUV420:
542         case TBM_FORMAT_YVU420:
543                 bpp = 12;
544                 break;
545         case TBM_FORMAT_YUV422:
546         case TBM_FORMAT_YVU422:
547                 bpp = 16;
548                 break;
549         case TBM_FORMAT_YUV444:
550         case TBM_FORMAT_YVU444:
551                 bpp = 24;
552                 break;
553         default:
554                 break;
555         }
556
557         TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
558
559         return bpp;
560 }
561
562 tbm_surface_h
563 tbm_surface_internal_create_with_flags(int width, int height,
564                                        int format, int flags)
565 {
566         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
567         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
568
569         struct _tbm_bufmgr *mgr;
570         struct _tbm_surface *surf = NULL;
571         uint32_t size = 0;
572         uint32_t offset = 0;
573         uint32_t stride = 0;
574         uint32_t bo_size = 0;
575         int bo_idx;
576         int i, j;
577
578         _tbm_surface_mutex_lock();
579
580         if (!g_surface_bufmgr) {
581                 _init_surface_bufmgr();
582                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
583         }
584
585         mgr = g_surface_bufmgr;
586         if (!TBM_BUFMGR_IS_VALID(mgr)) {
587                 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
588                                 width, height, _tbm_surface_internal_format_to_str(format), flags);
589                 _tbm_surface_mutex_unlock();
590                 return NULL;
591         }
592         surf = calloc(1, sizeof(struct _tbm_surface));
593         if (!surf) {
594                 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
595                                 width, height, _tbm_surface_internal_format_to_str(format), flags);
596                 _tbm_surface_mutex_unlock();
597                 return NULL;
598         }
599
600         surf->bufmgr = mgr;
601         surf->info.width = width;
602         surf->info.height = height;
603         surf->info.format = format;
604         surf->info.bpp = tbm_surface_internal_get_bpp(format);
605         surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
606         surf->refcnt = 1;
607
608         /* get size, stride and offset bo_idx */
609         for (i = 0; i < surf->info.num_planes; i++) {
610                 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride,
611                                                        &bo_idx);
612                 surf->info.planes[i].size = size;
613                 surf->info.planes[i].offset = offset;
614                 surf->info.planes[i].stride = stride;
615                 surf->planes_bo_idx[i] = bo_idx;
616         }
617
618         surf->num_bos = 1;
619
620         for (i = 0; i < surf->info.num_planes; i++) {
621                 surf->info.size += surf->info.planes[i].size;
622
623                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
624                         surf->num_bos = surf->planes_bo_idx[i] + 1;
625         }
626
627         surf->flags = flags;
628
629         for (i = 0; i < surf->num_bos; i++) {
630                 bo_size = 0;
631                 for (j = 0; j < surf->info.num_planes; j++) {
632                         if (surf->planes_bo_idx[j] == i)
633                                 bo_size += surf->info.planes[j].size;
634                 }
635
636                 if (mgr->backend->surface_bo_alloc) {
637                         /* LCOV_EXCL_START */
638                         tbm_bo bo = NULL;
639                         void *bo_priv = NULL;
640
641                         bo = calloc(1, sizeof(struct _tbm_bo));
642                         if (!bo) {
643                                 TBM_LOG_E("fail to alloc bo struct\n");
644                                 goto alloc_fail;
645                         }
646
647                         bo->bufmgr = surf->bufmgr;
648
649                         pthread_mutex_lock(&surf->bufmgr->lock);
650
651                         bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
652                         if (!bo_priv) {
653                                 TBM_LOG_E("fail to alloc bo priv\n");
654                                 free(bo);
655                                 pthread_mutex_unlock(&surf->bufmgr->lock);
656                                 goto alloc_fail;
657                         }
658
659                         bo->ref_cnt = 1;
660                         bo->flags = flags;
661                         bo->priv = bo_priv;
662
663                         LIST_INITHEAD(&bo->user_data_list);
664
665                         LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
666
667                         pthread_mutex_unlock(&surf->bufmgr->lock);
668
669                         surf->bos[i] = bo;
670                         /* LCOV_EXCL_STOP */
671                 } else {
672                         surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
673                 }
674
675                 if (!surf->bos[i]) {
676                         TBM_LOG_E("fail to alloc bo idx:%d\n", i);
677                         goto alloc_fail;
678                 }
679
680                 _tbm_bo_set_surface(surf->bos[i], surf);
681
682         }
683
684         TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
685                         _tbm_surface_internal_format_to_str(format), flags, surf);
686
687         LIST_INITHEAD(&surf->user_data_list);
688
689         LIST_ADD(&surf->item_link, &mgr->surf_list);
690
691         _tbm_surface_mutex_unlock();
692
693         return surf;
694
695 alloc_fail:
696
697         TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
698                         width, height, _tbm_surface_internal_format_to_str(format), flags);
699
700         for (j = 0; j < i; j++) {
701                 if (surf->bos[j])
702                         tbm_bo_unref(surf->bos[j]);
703         }
704
705         free(surf);
706         surf = NULL;
707
708         if (LIST_IS_EMPTY(&mgr->surf_list)) {
709                 LIST_DELINIT(&mgr->surf_list);
710                 _deinit_surface_bufmgr();
711         }
712
713         _tbm_surface_mutex_unlock();
714         return NULL;
715 }
716
717 tbm_surface_h
718 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
719                                      tbm_bo *bos, int num)
720 {
721         TBM_RETURN_VAL_IF_FAIL(bos, NULL);
722         TBM_RETURN_VAL_IF_FAIL(info, NULL);
723         TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
724
725         struct _tbm_bufmgr *mgr;
726         struct _tbm_surface *surf = NULL;
727         int i;
728
729         _tbm_surface_mutex_lock();
730
731         if (!g_surface_bufmgr) {
732                 _init_surface_bufmgr();
733                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
734         }
735
736         mgr = g_surface_bufmgr;
737         if (!TBM_BUFMGR_IS_VALID(mgr)) {
738                 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
739                                 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
740                 _tbm_surface_mutex_unlock();
741                 return NULL;
742         }
743
744         surf = calloc(1, sizeof(struct _tbm_surface));
745         if (!surf) {
746                 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
747                                 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
748                 _tbm_surface_mutex_unlock();
749                 return NULL;
750         }
751
752         surf->bufmgr = mgr;
753         surf->info.width = info->width;
754         surf->info.height = info->height;
755         surf->info.format = info->format;
756         surf->info.bpp = info->bpp;
757         surf->info.num_planes = info->num_planes;
758         surf->refcnt = 1;
759
760         /* get size, stride and offset */
761         for (i = 0; i < info->num_planes; i++) {
762                 surf->info.planes[i].offset = info->planes[i].offset;
763                 surf->info.planes[i].stride = info->planes[i].stride;
764
765                 if (info->planes[i].size > 0)
766                         surf->info.planes[i].size = info->planes[i].size;
767                 else
768                         surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
769
770                 if (num == 1)
771                         surf->planes_bo_idx[i] = 0;
772                 else
773                         surf->planes_bo_idx[i] = i;
774         }
775
776         if (info->size > 0) {
777                 surf->info.size = info->size;
778         } else {
779                 surf->info.size = 0;
780                 for (i = 0; i < info->num_planes; i++)
781                         surf->info.size += surf->info.planes[i].size;
782         }
783
784         surf->flags = TBM_BO_DEFAULT;
785
786         /* create only one bo */
787         surf->num_bos = num;
788         for (i = 0; i < num; i++) {
789                 if (bos[i] == NULL)
790                         goto bail1;
791
792                 surf->bos[i] = tbm_bo_ref(bos[i]);
793                 _tbm_bo_set_surface(bos[i], surf);
794         }
795
796         TBM_TRACE("tbm_surface(%p) width(%d) height(%d) format(%s) bo_num(%d)\n", surf,
797                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
798
799         LIST_INITHEAD(&surf->user_data_list);
800
801         LIST_ADD(&surf->item_link, &mgr->surf_list);
802
803         _tbm_surface_mutex_unlock();
804
805         return surf;
806 bail1:
807         TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
808                                 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
809         for (i = 0; i < num; i++) {
810                 if (surf->bos[i]) {
811                         tbm_bo_unref(surf->bos[i]);
812                         surf->bos[i] = NULL;
813                 }
814         }
815
816         free(surf);
817         surf = NULL;
818
819         if (LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
820                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
821                 _deinit_surface_bufmgr();
822         }
823
824         _tbm_surface_mutex_unlock();
825
826         return NULL;
827 }
828
829 void
830 tbm_surface_internal_destroy(tbm_surface_h surface)
831 {
832         if (!tbm_surface_internal_is_valid(surface))
833                 return;
834
835         _tbm_surface_mutex_lock();
836
837         surface->refcnt--;
838
839         if (surface->refcnt > 0) {
840                 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
841                 _tbm_surface_mutex_unlock();
842                 return;
843         }
844
845         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
846
847         if (surface->refcnt == 0)
848                 _tbm_surface_internal_destroy(surface);
849
850         _tbm_surface_mutex_unlock();
851 }
852
853 void
854 tbm_surface_internal_ref(tbm_surface_h surface)
855 {
856         TBM_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
857
858         _tbm_surface_mutex_lock();
859
860         surface->refcnt++;
861
862         TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
863
864         _tbm_surface_mutex_unlock();
865 }
866
867 void
868 tbm_surface_internal_unref(tbm_surface_h surface)
869 {
870         TBM_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
871
872         _tbm_surface_mutex_lock();
873
874         surface->refcnt--;
875
876         if (surface->refcnt > 0) {
877                 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
878                 _tbm_surface_mutex_unlock();
879                 return;
880         }
881
882         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
883
884         if (surface->refcnt == 0)
885                 _tbm_surface_internal_destroy(surface);
886
887         _tbm_surface_mutex_unlock();
888 }
889
890 int
891 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
892 {
893         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
894
895         struct _tbm_surface *surf;
896         int num;
897
898         _tbm_surface_mutex_lock();
899
900         surf = (struct _tbm_surface *)surface;
901         num = surf->num_bos;
902
903         TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
904
905         _tbm_surface_mutex_unlock();
906
907         return num;
908 }
909
910 tbm_bo
911 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
912 {
913         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), NULL);
914         TBM_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
915
916         struct _tbm_surface *surf;
917         tbm_bo bo;
918
919         _tbm_surface_mutex_lock();
920
921         surf = (struct _tbm_surface *)surface;
922         bo = surf->bos[bo_idx];
923
924         TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
925
926         _tbm_surface_mutex_unlock();
927
928         return bo;
929 }
930
931 int
932 tbm_surface_internal_get_size(tbm_surface_h surface)
933 {
934         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
935
936         struct _tbm_surface *surf;
937         unsigned int size;
938
939         _tbm_surface_mutex_lock();
940
941         surf = (struct _tbm_surface *)surface;
942         size = surf->info.size;
943
944         TBM_TRACE("tbm_surface(%p) size(%d)\n", surface, size);
945
946         _tbm_surface_mutex_unlock();
947
948         return size;
949 }
950
951 int
952 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
953                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
954 {
955         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
956         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
957
958         struct _tbm_surface *surf;
959
960         _tbm_surface_mutex_lock();
961
962         surf = (struct _tbm_surface *)surface;
963
964         if (plane_idx >= surf->info.num_planes) {
965                 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
966                 _tbm_surface_mutex_unlock();
967                 return 0;
968         }
969
970         if (size)
971                 *size = surf->info.planes[plane_idx].size;
972
973         if (offset)
974                 *offset = surf->info.planes[plane_idx].offset;
975
976         if (pitch)
977                 *pitch = surf->info.planes[plane_idx].stride;
978
979         TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%d) offset(%d) pitch(%d)\n", surface, plane_idx,
980                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
981                                 surf->info.planes[plane_idx].stride);
982
983         _tbm_surface_mutex_unlock();
984
985         return 1;
986 }
987
988 int
989 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
990                               tbm_surface_info_s *info, int map)
991 {
992         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
993
994         struct _tbm_surface *surf;
995         tbm_bo_handle bo_handles[4];
996         int i, j;
997
998         _tbm_surface_mutex_lock();
999
1000         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1001
1002         surf = (struct _tbm_surface *)surface;
1003
1004         memset(info, 0x00, sizeof(tbm_surface_info_s));
1005         info->width = surf->info.width;
1006         info->height = surf->info.height;
1007         info->format = surf->info.format;
1008         info->bpp = surf->info.bpp;
1009         info->size = surf->info.size;
1010         info->num_planes = surf->info.num_planes;
1011
1012         if (map == 1) {
1013                 for (i = 0; i < surf->num_bos; i++) {
1014                         bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1015                         if (bo_handles[i].ptr == NULL) {
1016                                 for (j = 0; j < i; j++)
1017                                         tbm_bo_unmap(surf->bos[j]);
1018
1019                                 TBM_TRACE("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1020                                 _tbm_surface_mutex_unlock();
1021                                 return 0;
1022                         }
1023                 }
1024         } else {
1025                 for (i = 0; i < surf->num_bos; i++)
1026                         bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1027         }
1028
1029         for (i = 0; i < surf->info.num_planes; i++) {
1030                 info->planes[i].size = surf->info.planes[i].size;
1031                 info->planes[i].offset = surf->info.planes[i].offset;
1032                 info->planes[i].stride = surf->info.planes[i].stride;
1033
1034                 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1035                         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1036                                               surf->info.planes[i].offset;
1037         }
1038
1039         TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1040
1041         _tbm_surface_mutex_unlock();
1042
1043         return 1;
1044 }
1045
1046 void
1047 tbm_surface_internal_unmap(tbm_surface_h surface)
1048 {
1049         TBM_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1050
1051         struct _tbm_surface *surf;
1052         int i;
1053
1054         _tbm_surface_mutex_lock();
1055
1056         surf = (struct _tbm_surface *)surface;
1057
1058         for (i = 0; i < surf->num_bos; i++)
1059                 tbm_bo_unmap(surf->bos[i]);
1060
1061         TBM_TRACE("tbm_surface(%p)\n", surface);
1062
1063         _tbm_surface_mutex_unlock();
1064 }
1065
1066 unsigned int
1067 tbm_surface_internal_get_width(tbm_surface_h surface)
1068 {
1069         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1070
1071         struct _tbm_surface *surf;
1072         unsigned int width;
1073
1074         _tbm_surface_mutex_lock();
1075
1076         surf = (struct _tbm_surface *)surface;
1077         width = surf->info.width;
1078
1079         TBM_TRACE("tbm_surface(%p) width(%d)\n", surface, width);
1080
1081         _tbm_surface_mutex_unlock();
1082
1083         return width;
1084 }
1085
1086 unsigned int
1087 tbm_surface_internal_get_height(tbm_surface_h surface)
1088 {
1089         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1090
1091         struct _tbm_surface *surf;
1092         unsigned int height;
1093
1094         _tbm_surface_mutex_lock();
1095
1096         surf = (struct _tbm_surface *)surface;
1097         height = surf->info.height;
1098
1099         TBM_TRACE("tbm_surface(%p) height(%d)\n", surface, height);
1100
1101         _tbm_surface_mutex_unlock();
1102
1103         return height;
1104
1105 }
1106
1107 tbm_format
1108 tbm_surface_internal_get_format(tbm_surface_h surface)
1109 {
1110         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1111
1112         struct _tbm_surface *surf;
1113         tbm_format format;
1114
1115         _tbm_surface_mutex_lock();
1116
1117         surf = (struct _tbm_surface *)surface;
1118         format = surf->info.format;
1119
1120         TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1121
1122         _tbm_surface_mutex_unlock();
1123
1124         return format;
1125 }
1126
1127 int
1128 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1129 {
1130         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1131         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1132         struct _tbm_surface *surf;
1133         int bo_idx;
1134
1135         _tbm_surface_mutex_lock();
1136
1137         surf = (struct _tbm_surface *)surface;
1138         bo_idx = surf->planes_bo_idx[plane_idx];
1139
1140         TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1141
1142         _tbm_surface_mutex_unlock();
1143
1144         return bo_idx;
1145 }
1146
1147 int
1148 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1149                                    tbm_data_free data_free_func)
1150 {
1151         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1152
1153         tbm_user_data *data;
1154
1155         /* check if the data according to the key exist if so, return false. */
1156         data = user_data_lookup(&surface->user_data_list, key);
1157         if (data) {
1158                 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1159                 return 0;
1160         }
1161
1162         data = user_data_create(key, data_free_func);
1163         if (!data) {
1164                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1165                 return 0;
1166         }
1167
1168         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1169
1170         LIST_ADD(&data->item_link, &surface->user_data_list);
1171
1172         return 1;
1173 }
1174
1175 int
1176 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1177                                    void *data)
1178 {
1179         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1180
1181         tbm_user_data *old_data;
1182
1183         if (LIST_IS_EMPTY(&surface->user_data_list)) {
1184                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1185                 return 0;
1186         }
1187
1188         old_data = user_data_lookup(&surface->user_data_list, key);
1189         if (!old_data) {
1190                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1191                 return 0;
1192         }
1193
1194         if (old_data->data && old_data->free_func)
1195                 old_data->free_func(old_data->data);
1196
1197         old_data->data = data;
1198
1199         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1200
1201         return 1;
1202 }
1203
1204 int
1205 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1206                                    void **data)
1207 {
1208         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1209
1210         tbm_user_data *old_data;
1211
1212         if (!data || LIST_IS_EMPTY(&surface->user_data_list)) {
1213                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1214                 return 0;
1215         }
1216
1217         old_data = user_data_lookup(&surface->user_data_list, key);
1218         if (!old_data) {
1219                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1220                 *data = NULL;
1221                 return 0;
1222         }
1223
1224         *data = old_data->data;
1225
1226         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1227
1228         return 1;
1229 }
1230
1231 int
1232 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1233                                       unsigned long key)
1234 {
1235         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1236
1237         tbm_user_data *old_data = (void *)0;
1238
1239         if (LIST_IS_EMPTY(&surface->user_data_list)) {
1240                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1241                 return 0;
1242         }
1243
1244         old_data = user_data_lookup(&surface->user_data_list, key);
1245         if (!old_data) {
1246                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1247                 return 0;
1248         }
1249
1250         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1251
1252         user_data_delete(old_data);
1253
1254         return 1;
1255 }
1256
1257 /* LCOV_EXCL_START */
1258 unsigned int
1259 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1260 {
1261         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1262
1263         return surface->debug_pid;
1264 }
1265
1266 void
1267 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1268 {
1269         TBM_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1270
1271         surface->debug_pid = pid;
1272 }
1273
1274 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1275 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1276
1277 struct _tbm_surface_dump_buf_info {
1278         int index;
1279         tbm_bo bo;
1280         int size;
1281         int dirty;
1282         int dirty_shm;
1283         int shm_stride;
1284         int shm_h;
1285         char name[1024];
1286
1287         tbm_surface_info_s info;
1288
1289         struct list_head link;
1290 };
1291
1292 struct _tbm_surface_dump_info {
1293         char *path;  // copy???
1294         int dump_max;
1295         int count;
1296         struct list_head *link;
1297         struct list_head surface_list; /* link of surface */
1298 };
1299
1300 static tbm_surface_dump_info *g_dump_info = NULL;
1301 static const char *dump_postfix[2] = {"png", "yuv"};
1302
1303 static void
1304 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1, void *data2,
1305                 int size2, void *data3, int size3)
1306 {
1307         unsigned int *blocks;
1308         FILE *fp = fopen(file, "w+");
1309         TBM_RETURN_IF_FAIL(fp != NULL);
1310
1311         blocks = (unsigned int *)data1;
1312         fwrite(blocks, 1, size1, fp);
1313
1314         if (size2 > 0) {
1315                 blocks = (unsigned int *)data2;
1316                 fwrite(blocks, 1, size2, fp);
1317         }
1318
1319         if (size3 > 0) {
1320                 blocks = (unsigned int *)data3;
1321                 fwrite(blocks, 1, size3, fp);
1322         }
1323
1324         fclose(fp);
1325 }
1326
1327 static void
1328 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width,
1329                 int height)
1330 {
1331         FILE *fp = fopen(file, "wb");
1332         TBM_RETURN_IF_FAIL(fp != NULL);
1333         int depth = 8;
1334
1335         png_structp pPngStruct =
1336                 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1337         if (!pPngStruct) {
1338                 fclose(fp);
1339                 return;
1340         }
1341
1342         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1343         if (!pPngInfo) {
1344                 png_destroy_write_struct(&pPngStruct, NULL);
1345                 fclose(fp);
1346                 return;
1347         }
1348
1349         png_init_io(pPngStruct, fp);
1350         png_set_IHDR(pPngStruct,
1351                         pPngInfo,
1352                         width,
1353                         height,
1354                         depth,
1355                         PNG_COLOR_TYPE_RGBA,
1356                         PNG_INTERLACE_NONE,
1357                         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1358
1359         png_set_bgr(pPngStruct);
1360         png_write_info(pPngStruct, pPngInfo);
1361
1362         const int pixel_size = 4;       // RGBA
1363         png_bytep *row_pointers =
1364                         png_malloc(pPngStruct, height * sizeof(png_byte *));
1365
1366         unsigned int *blocks = (unsigned int *)data;
1367         int y = 0;
1368         int x = 0;
1369
1370         for (; y < height; ++y) {
1371                 png_bytep row =
1372                         png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1373                 row_pointers[y] = (png_bytep)row;
1374                 for (x = 0; x < width; ++x) {
1375                         unsigned int curBlock = blocks[y * width + x];
1376                         row[x * pixel_size] = (curBlock & 0xFF);
1377                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1378                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1379                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1380                 }
1381         }
1382
1383         png_write_image(pPngStruct, row_pointers);
1384         png_write_end(pPngStruct, pPngInfo);
1385
1386         for (y = 0; y < height; y++)
1387                 png_free(pPngStruct, row_pointers[y]);
1388         png_free(pPngStruct, row_pointers);
1389
1390         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1391
1392         fclose(fp);
1393 }
1394
1395 void
1396 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1397 {
1398         TBM_RETURN_IF_FAIL(path != NULL);
1399         TBM_RETURN_IF_FAIL(w > 0);
1400         TBM_RETURN_IF_FAIL(h > 0);
1401         TBM_RETURN_IF_FAIL(count > 0);
1402
1403         tbm_surface_dump_buf_info *buf_info = NULL;
1404         tbm_surface_dump_buf_info *tmp;
1405         tbm_bo bo = NULL;
1406         int i;
1407         int buffer_size;
1408         tbm_surface_h tbm_surface;
1409         tbm_surface_info_s info;
1410         tbm_surface_error_e err;
1411
1412         /* check running */
1413         if (g_dump_info) {
1414                 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1415                 return;
1416         }
1417
1418         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1419         TBM_RETURN_IF_FAIL(g_dump_info);
1420
1421         LIST_INITHEAD(&g_dump_info->surface_list);
1422         g_dump_info->count = 0;
1423         g_dump_info->dump_max = count;
1424
1425         /* get buffer size */
1426         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1427         if (tbm_surface == NULL) {
1428                 TBM_LOG_E("tbm_surface_create fail\n");
1429                 free(g_dump_info);
1430                 g_dump_info = NULL;
1431                 return;
1432         }
1433         err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
1434         if (err != TBM_SURFACE_ERROR_NONE) {
1435                 TBM_LOG_E("tbm_surface_map fail\n");
1436                 tbm_surface_destroy(tbm_surface);
1437                 free(g_dump_info);
1438                 g_dump_info = NULL;
1439                 return;
1440         }
1441         buffer_size = info.planes[0].stride * h;
1442         tbm_surface_unmap(tbm_surface);
1443         tbm_surface_destroy(tbm_surface);
1444
1445         /* create dump lists */
1446         for (i = 0; i < count; i++)     {
1447                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1448                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1449                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1450                 if (bo == NULL) {
1451                         free(buf_info);
1452                         goto fail;
1453                 }
1454
1455                 buf_info->index = i;
1456                 buf_info->bo = bo;
1457                 buf_info->size = buffer_size;
1458
1459                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1460         }
1461
1462         g_dump_info->path = path;
1463         g_dump_info->link = &g_dump_info->surface_list;
1464
1465         TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1466
1467         return;
1468 fail:
1469         /* free resources */
1470         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1471                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1472                         tbm_bo_unref(buf_info->bo);
1473                         free(buf_info);
1474                 }
1475         }
1476
1477         TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1478
1479         free(g_dump_info);
1480         g_dump_info = NULL;
1481
1482         return;
1483 }
1484
1485 void
1486 tbm_surface_internal_dump_end(void)
1487 {
1488         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1489         tbm_bo_handle bo_handle;
1490
1491         if (!g_dump_info)
1492                 return;
1493
1494         /* make files */
1495         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1496                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1497                         char file[2048];
1498
1499                         if (buf_info->dirty) {
1500                                 void *ptr1 = NULL;
1501                                 void *ptr2 = NULL;
1502
1503                                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1504                                 if (bo_handle.ptr == NULL)
1505                                         continue;
1506
1507                                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1508                                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1509
1510                                 switch (buf_info->info.format) {
1511                                 case TBM_FORMAT_ARGB8888:
1512                                 case TBM_FORMAT_XRGB8888:
1513                                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1514                                                                         buf_info->info.planes[0].stride >> 2, buf_info->info.height);
1515                                         break;
1516                                 case TBM_FORMAT_YVU420:
1517                                 case TBM_FORMAT_YUV420:
1518                                         ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1519                                         ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1520                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1521                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1522                                                                         ptr1,
1523                                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1524                                                                         ptr2,
1525                                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1526                                         break;
1527                                 case TBM_FORMAT_NV12:
1528                                 case TBM_FORMAT_NV21:
1529                                         ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1530                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1531                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1532                                                                         ptr1,
1533                                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1534                                                                         NULL, 0);
1535                                         break;
1536                                 case TBM_FORMAT_YUYV:
1537                                 case TBM_FORMAT_UYVY:
1538                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1539                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1540                                                                         NULL, 0, NULL, 0);
1541                                         break;
1542                                 default:
1543                                         TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1544                                         tbm_bo_unmap(buf_info->bo);
1545                                         return;
1546                                 }
1547
1548                                 tbm_bo_unmap(buf_info->bo);
1549                         } else if (buf_info->dirty_shm) {
1550                                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1551                                 if (bo_handle.ptr == NULL)
1552                                         continue;
1553
1554                                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1555                                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1556
1557                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1558                                                                 buf_info->shm_stride >> 2, buf_info->shm_h);
1559
1560                                 tbm_bo_unmap(buf_info->bo);
1561                         }
1562                 }
1563         }
1564
1565
1566         /* free resources */
1567         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1568                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1569                         tbm_bo_unref(buf_info->bo);
1570                         free(buf_info);
1571                 }
1572         }
1573
1574         free(g_dump_info);
1575         g_dump_info = NULL;
1576
1577         TBM_LOG_I("Dump End..\n");
1578 }
1579
1580 void
1581 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1582 {
1583         TBM_RETURN_IF_FAIL(surface != NULL);
1584         TBM_RETURN_IF_FAIL(type != NULL);
1585
1586         tbm_surface_dump_buf_info *buf_info;
1587         tbm_surface_info_s info;
1588         struct list_head *next_link;
1589         tbm_bo_handle bo_handle;
1590         int ret;
1591         const char *postfix;
1592
1593         if (!g_dump_info)
1594                 return;
1595
1596         next_link = g_dump_info->link->next;
1597         TBM_RETURN_IF_FAIL(next_link != NULL);
1598
1599         if (next_link == &g_dump_info->surface_list) {
1600                 next_link = next_link->next;
1601                 TBM_RETURN_IF_FAIL(next_link != NULL);
1602         }
1603
1604         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1605         TBM_RETURN_IF_FAIL(buf_info != NULL);
1606
1607         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1608         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1609
1610         if (info.size > buf_info->size) {
1611                 TBM_LOG_W("Dump skip. surface over created buffer size(%d, %d)\n", info.size, buf_info->size);
1612                 tbm_surface_unmap(surface);
1613                 return;
1614         }
1615
1616         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1617                 postfix = dump_postfix[0];
1618         else
1619                 postfix = dump_postfix[1];
1620
1621         /* make the file information */
1622         memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1623
1624         /* dump */
1625         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1626         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1627         memset(bo_handle.ptr, 0x00, buf_info->size);
1628
1629         switch (info.format) {
1630         case TBM_FORMAT_ARGB8888:
1631         case TBM_FORMAT_XRGB8888:
1632                 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d_%p-%s.%s",
1633                                  _tbm_surface_internal_get_time(),
1634                                  g_dump_info->count++, surface, type, postfix);
1635                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1636                 break;
1637         case TBM_FORMAT_YVU420:
1638         case TBM_FORMAT_YUV420:
1639                 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1640                                  _tbm_surface_internal_get_time(),
1641                                  g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1642                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1643                 bo_handle.ptr += info.planes[0].stride * info.height;
1644                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1645                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1646                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1647                 break;
1648         case TBM_FORMAT_NV12:
1649         case TBM_FORMAT_NV21:
1650                 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1651                                  _tbm_surface_internal_get_time(),
1652                                  g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1653                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1654                 bo_handle.ptr += info.planes[0].stride * info.height;
1655                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1656                 break;
1657         case TBM_FORMAT_YUYV:
1658         case TBM_FORMAT_UYVY:
1659                 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1660                                  _tbm_surface_internal_get_time(),
1661                                  g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1662                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1663                 break;
1664         default:
1665                 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1666                 tbm_bo_unmap(buf_info->bo);
1667                 return;
1668         }
1669
1670         tbm_bo_unmap(buf_info->bo);
1671
1672         tbm_surface_unmap(surface);
1673
1674         buf_info->dirty = 1;
1675         buf_info->dirty_shm = 0;
1676
1677         if (g_dump_info->count == 1000)
1678                 g_dump_info->count = 0;
1679
1680         g_dump_info->link = next_link;
1681
1682         TBM_LOG_I("Dump %s \n", buf_info->name);
1683 }
1684
1685 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int  stride, const char *type)
1686 {
1687         TBM_RETURN_IF_FAIL(ptr != NULL);
1688         TBM_RETURN_IF_FAIL(w > 0);
1689         TBM_RETURN_IF_FAIL(h > 0);
1690         TBM_RETURN_IF_FAIL(stride > 0);
1691         TBM_RETURN_IF_FAIL(type != NULL);
1692
1693         tbm_surface_dump_buf_info *buf_info;
1694         struct list_head *next_link;
1695         tbm_bo_handle bo_handle;
1696
1697         if (!g_dump_info)
1698                 return;
1699
1700         next_link = g_dump_info->link->next;
1701         TBM_RETURN_IF_FAIL(next_link != NULL);
1702
1703         if (next_link == &g_dump_info->surface_list) {
1704                 next_link = next_link->next;
1705                 TBM_RETURN_IF_FAIL(next_link != NULL);
1706         }
1707
1708         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1709         TBM_RETURN_IF_FAIL(buf_info != NULL);
1710
1711         if (stride * h > buf_info->size) {
1712                 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n", stride * h, buf_info->size);
1713                 return;
1714         }
1715
1716         /* dump */
1717         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1718         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1719         memset(bo_handle.ptr, 0x00, buf_info->size);
1720         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1721
1722         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1723                          _tbm_surface_internal_get_time(),
1724                          g_dump_info->count++, type, dump_postfix[0]);
1725         memcpy(bo_handle.ptr, ptr, stride * h);
1726
1727         tbm_bo_unmap(buf_info->bo);
1728
1729         buf_info->dirty = 0;
1730         buf_info->dirty_shm = 1;
1731         buf_info->shm_stride = stride;
1732         buf_info->shm_h = h;
1733
1734         if (g_dump_info->count == 1000)
1735                 g_dump_info->count = 0;
1736
1737         g_dump_info->link = next_link;
1738
1739         TBM_LOG_I("Dump %s \n", buf_info->name);
1740 }
1741
1742 void tbm_surface_internal_dump_all(char *path)
1743 {
1744         TBM_RETURN_IF_FAIL(path != NULL);
1745         int w = 0, h = 0, count = 0;
1746         tbm_surface_h surface = NULL, tmp = NULL;
1747
1748         count = _tbm_surface_get_max_size(&w, &h);
1749         if (count == 0) {
1750                 TBM_LOG_I("No tbm_surface.\n");
1751                 return;
1752         }
1753
1754         tbm_surface_internal_dump_start(path, w, h, count);
1755
1756         LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &g_surface_bufmgr->surf_list, item_link) {
1757                 tbm_surface_internal_dump_buffer(surface, "dump_all");
1758         }
1759
1760         tbm_surface_internal_dump_end();
1761 }
1762 /*LCOV_EXCL_STOP*/