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