Added tc line coverage exception tag
[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         TBM_RETURN_IF_FAIL(scale > 0.0);
1712
1713         tbm_surface_internal_dump_start(path, (int)(scale * w), (int)(scale * h), count);
1714
1715         scale_factor = scale;
1716 }
1717
1718 void
1719 tbm_surface_internal_dump_end(void)
1720 {
1721         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1722         tbm_bo_handle bo_handle;
1723
1724         if (!g_dump_info)
1725                 return;
1726
1727         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1728                 free(g_dump_info);
1729                 g_dump_info = NULL;
1730                 return;
1731         }
1732
1733         /* make files */
1734         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1735                 char file[2048];
1736
1737                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1738                 if (bo_handle.ptr == NULL) {
1739                         tbm_bo_unref(buf_info->bo);
1740                         LIST_DEL(&buf_info->link);
1741                         free(buf_info);
1742                         continue;
1743                 }
1744
1745                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1746                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1747
1748                 if (buf_info->dirty) {
1749                         void *ptr1 = NULL, *ptr2 = NULL;
1750
1751                         switch (buf_info->info.format) {
1752                         case TBM_FORMAT_ARGB8888:
1753                         case TBM_FORMAT_XRGB8888:
1754                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1755                                                         buf_info->info.planes[0].stride >> 2,
1756                                                         buf_info->info.height);
1757                                 break;
1758                         case TBM_FORMAT_YVU420:
1759                         case TBM_FORMAT_YUV420:
1760                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1761                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1762                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1763                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1764                                                         ptr1,
1765                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1766                                                         ptr2,
1767                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1768                                 break;
1769                         case TBM_FORMAT_NV12:
1770                         case TBM_FORMAT_NV21:
1771                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1772                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1773                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1774                                                         ptr1,
1775                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1776                                                         NULL, 0);
1777                                 break;
1778                         case TBM_FORMAT_YUYV:
1779                         case TBM_FORMAT_UYVY:
1780                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1781                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1782                                                         NULL, 0, NULL, 0);
1783                                 break;
1784                         default:
1785                                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1786                                 break;
1787                         }
1788                 } else if (buf_info->dirty_shm)
1789                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1790                                                         buf_info->shm_stride >> 2,
1791                                                         buf_info->shm_h);
1792
1793                 tbm_bo_unmap(buf_info->bo);
1794                 tbm_bo_unref(buf_info->bo);
1795                 LIST_DEL(&buf_info->link);
1796                 free(buf_info);
1797         }
1798
1799         free(g_dump_info);
1800         g_dump_info = NULL;
1801
1802         TBM_LOG_I("Dump End..\n");
1803 }
1804
1805 static pixman_format_code_t
1806 _tbm_surface_internal_pixman_format_get(tbm_format format)
1807 {
1808         switch (format) {
1809         case TBM_FORMAT_ARGB8888:
1810                 return PIXMAN_a8r8g8b8;
1811         case TBM_FORMAT_XRGB8888:
1812                 return PIXMAN_x8r8g8b8;
1813         default:
1814                 return 0;
1815         }
1816
1817         return 0;
1818 }
1819
1820 /**
1821  * This function supports only if a buffer has below formats.
1822  * - TBM_FORMAT_ARGB8888
1823  * - TBM_FORMAT_XRGB8888
1824  */
1825 static tbm_surface_error_e
1826 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
1827                                                                    int format, int src_stride, int src_w, int src_h,
1828                                                                    int dst_stride, int dst_w, int dst_h)
1829 {
1830         pixman_image_t *src_img = NULL, *dst_img = NULL;
1831         pixman_format_code_t pixman_format;
1832         pixman_transform_t t;
1833         struct pixman_f_transform ft;
1834         double scale_x, scale_y;
1835
1836         TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
1837         TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
1838
1839         pixman_format = _tbm_surface_internal_pixman_format_get(format);
1840         TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
1841
1842         /* src */
1843         src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
1844                                                                            (uint32_t*)src_ptr, src_stride);
1845         TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
1846
1847         /* dst */
1848         dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
1849                                                                            (uint32_t*)dst_ptr, dst_stride);
1850         TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
1851
1852         pixman_f_transform_init_identity(&ft);
1853
1854         scale_x = (double)src_w / dst_w;
1855         scale_y = (double)src_h / dst_h;
1856
1857         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
1858         pixman_f_transform_translate(&ft, NULL, 0, 0);
1859         pixman_transform_from_pixman_f_transform(&t, &ft);
1860         pixman_image_set_transform(src_img, &t);
1861
1862         pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
1863                                                    0, 0, 0, 0, 0, 0, dst_w, dst_h);
1864
1865         pixman_image_unref(src_img);
1866         pixman_image_unref(dst_img);
1867
1868         return TBM_SURFACE_ERROR_NONE;
1869
1870 cant_convert:
1871         if (src_img)
1872                 pixman_image_unref(src_img);
1873
1874         return TBM_SURFACE_ERROR_INVALID_OPERATION;
1875 }
1876
1877 void
1878 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1879 {
1880         TBM_RETURN_IF_FAIL(surface != NULL);
1881         TBM_RETURN_IF_FAIL(type != NULL);
1882
1883         tbm_surface_dump_buf_info *buf_info;
1884         struct list_head *next_link;
1885         tbm_surface_info_s info;
1886         tbm_bo_handle bo_handle;
1887         const char *postfix;
1888         int ret;
1889
1890         if (!g_dump_info)
1891                 return;
1892
1893         next_link = g_dump_info->link->next;
1894         TBM_RETURN_IF_FAIL(next_link != NULL);
1895
1896         if (next_link == &g_dump_info->surface_list) {
1897                 next_link = next_link->next;
1898                 TBM_RETURN_IF_FAIL(next_link != NULL);
1899         }
1900
1901         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1902         TBM_RETURN_IF_FAIL(buf_info != NULL);
1903
1904         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1905         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1906
1907         if (scale_factor > 0.0) {
1908                 const int bpp = 4;
1909
1910                 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
1911                         TBM_LOG_W("Dump with scale skip. unsupported format(%s)\n",
1912                                           _tbm_surface_internal_format_to_str(info.format));
1913                         tbm_surface_unmap(surface);
1914                         return;
1915                 }
1916
1917                 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
1918
1919                 buf_info->info.width = info.width * scale_factor;
1920                 buf_info->info.height = info.height * scale_factor;
1921                 buf_info->info.format = info.format;
1922                 buf_info->info.bpp = tbm_surface_internal_get_bpp(buf_info->info.format);
1923                 buf_info->info.num_planes = 1;
1924                 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
1925                 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
1926
1927                 if (buf_info->info.size > buf_info->size) {
1928                         TBM_LOG_W("Dump with scale skip. surface over created buffer size(%u, %d)\n",
1929                                         buf_info->info.size, buf_info->size);
1930                         tbm_surface_unmap(surface);
1931                         return;
1932                 }
1933         } else {
1934                 if (info.size > buf_info->size) {
1935                         TBM_LOG_W("Dump skip. surface over created buffer size(%u, %d)\n",
1936                                         info.size, buf_info->size);
1937                         tbm_surface_unmap(surface);
1938                         return;
1939                 }
1940
1941                 /* make the file information */
1942                 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1943         }
1944
1945         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1946                 postfix = dump_postfix[0];
1947         else
1948                 postfix = dump_postfix[1];
1949
1950         /* dump */
1951         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1952         if (!bo_handle.ptr) {
1953                 TBM_LOG_E("fail to map bo");
1954                 tbm_surface_unmap(surface);
1955                 return;
1956         }
1957         memset(bo_handle.ptr, 0x00, buf_info->size);
1958
1959         switch (info.format) {
1960         case TBM_FORMAT_ARGB8888:
1961         case TBM_FORMAT_XRGB8888:
1962                 snprintf(buf_info->name, sizeof(buf_info->name),
1963                                 "%10.3f_%03d_%p-%s.%s",
1964                                  _tbm_surface_internal_get_time(),
1965                                  g_dump_info->count++, surface, type, postfix);
1966
1967                 if (scale_factor > 0.0) {
1968                         ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
1969                                                                                                          bo_handle.ptr,
1970                                                                                                          buf_info->info.format,
1971                                                                                                          info.planes[0].stride,
1972                                                                                                          info.width, info.height,
1973                                                                                                          buf_info->info.planes[0].stride,
1974                                                                                                          buf_info->info.width,
1975                                                                                                          buf_info->info.height);
1976                         if (ret != TBM_SURFACE_ERROR_NONE) {
1977                                 TBM_LOG_E("fail to scale buffer");
1978                                 tbm_bo_unmap(buf_info->bo);
1979                                 tbm_surface_unmap(surface);
1980                                 return;
1981                         }
1982                 } else
1983                         memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1984                 break;
1985         case TBM_FORMAT_YVU420:
1986         case TBM_FORMAT_YUV420:
1987                 snprintf(buf_info->name, sizeof(buf_info->name),
1988                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1989                                  _tbm_surface_internal_get_time(),
1990                                  g_dump_info->count++, type, info.planes[0].stride,
1991                                 info.height, FOURCC_STR(info.format), postfix);
1992                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1993                 bo_handle.ptr += info.planes[0].stride * info.height;
1994                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1995                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1996                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1997                 break;
1998         case TBM_FORMAT_NV12:
1999         case TBM_FORMAT_NV21:
2000                 snprintf(buf_info->name, sizeof(buf_info->name),
2001                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
2002                                  _tbm_surface_internal_get_time(),
2003                                  g_dump_info->count++, type, info.planes[0].stride,
2004                                 info.height, FOURCC_STR(info.format), postfix);
2005                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2006                 bo_handle.ptr += info.planes[0].stride * info.height;
2007                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2008                 break;
2009         case TBM_FORMAT_YUYV:
2010         case TBM_FORMAT_UYVY:
2011                 snprintf(buf_info->name, sizeof(buf_info->name),
2012                                 "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
2013                                  _tbm_surface_internal_get_time(),
2014                                  g_dump_info->count++, type, info.planes[0].stride,
2015                                 info.height, FOURCC_STR(info.format), postfix);
2016                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2017                 break;
2018         default:
2019                 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2020                 tbm_bo_unmap(buf_info->bo);
2021                 tbm_surface_unmap(surface);
2022                 return;
2023         }
2024
2025         tbm_bo_unmap(buf_info->bo);
2026
2027         tbm_surface_unmap(surface);
2028
2029         buf_info->dirty = 1;
2030         buf_info->dirty_shm = 0;
2031
2032         if (g_dump_info->count == 1000)
2033                 g_dump_info->count = 0;
2034
2035         g_dump_info->link = next_link;
2036
2037         TBM_LOG_I("Dump %s \n", buf_info->name);
2038 }
2039
2040 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2041                                                 const char *type)
2042 {
2043         TBM_RETURN_IF_FAIL(ptr != NULL);
2044         TBM_RETURN_IF_FAIL(w > 0);
2045         TBM_RETURN_IF_FAIL(h > 0);
2046         TBM_RETURN_IF_FAIL(stride > 0);
2047         TBM_RETURN_IF_FAIL(type != NULL);
2048
2049         tbm_surface_dump_buf_info *buf_info;
2050         struct list_head *next_link;
2051         tbm_bo_handle bo_handle;
2052         int ret, size, dw = 0, dh = 0, dstride = 0;
2053
2054         if (!g_dump_info)
2055                 return;
2056
2057         next_link = g_dump_info->link->next;
2058         TBM_RETURN_IF_FAIL(next_link != NULL);
2059
2060         if (next_link == &g_dump_info->surface_list) {
2061                 next_link = next_link->next;
2062                 TBM_RETURN_IF_FAIL(next_link != NULL);
2063         }
2064
2065         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2066         TBM_RETURN_IF_FAIL(buf_info != NULL);
2067
2068         if (scale_factor > 0.0) {
2069                 const int bpp = 4;
2070
2071                 dw = w * scale_factor;
2072                 dh = h * scale_factor;
2073                 dstride = dw * bpp;
2074                 size = dstride * dh;
2075         } else
2076                 size = stride * h;
2077
2078         if (size > buf_info->size) {
2079                 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2080                                 size, buf_info->size);
2081                 return;
2082         }
2083
2084         /* dump */
2085         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2086         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2087
2088         memset(bo_handle.ptr, 0x00, buf_info->size);
2089         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2090
2091         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2092                          _tbm_surface_internal_get_time(),
2093                          g_dump_info->count++, type, dump_postfix[0]);
2094         if (scale_factor > 0.0) {
2095                 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2096                                                                                                  TBM_FORMAT_ARGB8888, stride,
2097                                                                                                  w, h, dstride, dw, dh);
2098                 if (ret != TBM_SURFACE_ERROR_NONE) {
2099                         TBM_LOG_E("fail to scale buffer");
2100                         tbm_bo_unmap(buf_info->bo);
2101                         return;
2102                 }
2103                 buf_info->shm_stride = dstride;
2104                 buf_info->shm_h = dh;
2105         } else {
2106                 memcpy(bo_handle.ptr, ptr, size);
2107                 buf_info->shm_stride = stride;
2108                 buf_info->shm_h = h;
2109         }
2110
2111         tbm_bo_unmap(buf_info->bo);
2112
2113         buf_info->dirty = 0;
2114         buf_info->dirty_shm = 1;
2115
2116         if (g_dump_info->count == 1000)
2117                 g_dump_info->count = 0;
2118
2119         g_dump_info->link = next_link;
2120
2121         TBM_LOG_I("Dump %s \n", buf_info->name);
2122 }
2123
2124 int
2125 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2126 {
2127         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2128         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2129         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2130
2131         tbm_surface_info_s info;
2132         const char *postfix;
2133         int ret;
2134         char file[1024];
2135
2136         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2137         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2138
2139         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2140                 postfix = dump_postfix[0];
2141         else
2142                 postfix = dump_postfix[1];
2143
2144         if (strcmp(postfix, type)) {
2145                 TBM_LOG_E("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2146                 tbm_surface_unmap(surface);
2147                 return 0;
2148         }
2149
2150         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2151
2152         if (!access(file, 0)) {
2153                 TBM_LOG_E("can't capture  buffer, exist file %s", file);
2154                 tbm_surface_unmap(surface);
2155                 return 0;
2156         }
2157
2158         switch (info.format) {
2159         case TBM_FORMAT_ARGB8888:
2160         case TBM_FORMAT_XRGB8888:
2161                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2162                                                         info.planes[0].stride >> 2,
2163                                                         info.height);
2164                 break;
2165         case TBM_FORMAT_YVU420:
2166         case TBM_FORMAT_YUV420:
2167                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2168                                 info.planes[0].stride * info.height,
2169                                 info.planes[1].ptr,
2170                                 info.planes[1].stride * (info.height >> 1),
2171                                 info.planes[2].ptr,
2172                                 info.planes[2].stride * (info.height >> 1));
2173                 break;
2174         case TBM_FORMAT_NV12:
2175         case TBM_FORMAT_NV21:
2176                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2177                                         info.planes[0].stride * info.height,
2178                                         info.planes[1].ptr,
2179                                         info.planes[1].stride * (info.height >> 1),
2180                                         NULL, 0);
2181                 break;
2182         case TBM_FORMAT_YUYV:
2183         case TBM_FORMAT_UYVY:
2184                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2185                                         info.planes[0].stride * info.height,
2186                                         NULL, 0, NULL, 0);
2187                 break;
2188         default:
2189                 TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2190                 tbm_surface_unmap(surface);
2191                 return 0;
2192         }
2193
2194         tbm_surface_unmap(surface);
2195
2196         TBM_TRACE("Capture %s \n", file);
2197
2198         return 1;
2199 }
2200
2201 int
2202 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2203                                                 const char *path, const char *name, const char *type)
2204 {
2205         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2206         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2207         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2208         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2209         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2210         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2211
2212         char file[1024];
2213
2214         if (strcmp(dump_postfix[0], type)) {
2215                 TBM_LOG_E("Not supported type:%s'", type);
2216                 return 0;
2217         }
2218
2219         if (!access(file, 0)) {
2220                 TBM_LOG_E("can't capture buffer, exist file %s", file);
2221                 return 0;
2222         }
2223
2224         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2225
2226         _tbm_surface_internal_dump_file_png(file, ptr, stride, h);
2227
2228         TBM_TRACE("Capture %s \n", file);
2229
2230         return 1;
2231 }
2232 /*LCOV_EXCL_STOP*/