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