add scale factor to tbm_bufmgr_debug_dump_all() and tbm_bufmgr_debug_queue_dump(...
[platform/core/uifw/libtbm.git] / src / tbm_surface_internal.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #include "config.h"
33
34 #include <stdio.h>
35 #include <time.h>
36 #include <sys/time.h>
37 #include "tbm_bufmgr.h"
38 #include "tbm_bufmgr_int.h"
39 #include "tbm_surface_internal.h"
40 #include "list.h"
41 #include <png.h>
42 #include <pixman.h>
43
44 static tbm_bufmgr g_surface_bufmgr;
45 static pthread_mutex_t tbm_surface_lock;
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_LOG_E("'%s' failed.\n", #cond);\
58                 _tbm_surface_mutex_unlock();\
59                 return;\
60         } \
61 }
62
63 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
64         if (!(cond)) {\
65                 TBM_LOG_E("'%s' failed.\n", #cond);\
66                 _tbm_surface_mutex_unlock();\
67                 return val;\
68         } \
69 }
70
71 /* LCOV_EXCL_START */
72 static double
73 _tbm_surface_internal_get_time(void)
74 {
75         struct timespec tp;
76         unsigned int time;
77
78         clock_gettime(CLOCK_MONOTONIC, &tp);
79         time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
80
81         return time / 1000.0;
82 }
83
84 static void
85 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
86 {
87         LIST_DEL(&debug_data->item_link);
88
89         if (debug_data->key) free(debug_data->key);
90         if (debug_data->value) free(debug_data->value);
91         free(debug_data);
92 }
93
94 char *
95 _tbm_surface_internal_format_to_str(tbm_format format)
96 {
97         switch (format) {
98         case TBM_FORMAT_C8:
99                 return "TBM_FORMAT_C8";
100         case TBM_FORMAT_RGB332:
101                 return "TBM_FORMAT_RGB332";
102         case TBM_FORMAT_BGR233:
103                 return "TBM_FORMAT_BGR233";
104         case TBM_FORMAT_XRGB4444:
105                 return "TBM_FORMAT_XRGB4444";
106         case TBM_FORMAT_XBGR4444:
107                 return "TBM_FORMAT_XBGR4444";
108         case TBM_FORMAT_RGBX4444:
109                 return "TBM_FORMAT_RGBX4444";
110         case TBM_FORMAT_BGRX4444:
111                 return "TBM_FORMAT_BGRX4444";
112         case TBM_FORMAT_ARGB4444:
113                 return "TBM_FORMAT_ARGB4444";
114         case TBM_FORMAT_ABGR4444:
115                 return "TBM_FORMAT_ABGR4444";
116         case TBM_FORMAT_RGBA4444:
117                 return "TBM_FORMAT_RGBA4444";
118         case TBM_FORMAT_BGRA4444:
119                 return "TBM_FORMAT_BGRA4444";
120         case TBM_FORMAT_XRGB1555:
121                 return "TBM_FORMAT_XRGB1555";
122         case TBM_FORMAT_XBGR1555:
123                 return "TBM_FORMAT_XBGR1555";
124         case TBM_FORMAT_RGBX5551:
125                 return "TBM_FORMAT_RGBX5551";
126         case TBM_FORMAT_BGRX5551:
127                 return "TBM_FORMAT_BGRX5551";
128         case TBM_FORMAT_ARGB1555:
129                 return "TBM_FORMAT_ARGB1555";
130         case TBM_FORMAT_ABGR1555:
131                 return "TBM_FORMAT_ABGR1555";
132         case TBM_FORMAT_RGBA5551:
133                 return "TBM_FORMAT_RGBA5551";
134         case TBM_FORMAT_BGRA5551:
135                 return "TBM_FORMAT_BGRA5551";
136         case TBM_FORMAT_RGB565:
137                 return "TBM_FORMAT_RGB565";
138         case TBM_FORMAT_BGR565:
139                 return "TBM_FORMAT_BGR565";
140         case TBM_FORMAT_RGB888:
141                 return "TBM_FORMAT_RGB888";
142         case TBM_FORMAT_BGR888:
143                 return "TBM_FORMAT_BGR888";
144         case TBM_FORMAT_XRGB8888:
145                 return "TBM_FORMAT_XRGB8888";
146         case TBM_FORMAT_XBGR8888:
147                 return "TBM_FORMAT_XBGR8888";
148         case TBM_FORMAT_RGBX8888:
149                 return "TBM_FORMAT_RGBX8888";
150         case TBM_FORMAT_BGRX8888:
151                 return "TBM_FORMAT_BGRX8888";
152         case TBM_FORMAT_ARGB8888:
153                 return "TBM_FORMAT_ARGB8888";
154         case TBM_FORMAT_ABGR8888:
155                 return "TBM_FORMAT_ABGR8888";
156         case TBM_FORMAT_RGBA8888:
157                 return "TBM_FORMAT_RGBA8888";
158         case TBM_FORMAT_BGRA8888:
159                 return "TBM_FORMAT_BGRA8888";
160         case TBM_FORMAT_XRGB2101010:
161                 return "TBM_FORMAT_XRGB2101010";
162         case TBM_FORMAT_XBGR2101010:
163                 return "TBM_FORMAT_XBGR2101010";
164         case TBM_FORMAT_RGBX1010102:
165                 return "TBM_FORMAT_RGBX1010102";
166         case TBM_FORMAT_BGRX1010102:
167                 return "TBM_FORMAT_BGRX1010102";
168         case TBM_FORMAT_ARGB2101010:
169                 return "TBM_FORMAT_ARGB2101010";
170         case TBM_FORMAT_ABGR2101010:
171                 return "TBM_FORMAT_ABGR2101010";
172         case TBM_FORMAT_RGBA1010102:
173                 return "TBM_FORMAT_RGBA1010102";
174         case TBM_FORMAT_BGRA1010102:
175                 return "TBM_FORMAT_BGRA1010102";
176         case TBM_FORMAT_YUYV:
177                 return "TBM_FORMAT_YUYV";
178         case TBM_FORMAT_YVYU:
179                 return "TBM_FORMAT_YVYU";
180         case TBM_FORMAT_UYVY:
181                 return "TBM_FORMAT_UYVY";
182         case TBM_FORMAT_VYUY:
183                 return "TBM_FORMAT_VYUY";
184         case TBM_FORMAT_AYUV:
185                 return "TBM_FORMAT_AYUV";
186         case TBM_FORMAT_NV12:
187                 return "TBM_FORMAT_NV12";
188         case TBM_FORMAT_NV21:
189                 return "TBM_FORMAT_NV21";
190         case TBM_FORMAT_NV16:
191                 return "TBM_FORMAT_NV16";
192         case TBM_FORMAT_NV61:
193                 return "TBM_FORMAT_NV61";
194         case TBM_FORMAT_YUV410:
195                 return "TBM_FORMAT_YUV410";
196         case TBM_FORMAT_YVU410:
197                 return "TBM_FORMAT_YVU410";
198         case TBM_FORMAT_YUV411:
199                 return "TBM_FORMAT_YUV411";
200         case TBM_FORMAT_YVU411:
201                 return "TBM_FORMAT_YVU411";
202         case TBM_FORMAT_YUV420:
203                 return "TBM_FORMAT_YUV420";
204         case TBM_FORMAT_YVU420:
205                 return "TBM_FORMAT_YVU420";
206         case TBM_FORMAT_YUV422:
207                 return "TBM_FORMAT_YUV422";
208         case TBM_FORMAT_YVU422:
209                 return "TBM_FORMAT_YVU422";
210         case TBM_FORMAT_YUV444:
211                 return "TBM_FORMAT_YUV444";
212         case TBM_FORMAT_YVU444:
213                 return "TBM_FORMAT_YVU444";
214         case TBM_FORMAT_NV12MT:
215                 return "TBM_FORMAT_NV12MT";
216         default:
217                 return "unknwon";
218         }
219 }
220
221 static bool
222 _tbm_surface_mutex_init(void)
223 {
224         static bool tbm_surface_mutex_init = false;
225
226         if (tbm_surface_mutex_init)
227                 return true;
228
229         if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
230                 TBM_LOG_E("fail: pthread_mutex_init for tbm_surface_lock.\n");
231                 return false;
232         }
233
234         tbm_surface_mutex_init = true;
235
236         return true;
237 }
238
239 void
240 _tbm_surface_mutex_lock(void)
241 {
242         if (!_tbm_surface_mutex_init()) {
243                 TBM_LOG_E("fail: _tbm_surface_mutex_init.\n");
244                 return;
245         }
246
247         pthread_mutex_lock(&tbm_surface_lock);
248 }
249
250 void
251 _tbm_surface_mutex_unlock(void)
252 {
253         pthread_mutex_unlock(&tbm_surface_lock);
254 }
255
256 static void
257 _init_surface_bufmgr(void)
258 {
259         g_surface_bufmgr = tbm_bufmgr_init(-1);
260 }
261
262 static void
263 _deinit_surface_bufmgr(void)
264 {
265         if (!g_surface_bufmgr)
266                 return;
267
268         tbm_bufmgr_deinit(g_surface_bufmgr);
269         g_surface_bufmgr = NULL;
270 }
271 /* LCOV_EXCL_STOP */
272
273 static int
274 _tbm_surface_internal_is_valid(tbm_surface_h surface)
275 {
276         tbm_surface_h old_data = NULL;
277
278         TBM_RETURN_VAL_IF_FAIL(g_surface_bufmgr, 0);
279         TBM_RETURN_VAL_IF_FAIL(surface, 0);
280
281         if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
282                 LIST_FOR_EACH_ENTRY(old_data, &g_surface_bufmgr->surf_list, item_link) {
283                         if (old_data == surface) {
284                                 TBM_TRACE("tbm_surface(%p)\n", surface);
285                                 return 1;
286                         }
287                 }
288         }
289
290         TBM_LOG_E("error: No valid tbm_surface(%p)\n", surface);
291
292         return 0;
293 }
294
295 static int
296 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
297                                        int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
298 {
299         TBM_RETURN_VAL_IF_FAIL(surface, 0);
300         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
301
302         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
303         struct _tbm_bufmgr *mgr = surf->bufmgr;
304         int ret = 0;
305
306         TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
307         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
308         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
309         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
310
311         if (!mgr->backend->surface_get_plane_data)
312                 return 0;
313
314         ret = mgr->backend->surface_get_plane_data(surf->info.width,
315                         surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
316         if (!ret) {
317                 /* LCOV_EXCL_START */
318                 TBM_LOG_E("Fail to surface_get_plane_data. surface(%p)\n", surface);
319                 return 0;
320                 /* LCOV_EXCL_STOP */
321         }
322
323         return 1;
324 }
325
326 static void
327 _tbm_surface_internal_destroy(tbm_surface_h surface)
328 {
329         int i;
330         tbm_bufmgr bufmgr = surface->bufmgr;
331         tbm_user_data *old_data = NULL, *tmp = NULL;
332         tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
333
334         /* destory the user_data_list */
335         if (!LIST_IS_EMPTY(&surface->user_data_list)) {
336                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
337                         TBM_DBG("free user_data\n");
338                         user_data_delete(old_data);
339                 }
340         }
341
342         for (i = 0; i < surface->num_bos; i++) {
343                 surface->bos[i]->surface = NULL;
344
345                 tbm_bo_unref(surface->bos[i]);
346                 surface->bos[i] = NULL;
347         }
348
349         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
350                 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
351                         _tbm_surface_internal_debug_data_delete(debug_old_data);
352         }
353
354         LIST_DEL(&surface->item_link);
355
356         free(surface);
357         surface = NULL;
358
359         if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
360                 LIST_DELINIT(&bufmgr->surf_list);
361
362                 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
363                         LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
364                                 _tbm_surface_internal_debug_data_delete(debug_old_data);
365                         }
366                 }
367
368                 _deinit_surface_bufmgr();
369         }
370 }
371
372 int
373 tbm_surface_internal_is_valid(tbm_surface_h surface)
374 {
375         int ret = 0;
376
377         _tbm_surface_mutex_lock();
378
379         /* Return silently if surface is null. */
380         if (!surface) {
381                 _tbm_surface_mutex_unlock();
382                 return 0;
383         }
384
385         ret = _tbm_surface_internal_is_valid(surface);
386
387         _tbm_surface_mutex_unlock();
388
389         return ret;
390 }
391
392 int
393 tbm_surface_internal_query_supported_formats(uint32_t **formats,
394                 uint32_t *num)
395 {
396         struct _tbm_bufmgr *mgr;
397         int ret = 0;
398         bool bufmgr_initialized = false;
399
400         _tbm_surface_mutex_lock();
401
402         if (!g_surface_bufmgr) {
403                 _init_surface_bufmgr();
404                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
405                 bufmgr_initialized = true;
406         }
407
408         mgr = g_surface_bufmgr;
409
410         if (!mgr->backend->surface_supported_format)
411                 goto fail;
412
413         ret = mgr->backend->surface_supported_format(formats, num);
414         if (!ret)  {
415                 /* LCOV_EXCL_START */
416                 TBM_LOG_E("Fail to surface_supported_format.\n");
417                 goto fail;
418                 /* LCOV_EXCL_START */
419         }
420
421         TBM_TRACE("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
422
423         _tbm_surface_mutex_unlock();
424
425         return ret;
426
427 /* LCOV_EXCL_START */
428 fail:
429         if (bufmgr_initialized) {
430                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
431                 _deinit_surface_bufmgr();
432         }
433         _tbm_surface_mutex_unlock();
434
435         TBM_LOG_E("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
436
437         return 0;
438 /* LCOV_EXCL_STOP */
439 }
440
441 int
442 tbm_surface_internal_get_num_planes(tbm_format format)
443 {
444         int num_planes = 0;
445
446         switch (format) {
447         case TBM_FORMAT_C8:
448         case TBM_FORMAT_RGB332:
449         case TBM_FORMAT_BGR233:
450         case TBM_FORMAT_XRGB4444:
451         case TBM_FORMAT_XBGR4444:
452         case TBM_FORMAT_RGBX4444:
453         case TBM_FORMAT_BGRX4444:
454         case TBM_FORMAT_ARGB4444:
455         case TBM_FORMAT_ABGR4444:
456         case TBM_FORMAT_RGBA4444:
457         case TBM_FORMAT_BGRA4444:
458         case TBM_FORMAT_XRGB1555:
459         case TBM_FORMAT_XBGR1555:
460         case TBM_FORMAT_RGBX5551:
461         case TBM_FORMAT_BGRX5551:
462         case TBM_FORMAT_ARGB1555:
463         case TBM_FORMAT_ABGR1555:
464         case TBM_FORMAT_RGBA5551:
465         case TBM_FORMAT_BGRA5551:
466         case TBM_FORMAT_RGB565:
467         case TBM_FORMAT_BGR565:
468         case TBM_FORMAT_RGB888:
469         case TBM_FORMAT_BGR888:
470         case TBM_FORMAT_XRGB8888:
471         case TBM_FORMAT_XBGR8888:
472         case TBM_FORMAT_RGBX8888:
473         case TBM_FORMAT_BGRX8888:
474         case TBM_FORMAT_ARGB8888:
475         case TBM_FORMAT_ABGR8888:
476         case TBM_FORMAT_RGBA8888:
477         case TBM_FORMAT_BGRA8888:
478         case TBM_FORMAT_XRGB2101010:
479         case TBM_FORMAT_XBGR2101010:
480         case TBM_FORMAT_RGBX1010102:
481         case TBM_FORMAT_BGRX1010102:
482         case TBM_FORMAT_ARGB2101010:
483         case TBM_FORMAT_ABGR2101010:
484         case TBM_FORMAT_RGBA1010102:
485         case TBM_FORMAT_BGRA1010102:
486         case TBM_FORMAT_YUYV:
487         case TBM_FORMAT_YVYU:
488         case TBM_FORMAT_UYVY:
489         case TBM_FORMAT_VYUY:
490         case TBM_FORMAT_AYUV:
491                 num_planes = 1;
492                 break;
493         case TBM_FORMAT_NV12:
494         case TBM_FORMAT_NV12MT:
495         case TBM_FORMAT_NV21:
496         case TBM_FORMAT_NV16:
497         case TBM_FORMAT_NV61:
498                 num_planes = 2;
499                 break;
500         case TBM_FORMAT_YUV410:
501         case TBM_FORMAT_YVU410:
502         case TBM_FORMAT_YUV411:
503         case TBM_FORMAT_YVU411:
504         case TBM_FORMAT_YUV420:
505         case TBM_FORMAT_YVU420:
506         case TBM_FORMAT_YUV422:
507         case TBM_FORMAT_YVU422:
508         case TBM_FORMAT_YUV444:
509         case TBM_FORMAT_YVU444:
510                 num_planes = 3;
511                 break;
512
513         default:
514                 break;
515         }
516
517         TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
518
519         return num_planes;
520 }
521
522 int
523 tbm_surface_internal_get_bpp(tbm_format format)
524 {
525
526         int bpp = 0;
527
528         switch (format) {
529         case TBM_FORMAT_C8:
530         case TBM_FORMAT_RGB332:
531         case TBM_FORMAT_BGR233:
532                 bpp = 8;
533                 break;
534         case TBM_FORMAT_XRGB4444:
535         case TBM_FORMAT_XBGR4444:
536         case TBM_FORMAT_RGBX4444:
537         case TBM_FORMAT_BGRX4444:
538         case TBM_FORMAT_ARGB4444:
539         case TBM_FORMAT_ABGR4444:
540         case TBM_FORMAT_RGBA4444:
541         case TBM_FORMAT_BGRA4444:
542         case TBM_FORMAT_XRGB1555:
543         case TBM_FORMAT_XBGR1555:
544         case TBM_FORMAT_RGBX5551:
545         case TBM_FORMAT_BGRX5551:
546         case TBM_FORMAT_ARGB1555:
547         case TBM_FORMAT_ABGR1555:
548         case TBM_FORMAT_RGBA5551:
549         case TBM_FORMAT_BGRA5551:
550         case TBM_FORMAT_RGB565:
551         case TBM_FORMAT_BGR565:
552                 bpp = 16;
553                 break;
554         case TBM_FORMAT_RGB888:
555         case TBM_FORMAT_BGR888:
556                 bpp = 24;
557                 break;
558         case TBM_FORMAT_XRGB8888:
559         case TBM_FORMAT_XBGR8888:
560         case TBM_FORMAT_RGBX8888:
561         case TBM_FORMAT_BGRX8888:
562         case TBM_FORMAT_ARGB8888:
563         case TBM_FORMAT_ABGR8888:
564         case TBM_FORMAT_RGBA8888:
565         case TBM_FORMAT_BGRA8888:
566         case TBM_FORMAT_XRGB2101010:
567         case TBM_FORMAT_XBGR2101010:
568         case TBM_FORMAT_RGBX1010102:
569         case TBM_FORMAT_BGRX1010102:
570         case TBM_FORMAT_ARGB2101010:
571         case TBM_FORMAT_ABGR2101010:
572         case TBM_FORMAT_RGBA1010102:
573         case TBM_FORMAT_BGRA1010102:
574         case TBM_FORMAT_YUYV:
575         case TBM_FORMAT_YVYU:
576         case TBM_FORMAT_UYVY:
577         case TBM_FORMAT_VYUY:
578         case TBM_FORMAT_AYUV:
579                 bpp = 32;
580                 break;
581         case TBM_FORMAT_NV12:
582         case TBM_FORMAT_NV12MT:
583         case TBM_FORMAT_NV21:
584                 bpp = 12;
585                 break;
586         case TBM_FORMAT_NV16:
587         case TBM_FORMAT_NV61:
588                 bpp = 16;
589                 break;
590         case TBM_FORMAT_YUV410:
591         case TBM_FORMAT_YVU410:
592                 bpp = 9;
593                 break;
594         case TBM_FORMAT_YUV411:
595         case TBM_FORMAT_YVU411:
596         case TBM_FORMAT_YUV420:
597         case TBM_FORMAT_YVU420:
598                 bpp = 12;
599                 break;
600         case TBM_FORMAT_YUV422:
601         case TBM_FORMAT_YVU422:
602                 bpp = 16;
603                 break;
604         case TBM_FORMAT_YUV444:
605         case TBM_FORMAT_YVU444:
606                 bpp = 24;
607                 break;
608         default:
609                 break;
610         }
611
612         TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
613
614         return bpp;
615 }
616
617 tbm_surface_h
618 tbm_surface_internal_create_with_flags(int width, int height,
619                                        int format, int flags)
620 {
621         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
622         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
623
624         struct _tbm_bufmgr *mgr;
625         struct _tbm_surface *surf = NULL;
626         uint32_t size = 0;
627         uint32_t offset = 0;
628         uint32_t stride = 0;
629         uint32_t bo_size = 0;
630         int bo_idx;
631         int i, j;
632         bool bufmgr_initialized = false;
633
634         _tbm_surface_mutex_lock();
635
636         if (!g_surface_bufmgr) {
637                 _init_surface_bufmgr();
638                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
639                 bufmgr_initialized = true;
640         }
641
642         mgr = g_surface_bufmgr;
643         if (!TBM_BUFMGR_IS_VALID(mgr)) {
644                 TBM_LOG_E("The bufmgr is invalid\n");
645                 goto check_valid_fail;
646         }
647
648         surf = calloc(1, sizeof(struct _tbm_surface));
649         if (!surf) {
650                 /* LCOV_EXCL_START */
651                 TBM_LOG_E("fail to alloc surf\n");
652                 goto alloc_surf_fail;
653                 /* LCOV_EXCL_STOP */
654         }
655
656         surf->bufmgr = mgr;
657         surf->info.width = width;
658         surf->info.height = height;
659         surf->info.format = format;
660         surf->info.bpp = tbm_surface_internal_get_bpp(format);
661         surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
662         surf->refcnt = 1;
663
664         /* get size, stride and offset bo_idx */
665         for (i = 0; i < surf->info.num_planes; i++) {
666                 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
667                                                 &offset, &stride, &bo_idx)) {
668                         TBM_LOG_E("fail to query plane data\n");
669                         goto query_plane_data_fail;
670                 }
671
672                 surf->info.planes[i].size = size;
673                 surf->info.planes[i].offset = offset;
674                 surf->info.planes[i].stride = stride;
675                 surf->planes_bo_idx[i] = bo_idx;
676         }
677
678         surf->num_bos = 1;
679
680         for (i = 0; i < surf->info.num_planes; i++) {
681                 surf->info.size += surf->info.planes[i].size;
682
683                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
684                         surf->num_bos = surf->planes_bo_idx[i] + 1;
685         }
686
687         surf->flags = flags;
688
689         for (i = 0; i < surf->num_bos; i++) {
690                 bo_size = 0;
691                 for (j = 0; j < surf->info.num_planes; j++) {
692                         if (surf->planes_bo_idx[j] == i)
693                                 bo_size += surf->info.planes[j].size;
694                 }
695
696                 if (mgr->backend->surface_bo_alloc) {
697                         /* LCOV_EXCL_START */
698                         tbm_bo bo = NULL;
699                         void *bo_priv = NULL;
700
701                         bo = calloc(1, sizeof(struct _tbm_bo));
702                         if (!bo) {
703                                 TBM_LOG_E("fail to alloc bo struct\n");
704                                 goto alloc_bo_fail;
705                         }
706
707                         bo->bufmgr = surf->bufmgr;
708
709                         pthread_mutex_lock(&surf->bufmgr->lock);
710
711                         bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
712                         if (!bo_priv) {
713                                 TBM_LOG_E("fail to alloc bo priv\n");
714                                 free(bo);
715                                 pthread_mutex_unlock(&surf->bufmgr->lock);
716                                 goto alloc_bo_fail;
717                         }
718
719                         bo->ref_cnt = 1;
720                         bo->flags = flags;
721                         bo->priv = bo_priv;
722
723                         LIST_INITHEAD(&bo->user_data_list);
724
725                         LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
726
727                         pthread_mutex_unlock(&surf->bufmgr->lock);
728
729                         surf->bos[i] = bo;
730                         /* LCOV_EXCL_STOP */
731                 } else {
732                         surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
733                         if (!surf->bos[i]) {
734                                 TBM_LOG_E("fail to alloc bo idx:%d\n", i);
735                                 goto alloc_bo_fail;
736                         }
737                 }
738
739                 _tbm_bo_set_surface(surf->bos[i], surf);
740         }
741
742         TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
743                         _tbm_surface_internal_format_to_str(format), flags, surf);
744
745         LIST_INITHEAD(&surf->user_data_list);
746         LIST_INITHEAD(&surf->debug_data_list);
747
748         LIST_ADD(&surf->item_link, &mgr->surf_list);
749
750         _tbm_surface_mutex_unlock();
751
752         return surf;
753
754 /* LCOV_EXCL_START */
755 alloc_bo_fail:
756         for (j = 0; j < i; j++) {
757                 if (surf->bos[j])
758                         tbm_bo_unref(surf->bos[j]);
759         }
760 query_plane_data_fail:
761         free(surf);
762 alloc_surf_fail:
763 check_valid_fail:
764         if (bufmgr_initialized && mgr) {
765                 LIST_DELINIT(&mgr->surf_list);
766                 _deinit_surface_bufmgr();
767         }
768         _tbm_surface_mutex_unlock();
769
770         TBM_LOG_E("error: width(%d) height(%d) format(%s) flags(%d)\n",
771                         width, height,
772                         _tbm_surface_internal_format_to_str(format), flags);
773 /* LCOV_EXCL_STOP */
774
775         return NULL;
776 }
777
778 tbm_surface_h
779 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
780                                      tbm_bo *bos, int num)
781 {
782         TBM_RETURN_VAL_IF_FAIL(bos, NULL);
783         TBM_RETURN_VAL_IF_FAIL(info, NULL);
784         TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
785
786         struct _tbm_bufmgr *mgr;
787         struct _tbm_surface *surf = NULL;
788         int i;
789         bool bufmgr_initialized = false;
790
791         _tbm_surface_mutex_lock();
792
793         if (!g_surface_bufmgr) {
794                 _init_surface_bufmgr();
795                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
796                 bufmgr_initialized = true;
797         }
798
799         mgr = g_surface_bufmgr;
800         if (!TBM_BUFMGR_IS_VALID(mgr)) {
801                 TBM_LOG_E("fail to validate the Bufmgr.\n");
802                 goto check_valid_fail;
803         }
804
805         surf = calloc(1, sizeof(struct _tbm_surface));
806         if (!surf) {
807                 /* LCOV_EXCL_START */
808                 TBM_LOG_E("fail to allocate struct _tbm_surface.\n");
809                 goto alloc_surf_fail;
810                 /* LCOV_EXCL_STOP */
811         }
812
813         surf->bufmgr = mgr;
814         surf->info.width = info->width;
815         surf->info.height = info->height;
816         surf->info.format = info->format;
817         if (info->bpp > 0)
818                 surf->info.bpp = info->bpp;
819         else
820                 surf->info.bpp = tbm_surface_internal_get_bpp(info->format);
821         surf->info.num_planes = info->num_planes;
822         surf->refcnt = 1;
823
824         /* get size, stride and offset */
825         for (i = 0; i < info->num_planes; i++) {
826                 surf->info.planes[i].offset = info->planes[i].offset;
827                 surf->info.planes[i].stride = info->planes[i].stride;
828
829                 if (info->planes[i].size > 0)
830                         surf->info.planes[i].size = info->planes[i].size;
831                 else {
832                         uint32_t size = 0, offset = 0, stride = 0;
833                         int32_t bo_idx = 0;
834
835                         _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx);
836                         surf->info.planes[i].size = size;
837                 }
838
839                 if (num == 1)
840                         surf->planes_bo_idx[i] = 0;
841                 else
842                         surf->planes_bo_idx[i] = i;
843         }
844
845         if (info->size > 0) {
846                 surf->info.size = info->size;
847         } else {
848                 surf->info.size = 0;
849                 for (i = 0; i < info->num_planes; i++)
850                         surf->info.size += surf->info.planes[i].size;
851         }
852
853         surf->flags = TBM_BO_DEFAULT;
854
855         /* create only one bo */
856         surf->num_bos = num;
857         for (i = 0; i < num; i++) {
858                 if (bos[i] == NULL) {
859                         TBM_LOG_E("bos[%d] is null.\n", i);
860                         goto check_bo_fail;
861                 }
862
863                 surf->bos[i] = tbm_bo_ref(bos[i]);
864                 _tbm_bo_set_surface(bos[i], surf);
865         }
866
867         TBM_TRACE("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
868                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
869
870         LIST_INITHEAD(&surf->user_data_list);
871         LIST_INITHEAD(&surf->debug_data_list);
872
873         LIST_ADD(&surf->item_link, &mgr->surf_list);
874
875         _tbm_surface_mutex_unlock();
876
877         return surf;
878
879 /* LCOV_EXCL_START */
880 check_bo_fail:
881         for (i = 0; i < num; i++) {
882                 if (surf->bos[i])
883                         tbm_bo_unref(surf->bos[i]);
884         }
885         free(surf);
886 alloc_surf_fail:
887 check_valid_fail:
888         if (bufmgr_initialized && mgr) {
889                 LIST_DELINIT(&mgr->surf_list);
890                 _deinit_surface_bufmgr();
891         }
892         _tbm_surface_mutex_unlock();
893
894         TBM_LOG_E("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
895                         info->width, info->height,
896                         _tbm_surface_internal_format_to_str(info->format), num);
897 /* LCOV_EXCL_STOP */
898
899         return NULL;
900 }
901
902 void
903 tbm_surface_internal_destroy(tbm_surface_h surface)
904 {
905         _tbm_surface_mutex_lock();
906
907         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
908
909         surface->refcnt--;
910
911         if (surface->refcnt > 0) {
912                 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
913                 _tbm_surface_mutex_unlock();
914                 return;
915         }
916
917         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
918
919         if (surface->refcnt == 0)
920                 _tbm_surface_internal_destroy(surface);
921
922         _tbm_surface_mutex_unlock();
923 }
924
925 void
926 tbm_surface_internal_ref(tbm_surface_h surface)
927 {
928         _tbm_surface_mutex_lock();
929
930         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
931
932         surface->refcnt++;
933
934         TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
935
936         _tbm_surface_mutex_unlock();
937 }
938
939 void
940 tbm_surface_internal_unref(tbm_surface_h surface)
941 {
942         _tbm_surface_mutex_lock();
943
944         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
945
946         surface->refcnt--;
947
948         if (surface->refcnt > 0) {
949                 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
950                 _tbm_surface_mutex_unlock();
951                 return;
952         }
953
954         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
955
956         if (surface->refcnt == 0)
957                 _tbm_surface_internal_destroy(surface);
958
959         _tbm_surface_mutex_unlock();
960 }
961
962 int
963 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
964 {
965         struct _tbm_surface *surf;
966         int num;
967
968         _tbm_surface_mutex_lock();
969
970         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
971
972         surf = (struct _tbm_surface *)surface;
973         num = surf->num_bos;
974
975         TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
976
977         _tbm_surface_mutex_unlock();
978
979         return num;
980 }
981
982 tbm_bo
983 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
984 {
985         struct _tbm_surface *surf;
986         tbm_bo bo;
987
988         _tbm_surface_mutex_lock();
989
990         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
991         TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
992
993         surf = (struct _tbm_surface *)surface;
994         bo = surf->bos[bo_idx];
995
996         TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
997
998         _tbm_surface_mutex_unlock();
999
1000         return bo;
1001 }
1002
1003 unsigned int
1004 tbm_surface_internal_get_size(tbm_surface_h surface)
1005 {
1006         struct _tbm_surface *surf;
1007         unsigned int size;
1008
1009         _tbm_surface_mutex_lock();
1010
1011         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1012
1013         surf = (struct _tbm_surface *)surface;
1014         size = surf->info.size;
1015
1016         TBM_TRACE("tbm_surface(%p) size(%u)\n", surface, size);
1017
1018         _tbm_surface_mutex_unlock();
1019
1020         return size;
1021 }
1022
1023 int
1024 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1025                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
1026 {
1027         struct _tbm_surface *surf;
1028
1029         _tbm_surface_mutex_lock();
1030
1031         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1032         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1033
1034         surf = (struct _tbm_surface *)surface;
1035
1036         if (plane_idx >= surf->info.num_planes) {
1037                 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1038                 _tbm_surface_mutex_unlock();
1039                 return 0;
1040         }
1041
1042         if (size)
1043                 *size = surf->info.planes[plane_idx].size;
1044
1045         if (offset)
1046                 *offset = surf->info.planes[plane_idx].offset;
1047
1048         if (pitch)
1049                 *pitch = surf->info.planes[plane_idx].stride;
1050
1051         TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1052                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1053                                 surf->info.planes[plane_idx].stride);
1054
1055         _tbm_surface_mutex_unlock();
1056
1057         return 1;
1058 }
1059
1060 int
1061 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1062                               tbm_surface_info_s *info, int map)
1063 {
1064         struct _tbm_surface *surf;
1065         tbm_bo_handle bo_handles[4];
1066         int i, j;
1067
1068         _tbm_surface_mutex_lock();
1069
1070         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1071
1072         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1073
1074         surf = (struct _tbm_surface *)surface;
1075
1076         memset(info, 0x00, sizeof(tbm_surface_info_s));
1077         info->width = surf->info.width;
1078         info->height = surf->info.height;
1079         info->format = surf->info.format;
1080         info->bpp = surf->info.bpp;
1081         info->size = surf->info.size;
1082         info->num_planes = surf->info.num_planes;
1083
1084         if (map == 1) {
1085                 for (i = 0; i < surf->num_bos; i++) {
1086                         _tbm_surface_mutex_unlock();
1087                         bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1088                         _tbm_surface_mutex_lock();
1089                         if (bo_handles[i].ptr == NULL) {
1090                                 for (j = 0; j < i; j++)
1091                                         tbm_bo_unmap(surf->bos[j]);
1092
1093                                 TBM_LOG_E("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1094                                 _tbm_surface_mutex_unlock();
1095                                 return 0;
1096                         }
1097                 }
1098         } else {
1099                 for (i = 0; i < surf->num_bos; i++) {
1100                         bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1101                         if (bo_handles[i].ptr == NULL) {
1102                                 TBM_LOG_E("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1103                                 _tbm_surface_mutex_unlock();
1104                                 return 0;
1105                         }
1106                 }
1107         }
1108
1109         for (i = 0; i < surf->info.num_planes; i++) {
1110                 info->planes[i].size = surf->info.planes[i].size;
1111                 info->planes[i].offset = surf->info.planes[i].offset;
1112                 info->planes[i].stride = surf->info.planes[i].stride;
1113
1114                 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1115                         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1116                                               surf->info.planes[i].offset;
1117         }
1118
1119         TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1120
1121         _tbm_surface_mutex_unlock();
1122
1123         return 1;
1124 }
1125
1126 void
1127 tbm_surface_internal_unmap(tbm_surface_h surface)
1128 {
1129         struct _tbm_surface *surf;
1130         int i;
1131
1132         _tbm_surface_mutex_lock();
1133
1134         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1135
1136         surf = (struct _tbm_surface *)surface;
1137
1138         for (i = 0; i < surf->num_bos; i++)
1139                 tbm_bo_unmap(surf->bos[i]);
1140
1141         TBM_TRACE("tbm_surface(%p)\n", surface);
1142
1143         _tbm_surface_mutex_unlock();
1144 }
1145
1146 unsigned int
1147 tbm_surface_internal_get_width(tbm_surface_h surface)
1148 {
1149         struct _tbm_surface *surf;
1150         unsigned int width;
1151
1152         _tbm_surface_mutex_lock();
1153
1154         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1155
1156         surf = (struct _tbm_surface *)surface;
1157         width = surf->info.width;
1158
1159         TBM_TRACE("tbm_surface(%p) width(%u)\n", surface, width);
1160
1161         _tbm_surface_mutex_unlock();
1162
1163         return width;
1164 }
1165
1166 unsigned int
1167 tbm_surface_internal_get_height(tbm_surface_h surface)
1168 {
1169         struct _tbm_surface *surf;
1170         unsigned int height;
1171
1172         _tbm_surface_mutex_lock();
1173
1174         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1175
1176         surf = (struct _tbm_surface *)surface;
1177         height = surf->info.height;
1178
1179         TBM_TRACE("tbm_surface(%p) height(%u)\n", surface, height);
1180
1181         _tbm_surface_mutex_unlock();
1182
1183         return height;
1184
1185 }
1186
1187 tbm_format
1188 tbm_surface_internal_get_format(tbm_surface_h surface)
1189 {
1190         struct _tbm_surface *surf;
1191         tbm_format format;
1192
1193         _tbm_surface_mutex_lock();
1194
1195         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1196
1197         surf = (struct _tbm_surface *)surface;
1198         format = surf->info.format;
1199
1200         TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1201
1202         _tbm_surface_mutex_unlock();
1203
1204         return format;
1205 }
1206
1207 int
1208 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1209 {
1210         struct _tbm_surface *surf;
1211         int bo_idx;
1212
1213         _tbm_surface_mutex_lock();
1214
1215         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1216         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1217
1218         surf = (struct _tbm_surface *)surface;
1219         bo_idx = surf->planes_bo_idx[plane_idx];
1220
1221         TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1222
1223         _tbm_surface_mutex_unlock();
1224
1225         return bo_idx;
1226 }
1227
1228 int
1229 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1230                                    tbm_data_free data_free_func)
1231 {
1232         tbm_user_data *data;
1233
1234         _tbm_surface_mutex_lock();
1235
1236         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1237
1238         /* check if the data according to the key exist if so, return false. */
1239         data = user_data_lookup(&surface->user_data_list, key);
1240         if (data) {
1241                 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1242                 _tbm_surface_mutex_unlock();
1243                 return 0;
1244         }
1245
1246         data = user_data_create(key, data_free_func);
1247         if (!data) {
1248                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1249                 _tbm_surface_mutex_unlock();
1250                 return 0;
1251         }
1252
1253         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1254
1255         LIST_ADD(&data->item_link, &surface->user_data_list);
1256
1257         _tbm_surface_mutex_unlock();
1258
1259         return 1;
1260 }
1261
1262 int
1263 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1264                                    void *data)
1265 {
1266         tbm_user_data *old_data;
1267
1268         _tbm_surface_mutex_lock();
1269
1270         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1271
1272         old_data = user_data_lookup(&surface->user_data_list, key);
1273         if (!old_data) {
1274                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1275                 _tbm_surface_mutex_unlock();
1276                 return 0;
1277         }
1278
1279         if (old_data->data && old_data->free_func)
1280                 old_data->free_func(old_data->data);
1281
1282         old_data->data = data;
1283
1284         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1285
1286         _tbm_surface_mutex_unlock();
1287
1288         return 1;
1289 }
1290
1291 int
1292 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1293                                    void **data)
1294 {
1295         tbm_user_data *old_data;
1296
1297         _tbm_surface_mutex_lock();
1298
1299         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1300
1301         if (!data) {
1302                 TBM_LOG_E("error: tbm_surface(%p) key(%lu)\n", surface, key);
1303                 _tbm_surface_mutex_unlock();
1304                 return 0;
1305         }
1306         *data = NULL;
1307
1308         old_data = user_data_lookup(&surface->user_data_list, key);
1309         if (!old_data) {
1310                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1311                 _tbm_surface_mutex_unlock();
1312                 return 0;
1313         }
1314
1315         *data = old_data->data;
1316
1317         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1318
1319         _tbm_surface_mutex_unlock();
1320
1321         return 1;
1322 }
1323
1324 int
1325 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1326                                       unsigned long key)
1327 {
1328         tbm_user_data *old_data = (void *)0;
1329
1330         _tbm_surface_mutex_lock();
1331
1332         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1333
1334         old_data = user_data_lookup(&surface->user_data_list, key);
1335         if (!old_data) {
1336                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1337                 _tbm_surface_mutex_unlock();
1338                 return 0;
1339         }
1340
1341         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1342
1343         user_data_delete(old_data);
1344
1345         _tbm_surface_mutex_unlock();
1346
1347         return 1;
1348 }
1349
1350 /* LCOV_EXCL_START */
1351 unsigned int
1352 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1353 {
1354         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1355
1356         return surface->debug_pid;
1357 }
1358
1359 void
1360 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1361 {
1362         _tbm_surface_mutex_lock();
1363
1364         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1365
1366         surface->debug_pid = pid;
1367
1368         _tbm_surface_mutex_unlock();
1369 }
1370
1371 static tbm_surface_debug_data *
1372 _tbm_surface_internal_debug_data_create(char *key, char *value)
1373 {
1374         tbm_surface_debug_data *debug_data = NULL;
1375
1376         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1377         if (!debug_data)
1378                 return NULL;
1379
1380         if (key) debug_data->key = strdup(key);
1381         if (value) debug_data->value = strdup(value);
1382
1383         return debug_data;
1384 }
1385
1386 int
1387 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1388 {
1389         tbm_surface_debug_data *debug_data = NULL;
1390         tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1391         tbm_bufmgr bufmgr = NULL;
1392
1393         _tbm_surface_mutex_lock();
1394
1395         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1396         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1397
1398         bufmgr = surface->bufmgr;
1399
1400         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1401
1402         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1403                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1404                         if (old_data) {
1405                                 if (!strcmp(old_data->key, key)) {
1406                                         if (old_data->value && value && !strncmp(old_data->value, value, strlen(old_data->value))) {
1407                                                 TBM_TRACE("tbm_surface(%p) Already exist key(%s) and value(%s)!\n", surface, key, value);
1408                                                 goto add_debug_key_list;
1409                                         }
1410
1411                                         if (old_data->value)
1412                                                 free(old_data->value);
1413
1414                                         if (value)
1415                                                 old_data->value = strdup(value);
1416                                         else
1417                                                 old_data->value = NULL;
1418
1419                                         goto add_debug_key_list;
1420                                 }
1421                         }
1422                 }
1423         }
1424
1425         debug_data = _tbm_surface_internal_debug_data_create(key, value);
1426         if (!debug_data) {
1427                 TBM_LOG_E("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1428                 _tbm_surface_mutex_unlock();
1429                 return 0;
1430         }
1431
1432         TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1433
1434         LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1435
1436 add_debug_key_list:
1437         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1438                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1439                         if (!strcmp(old_data->key, key)) {
1440                                 _tbm_surface_mutex_unlock();
1441                                 return 1;
1442                         }
1443                 }
1444         }
1445
1446         debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1447         LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1448
1449         _tbm_surface_mutex_unlock();
1450
1451         return 1;
1452 }
1453
1454 char *
1455 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1456 {
1457         tbm_surface_debug_data *old_data = NULL;
1458
1459         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1460
1461         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1462                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1463                         if (!strcmp(old_data->key, key))
1464                                 return old_data->value;
1465                 }
1466         }
1467
1468         return NULL;
1469 }
1470
1471 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1472 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1473
1474 struct _tbm_surface_dump_buf_info {
1475         int index;
1476         tbm_bo bo;
1477         int size;
1478         int dirty;
1479         int dirty_shm;
1480         int shm_stride;
1481         int shm_h;
1482         char name[1024];
1483
1484         tbm_surface_info_s info;
1485
1486         struct list_head link;
1487 };
1488
1489 struct _tbm_surface_dump_info {
1490         char *path;  // copy???
1491         int dump_max;
1492         int count;
1493         struct list_head *link;
1494         struct list_head surface_list; /* link of surface */
1495 };
1496
1497 static tbm_surface_dump_info *g_dump_info = NULL;
1498 static const char *dump_postfix[2] = {"png", "yuv"};
1499 static double scale_factor;
1500
1501 static void
1502 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1503                                 void *data2, int size2, void *data3, int size3)
1504 {
1505         FILE *fp = fopen(file, "w+");
1506         TBM_RETURN_IF_FAIL(fp != NULL);
1507         unsigned int *blocks;
1508
1509         blocks = (unsigned int *)data1;
1510         fwrite(blocks, 1, size1, fp);
1511
1512         if (size2 > 0) {
1513                 blocks = (unsigned int *)data2;
1514                 fwrite(blocks, 1, size2, fp);
1515         }
1516
1517         if (size3 > 0) {
1518                 blocks = (unsigned int *)data3;
1519                 fwrite(blocks, 1, size3, fp);
1520         }
1521
1522         fclose(fp);
1523 }
1524
1525 static void
1526 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height)
1527 {
1528         unsigned int *blocks = (unsigned int *)data;
1529         FILE *fp = fopen(file, "wb");
1530         TBM_RETURN_IF_FAIL(fp != NULL);
1531         const int pixel_size = 4;       // RGBA
1532         png_bytep *row_pointers;
1533         int depth = 8, y;
1534
1535         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1536                                                         NULL, NULL, NULL);
1537         if (!pPngStruct) {
1538                 TBM_LOG_E("fail to create a png write structure.\n");
1539                 fclose(fp);
1540                 return;
1541         }
1542
1543         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1544         if (!pPngInfo) {
1545                 TBM_LOG_E("fail to create a png info structure.\n");
1546                 png_destroy_write_struct(&pPngStruct, NULL);
1547                 fclose(fp);
1548                 return;
1549         }
1550
1551         png_init_io(pPngStruct, fp);
1552         png_set_IHDR(pPngStruct,
1553                         pPngInfo,
1554                         width,
1555                         height,
1556                         depth,
1557                         PNG_COLOR_TYPE_RGBA,
1558                         PNG_INTERLACE_NONE,
1559                         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1560
1561         png_set_bgr(pPngStruct);
1562         png_write_info(pPngStruct, pPngInfo);
1563
1564         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1565         if (!row_pointers) {
1566                 TBM_LOG_E("fail to allocate the png row_pointers.\n");
1567                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1568                 fclose(fp);
1569                 return;
1570         }
1571
1572         for (y = 0; y < height; ++y) {
1573                 png_bytep row;
1574                 int x = 0;
1575
1576                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1577                 if (!row) {
1578                         TBM_LOG_E("fail to allocate the png row.\n");
1579                         for (x = 0; x < y; x++)
1580                                 png_free(pPngStruct, row_pointers[x]);
1581                         png_free(pPngStruct, row_pointers);
1582                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1583                         fclose(fp);
1584                         return;
1585                 }
1586                 row_pointers[y] = (png_bytep)row;
1587
1588                 for (x = 0; x < width; ++x) {
1589                         unsigned int curBlock = blocks[y * width + x];
1590
1591                         row[x * pixel_size] = (curBlock & 0xFF);
1592                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1593                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1594                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1595                 }
1596         }
1597
1598         png_write_image(pPngStruct, row_pointers);
1599         png_write_end(pPngStruct, pPngInfo);
1600
1601         for (y = 0; y < height; y++)
1602                 png_free(pPngStruct, row_pointers[y]);
1603         png_free(pPngStruct, row_pointers);
1604
1605         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1606
1607         fclose(fp);
1608 }
1609
1610 void
1611 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1612 {
1613         TBM_RETURN_IF_FAIL(path != NULL);
1614         TBM_RETURN_IF_FAIL(w > 0);
1615         TBM_RETURN_IF_FAIL(h > 0);
1616         TBM_RETURN_IF_FAIL(count > 0);
1617
1618         tbm_surface_dump_buf_info *buf_info = NULL;
1619         tbm_surface_h tbm_surface;
1620         tbm_surface_info_s info;
1621         int buffer_size, i;
1622
1623         /* check running */
1624         if (g_dump_info) {
1625                 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1626                 return;
1627         }
1628
1629         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1630         TBM_RETURN_IF_FAIL(g_dump_info);
1631
1632         LIST_INITHEAD(&g_dump_info->surface_list);
1633         g_dump_info->count = 0;
1634         g_dump_info->dump_max = count;
1635
1636         /* get buffer size */
1637         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1638         if (tbm_surface == NULL) {
1639                 TBM_LOG_E("tbm_surface_create fail\n");
1640                 free(g_dump_info);
1641                 g_dump_info = NULL;
1642                 return;
1643         }
1644
1645         if (TBM_SURFACE_ERROR_NONE != tbm_surface_map(tbm_surface,
1646                                                 TBM_SURF_OPTION_READ, &info)) {
1647                 TBM_LOG_E("tbm_surface_map fail\n");
1648                 tbm_surface_destroy(tbm_surface);
1649                 free(g_dump_info);
1650                 g_dump_info = NULL;
1651                 return;
1652         }
1653         buffer_size = info.planes[0].stride * h;
1654
1655         tbm_surface_unmap(tbm_surface);
1656         tbm_surface_destroy(tbm_surface);
1657
1658         /* create dump lists */
1659         for (i = 0; i < count; i++) {
1660                 tbm_bo bo = NULL;
1661
1662                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1663                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1664
1665                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1666                 if (bo == NULL) {
1667                         TBM_LOG_E("fail to allocate the tbm_bo[%d]\n", i);
1668                         free(buf_info);
1669                         goto fail;
1670                 }
1671
1672                 buf_info->index = i;
1673                 buf_info->bo = bo;
1674                 buf_info->size = buffer_size;
1675
1676                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1677         }
1678
1679         g_dump_info->path = path;
1680         g_dump_info->link = &g_dump_info->surface_list;
1681
1682         scale_factor = 0.0;
1683
1684         TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1685
1686         return;
1687
1688 fail:
1689         /* free resources */
1690         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1691                 tbm_surface_dump_buf_info *tmp;
1692
1693                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1694                         tbm_bo_unref(buf_info->bo);
1695                         LIST_DEL(&buf_info->link);
1696                         free(buf_info);
1697                 }
1698         }
1699
1700         TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1701
1702         free(g_dump_info);
1703         g_dump_info = NULL;
1704
1705         return;
1706 }
1707
1708 void
1709 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
1710 {
1711         if (scale > 0.0) {
1712                 w *= scale;
1713                 h *= scale;
1714         }
1715
1716         tbm_surface_internal_dump_start(path, w, h, count);
1717         scale_factor = scale;
1718 }
1719
1720 void
1721 tbm_surface_internal_dump_end(void)
1722 {
1723         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1724         tbm_bo_handle bo_handle;
1725
1726         if (!g_dump_info)
1727                 return;
1728
1729         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1730                 free(g_dump_info);
1731                 g_dump_info = NULL;
1732                 return;
1733         }
1734
1735         /* make files */
1736         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1737                 char file[2048];
1738
1739                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1740                 if (bo_handle.ptr == NULL) {
1741                         tbm_bo_unref(buf_info->bo);
1742                         LIST_DEL(&buf_info->link);
1743                         free(buf_info);
1744                         continue;
1745                 }
1746
1747                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1748                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1749
1750                 if (buf_info->dirty) {
1751                         void *ptr1 = NULL, *ptr2 = NULL;
1752
1753                         switch (buf_info->info.format) {
1754                         case TBM_FORMAT_ARGB8888:
1755                         case TBM_FORMAT_XRGB8888:
1756                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1757                                                         buf_info->info.planes[0].stride >> 2,
1758                                                         buf_info->info.height);
1759                                 break;
1760                         case TBM_FORMAT_YVU420:
1761                         case TBM_FORMAT_YUV420:
1762                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1763                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1764                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1765                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1766                                                         ptr1,
1767                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1768                                                         ptr2,
1769                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1770                                 break;
1771                         case TBM_FORMAT_NV12:
1772                         case TBM_FORMAT_NV21:
1773                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1774                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1775                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1776                                                         ptr1,
1777                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1778                                                         NULL, 0);
1779                                 break;
1780                         case TBM_FORMAT_YUYV:
1781                         case TBM_FORMAT_UYVY:
1782                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1783                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1784                                                         NULL, 0, NULL, 0);
1785                                 break;
1786                         default:
1787                                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1788                                 break;
1789                         }
1790                 } else if (buf_info->dirty_shm)
1791                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1792                                                         buf_info->shm_stride >> 2,
1793                                                         buf_info->shm_h);
1794
1795                 tbm_bo_unmap(buf_info->bo);
1796                 tbm_bo_unref(buf_info->bo);
1797                 LIST_DEL(&buf_info->link);
1798                 free(buf_info);
1799         }
1800
1801         free(g_dump_info);
1802         g_dump_info = NULL;
1803
1804         TBM_LOG_I("Dump End..\n");
1805 }
1806
1807 static pixman_format_code_t
1808 _tbm_surface_internal_pixman_format_get(tbm_format format)
1809 {
1810         switch (format) {
1811         case TBM_FORMAT_ARGB8888:
1812                 return PIXMAN_a8r8g8b8;
1813         case TBM_FORMAT_XRGB8888:
1814                 return PIXMAN_x8r8g8b8;
1815         default:
1816                 return 0;
1817         }
1818
1819         return 0;
1820 }
1821
1822 /**
1823  * This function supports only if a buffer has below formats.
1824  * - TBM_FORMAT_ARGB8888
1825  * - TBM_FORMAT_XRGB8888
1826  */
1827 static tbm_surface_error_e
1828 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
1829                                                                    int format, int src_stride, int src_w, int src_h,
1830                                                                    int dst_stride, int dst_w, int dst_h)
1831 {
1832         pixman_image_t *src_img = NULL, *dst_img = NULL;
1833         pixman_format_code_t pixman_format;
1834         pixman_transform_t t;
1835         struct pixman_f_transform ft;
1836         double scale_x, scale_y;
1837
1838         TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
1839         TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
1840
1841         pixman_format = _tbm_surface_internal_pixman_format_get(format);
1842         TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
1843
1844         /* src */
1845         src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
1846                                                                            (uint32_t*)src_ptr, src_stride);
1847         TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
1848
1849         /* dst */
1850         dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
1851                                                                            (uint32_t*)dst_ptr, dst_stride);
1852         TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
1853
1854         pixman_f_transform_init_identity(&ft);
1855
1856         scale_x = (double)src_w / dst_w;
1857         scale_y = (double)src_h / dst_h;
1858
1859         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
1860         pixman_f_transform_translate(&ft, NULL, 0, 0);
1861         pixman_transform_from_pixman_f_transform(&t, &ft);
1862         pixman_image_set_transform(src_img, &t);
1863
1864         pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
1865                                                    0, 0, 0, 0, 0, 0, dst_w, dst_h);
1866
1867         pixman_image_unref(src_img);
1868         pixman_image_unref(dst_img);
1869
1870         return TBM_SURFACE_ERROR_NONE;
1871
1872 cant_convert:
1873         if (src_img)
1874                 pixman_image_unref(src_img);
1875
1876         return TBM_SURFACE_ERROR_INVALID_OPERATION;
1877 }
1878
1879 void
1880 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1881 {
1882         TBM_RETURN_IF_FAIL(surface != NULL);
1883         TBM_RETURN_IF_FAIL(type != NULL);
1884
1885         tbm_surface_dump_buf_info *buf_info;
1886         struct list_head *next_link;
1887         tbm_surface_info_s info;
1888         tbm_bo_handle bo_handle;
1889         const char *postfix;
1890         int ret;
1891
1892         if (!g_dump_info)
1893                 return;
1894
1895         next_link = g_dump_info->link->next;
1896         TBM_RETURN_IF_FAIL(next_link != NULL);
1897
1898         if (next_link == &g_dump_info->surface_list) {
1899                 next_link = next_link->next;
1900                 TBM_RETURN_IF_FAIL(next_link != NULL);
1901         }
1902
1903         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1904         TBM_RETURN_IF_FAIL(buf_info != NULL);
1905
1906         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1907         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1908
1909         if (scale_factor > 0.0) {
1910                 const int bpp = 4;
1911
1912                 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
1913                         TBM_LOG_W("Dump with scale skip. unsupported format(%s)\n",
1914                                           _tbm_surface_internal_format_to_str(info.format));
1915                         tbm_surface_unmap(surface);
1916                         return;
1917                 }
1918
1919                 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
1920
1921                 buf_info->info.width = info.width * scale_factor;
1922                 buf_info->info.height = info.height * scale_factor;
1923                 buf_info->info.format = info.format;
1924                 buf_info->info.bpp = tbm_surface_internal_get_bpp(buf_info->info.format);
1925                 buf_info->info.num_planes = 1;
1926                 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
1927                 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
1928
1929                 if (buf_info->info.size > buf_info->size) {
1930                         TBM_LOG_W("Dump with scale skip. surface over created buffer size(%u, %d)\n",
1931                                         buf_info->info.size, buf_info->size);
1932                         tbm_surface_unmap(surface);
1933                         return;
1934                 }
1935         } else {
1936                 if (info.size > buf_info->size) {
1937                         TBM_LOG_W("Dump skip. surface over created buffer size(%u, %d)\n",
1938                                         info.size, buf_info->size);
1939                         tbm_surface_unmap(surface);
1940                         return;
1941                 }
1942
1943                 /* make the file information */
1944                 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1945         }
1946
1947         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1948                 postfix = dump_postfix[0];
1949         else
1950                 postfix = dump_postfix[1];
1951
1952         /* dump */
1953         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1954         if (!bo_handle.ptr) {
1955                 TBM_LOG_E("fail to map bo");
1956                 tbm_surface_unmap(surface);
1957                 return;
1958         }
1959         memset(bo_handle.ptr, 0x00, buf_info->size);
1960
1961         switch (info.format) {
1962         case TBM_FORMAT_ARGB8888:
1963         case TBM_FORMAT_XRGB8888:
1964                 snprintf(buf_info->name, sizeof(buf_info->name),
1965                                 "%10.3f_%03d_%p-%s.%s",
1966                                  _tbm_surface_internal_get_time(),
1967                                  g_dump_info->count++, surface, type, postfix);
1968
1969                 if (scale_factor > 0.0) {
1970                         ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
1971                                                                                                          bo_handle.ptr,
1972                                                                                                          buf_info->info.format,
1973                                                                                                          info.planes[0].stride,
1974                                                                                                          info.width, info.height,
1975                                                                                                          buf_info->info.planes[0].stride,
1976                                                                                                          buf_info->info.width,
1977                                                                                                          buf_info->info.height);
1978                         if (ret != TBM_SURFACE_ERROR_NONE) {
1979                                 TBM_LOG_E("fail to scale buffer");
1980                                 tbm_bo_unmap(buf_info->bo);
1981                                 tbm_surface_unmap(surface);
1982                                 return;
1983                         }
1984                 } else
1985                         memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1986                 break;
1987         case TBM_FORMAT_YVU420:
1988         case TBM_FORMAT_YUV420:
1989                 snprintf(buf_info->name, sizeof(buf_info->name),
1990                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1991                                  _tbm_surface_internal_get_time(),
1992                                  g_dump_info->count++, type, info.planes[0].stride,
1993                                 info.height, FOURCC_STR(info.format), postfix);
1994                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1995                 bo_handle.ptr += info.planes[0].stride * info.height;
1996                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1997                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1998                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1999                 break;
2000         case TBM_FORMAT_NV12:
2001         case TBM_FORMAT_NV21:
2002                 snprintf(buf_info->name, sizeof(buf_info->name),
2003                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
2004                                  _tbm_surface_internal_get_time(),
2005                                  g_dump_info->count++, type, info.planes[0].stride,
2006                                 info.height, FOURCC_STR(info.format), postfix);
2007                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2008                 bo_handle.ptr += info.planes[0].stride * info.height;
2009                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2010                 break;
2011         case TBM_FORMAT_YUYV:
2012         case TBM_FORMAT_UYVY:
2013                 snprintf(buf_info->name, sizeof(buf_info->name),
2014                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
2015                                  _tbm_surface_internal_get_time(),
2016                                  g_dump_info->count++, type, info.planes[0].stride,
2017                                 info.height, FOURCC_STR(info.format), postfix);
2018                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2019                 break;
2020         default:
2021                 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2022                 tbm_bo_unmap(buf_info->bo);
2023                 tbm_surface_unmap(surface);
2024                 return;
2025         }
2026
2027         tbm_bo_unmap(buf_info->bo);
2028
2029         tbm_surface_unmap(surface);
2030
2031         buf_info->dirty = 1;
2032         buf_info->dirty_shm = 0;
2033
2034         if (g_dump_info->count == 1000)
2035                 g_dump_info->count = 0;
2036
2037         g_dump_info->link = next_link;
2038
2039         TBM_LOG_I("Dump %s \n", buf_info->name);
2040 }
2041
2042 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2043                                                 const char *type)
2044 {
2045         TBM_RETURN_IF_FAIL(ptr != NULL);
2046         TBM_RETURN_IF_FAIL(w > 0);
2047         TBM_RETURN_IF_FAIL(h > 0);
2048         TBM_RETURN_IF_FAIL(stride > 0);
2049         TBM_RETURN_IF_FAIL(type != NULL);
2050
2051         tbm_surface_dump_buf_info *buf_info;
2052         struct list_head *next_link;
2053         tbm_bo_handle bo_handle;
2054         int ret, size, dw = 0, dh = 0, dstride = 0;
2055
2056         if (!g_dump_info)
2057                 return;
2058
2059         next_link = g_dump_info->link->next;
2060         TBM_RETURN_IF_FAIL(next_link != NULL);
2061
2062         if (next_link == &g_dump_info->surface_list) {
2063                 next_link = next_link->next;
2064                 TBM_RETURN_IF_FAIL(next_link != NULL);
2065         }
2066
2067         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2068         TBM_RETURN_IF_FAIL(buf_info != NULL);
2069
2070         if (scale_factor > 0.0) {
2071                 const int bpp = 4;
2072
2073                 dw = w * scale_factor;
2074                 dh = h * scale_factor;
2075                 dstride = dw * bpp;
2076                 size = dstride * dh;
2077         } else
2078                 size = stride * h;
2079
2080         if (size > buf_info->size) {
2081                 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2082                                 size, buf_info->size);
2083                 return;
2084         }
2085
2086         /* dump */
2087         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2088         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2089
2090         memset(bo_handle.ptr, 0x00, buf_info->size);
2091         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2092
2093         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2094                          _tbm_surface_internal_get_time(),
2095                          g_dump_info->count++, type, dump_postfix[0]);
2096         if (scale_factor > 0.0) {
2097                 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2098                                                                                                  TBM_FORMAT_ARGB8888, stride,
2099                                                                                                  w, h, dstride, dw, dh);
2100                 if (ret != TBM_SURFACE_ERROR_NONE) {
2101                         TBM_LOG_E("fail to scale buffer");
2102                         tbm_bo_unmap(buf_info->bo);
2103                         return;
2104                 }
2105                 buf_info->shm_stride = dstride;
2106                 buf_info->shm_h = dh;
2107         } else {
2108                 memcpy(bo_handle.ptr, ptr, size);
2109                 buf_info->shm_stride = stride;
2110                 buf_info->shm_h = h;
2111         }
2112
2113         tbm_bo_unmap(buf_info->bo);
2114
2115         buf_info->dirty = 0;
2116         buf_info->dirty_shm = 1;
2117
2118         if (g_dump_info->count == 1000)
2119                 g_dump_info->count = 0;
2120
2121         g_dump_info->link = next_link;
2122
2123         TBM_LOG_I("Dump %s \n", buf_info->name);
2124 }
2125
2126 int
2127 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2128 {
2129         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2130         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2131         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2132
2133         tbm_surface_info_s info;
2134         const char *postfix;
2135         int ret;
2136         char file[1024];
2137
2138         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2139         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2140
2141         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2142                 postfix = dump_postfix[0];
2143         else
2144                 postfix = dump_postfix[1];
2145
2146         if (strcmp(postfix, type)) {
2147                 TBM_LOG_E("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2148                 tbm_surface_unmap(surface);
2149                 return 0;
2150         }
2151
2152         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2153
2154         if (!access(file, 0)) {
2155                 TBM_LOG_E("can't capture  buffer, exist file %s", file);
2156                 tbm_surface_unmap(surface);
2157                 return 0;
2158         }
2159
2160         switch (info.format) {
2161         case TBM_FORMAT_ARGB8888:
2162         case TBM_FORMAT_XRGB8888:
2163                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2164                                                         info.planes[0].stride >> 2,
2165                                                         info.height);
2166                 break;
2167         case TBM_FORMAT_YVU420:
2168         case TBM_FORMAT_YUV420:
2169                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2170                                 info.planes[0].stride * info.height,
2171                                 info.planes[1].ptr,
2172                                 info.planes[1].stride * (info.height >> 1),
2173                                 info.planes[2].ptr,
2174                                 info.planes[2].stride * (info.height >> 1));
2175                 break;
2176         case TBM_FORMAT_NV12:
2177         case TBM_FORMAT_NV21:
2178                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2179                                         info.planes[0].stride * info.height,
2180                                         info.planes[1].ptr,
2181                                         info.planes[1].stride * (info.height >> 1),
2182                                         NULL, 0);
2183                 break;
2184         case TBM_FORMAT_YUYV:
2185         case TBM_FORMAT_UYVY:
2186                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2187                                         info.planes[0].stride * info.height,
2188                                         NULL, 0, NULL, 0);
2189                 break;
2190         default:
2191                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2192                 tbm_surface_unmap(surface);
2193                 return 0;
2194         }
2195
2196         tbm_surface_unmap(surface);
2197
2198         TBM_TRACE("Capture %s \n", file);
2199
2200         return 1;
2201 }
2202
2203 int
2204 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2205                                                 const char *path, const char *name, const char *type)
2206 {
2207         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2208         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2209         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2210         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2211         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2212         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2213
2214         char file[1024];
2215
2216         if (strcmp(dump_postfix[0], type)) {
2217                 TBM_LOG_E("Not supported type:%s'", type);
2218                 return 0;
2219         }
2220
2221         if (!access(file, 0)) {
2222                 TBM_LOG_E("can't capture buffer, exist file %s", file);
2223                 return 0;
2224         }
2225
2226         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2227
2228         _tbm_surface_internal_dump_file_png(file, ptr, stride, h);
2229
2230         TBM_TRACE("Capture %s \n", file);
2231
2232         return 1;
2233 }
2234 /*LCOV_EXCL_STOP*/