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