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