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