tbm_module: add tbm_bo_data structure and use it
[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 struct _tbm_surface *
598 _tbm_surface_internal_create_surface(tbm_bufmgr bufmgr, int width, int height, int format, int flags, tbm_error_e *error)
599 {
600         struct _tbm_surface *surf = NULL;
601         uint32_t size = 0, offset = 0, stride = 0, bo_size = 0;
602         int i, j, bo_idx;
603
604         surf = calloc(1, sizeof(struct _tbm_surface));
605         if (!surf) {
606                 /* LCOV_EXCL_START */
607                 TBM_ERR("fail to alloc surf\n");
608                 *error = TBM_ERROR_OUT_OF_MEMORY;
609                 goto alloc_surf_fail;
610                 /* LCOV_EXCL_STOP */
611         }
612
613         surf->magic = TBM_SURFACE_MAGIC;
614         surf->bufmgr = bufmgr;
615         surf->info.width = width;
616         surf->info.height = height;
617         surf->info.format = format;
618         surf->info.bpp = _tbm_surface_internal_get_bpp(format);
619         if (!surf->info.bpp) {
620                 TBM_ERR("fail to get bpp from format(%d), error(%s)\n", format, tbm_error_str(*error));
621                 *error = tbm_get_last_error();
622                 goto bpp_fail;
623         }
624
625         surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
626         if (!surf->info.num_planes) {
627                 TBM_ERR("fail to get num_planes from format(%d), error(%s)\n", format, tbm_error_str(*error));
628                 *error = tbm_get_last_error();
629                 goto num_planes_fail;
630         }
631         surf->refcnt = 1;
632
633         /* get size, stride and offset bo_idx */
634         for (i = 0; i < surf->info.num_planes; i++) {
635                 if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
636                         TBM_ERR("fail to query plane data\n");
637                         *error = tbm_get_last_error();
638                         goto query_plane_data_fail;
639                 }
640
641                 surf->info.planes[i].size = size;
642                 surf->info.planes[i].offset = offset;
643                 surf->info.planes[i].stride = stride;
644                 surf->planes_bo_idx[i] = bo_idx;
645         }
646
647         surf->num_bos = 1;
648
649         for (i = 0; i < surf->info.num_planes; i++) {
650                 surf->info.size += surf->info.planes[i].size;
651
652                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
653                         surf->num_bos = surf->planes_bo_idx[i] + 1;
654         }
655
656         surf->flags = flags;
657
658         for (i = 0; i < surf->num_bos; i++) {
659                 bo_size = 0;
660                 for (j = 0; j < surf->info.num_planes; j++) {
661                         if (surf->planes_bo_idx[j] == i)
662                                 bo_size += surf->info.planes[j].size;
663                 }
664
665                 surf->bos[i] = tbm_bufmgr_internal_alloc_bo_with_format(bufmgr, format, i, width, height, surf->info.bpp/8, flags, error);
666                 if (!surf->bos[i]) {
667                         surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
668                         if (!surf->bos[i]) {
669                                 TBM_ERR("fail to alloc bo idx:%d\n", i);
670                                 *error = tbm_get_last_error();
671                                 goto alloc_bo_fail;
672                         }
673                 }
674
675                 _tbm_bo_set_surface(surf->bos[i], surf);
676         }
677
678         *error = TBM_ERROR_NONE;
679
680         return surf;
681
682 alloc_bo_fail:
683         for (j = 0; j < i; j++) {
684                 if (surf->bos[j])
685                         tbm_bo_unref(surf->bos[j]);
686         }
687 query_plane_data_fail:
688 bpp_fail:
689 num_planes_fail:
690         free(surf);
691 alloc_surf_fail:
692
693         return NULL;
694 }
695
696 static struct _tbm_surface *
697 _tbm_surface_internal_create_surface_data(tbm_bufmgr bufmgr, int width, int height, int format, int flags, tbm_error_e *error)
698 {
699         struct _tbm_surface *surf = NULL;
700         uint32_t size = 0, offset = 0, stride = 0;
701         int i, j, bo_idx;
702         tbm_bo_data **bo_data_array = NULL;
703         int num_bos = 0;
704
705         surf = calloc(1, sizeof(struct _tbm_surface));
706         if (!surf) {
707                 /* LCOV_EXCL_START */
708                 TBM_ERR("fail to alloc surf");
709                 *error = TBM_ERROR_OUT_OF_MEMORY;
710                 goto alloc_surf_fail;
711                 /* LCOV_EXCL_STOP */
712         }
713         surf->refcnt = 1;
714
715         surf->magic = TBM_SURFACE_MAGIC;
716         surf->bufmgr = bufmgr;
717         surf->info.width = width;
718         surf->info.height = height;
719         surf->info.format = format;
720         surf->info.bpp = _tbm_surface_internal_get_bpp(format);
721         if (!surf->info.bpp) {
722                 TBM_ERR("fail to get bpp from format(%d), error(%s)", format, tbm_error_str(*error));
723                 *error = tbm_get_last_error();
724                 goto bpp_fail;
725         }
726         surf->flags = flags;
727
728         // get number of planes
729         surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
730         if (!surf->info.num_planes) {
731                 TBM_ERR("fail to get num_planes from format(%d), error(%s)", format, tbm_error_str(*error));
732                 *error = tbm_get_last_error();
733                 goto num_planes_fail;
734         }
735
736         surf->surface_data = tbm_module_alloc_surface_data(bufmgr->module, width, height, format, flags, error);
737         if (!surf->surface_data) {
738                 TBM_ERR("tbm_module_alloc_surface_data failed. error:%s", tbm_error_str(*error));
739                 goto alloc_surface_data_fail;
740         }
741
742         // set infomation of planes
743         for (i = 0; i < surf->info.num_planes; i++) {
744                 *error = tbm_surface_data_get_plane_data(surf->surface_data, i, &size, &offset, &stride, &bo_idx);
745                 if (*error != TBM_ERROR_NONE) {
746                         goto query_plane_data_fail;
747                 }
748                 surf->info.planes[i].size = size;
749                 surf->info.planes[i].offset = offset;
750                 surf->info.planes[i].stride = stride;
751                 surf->planes_bo_idx[i] = bo_idx;
752         }
753
754         // set infomation of bos
755         bo_data_array = tbm_surface_data_get_bo_data_array(surf->surface_data, &num_bos, error);
756         if (!bo_data_array) {
757                 TBM_ERR("tbm_surface_data_get_bo_data_array failed. error:%s", tbm_error_str(*error));
758                 goto get_bos_fail;
759         }
760         surf->num_bos = num_bos;
761
762         for (i = 0; i < surf->info.num_planes; i++) {
763                 surf->info.size += surf->info.planes[i].size;
764
765                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
766                         surf->num_bos = surf->planes_bo_idx[i] + 1;
767         }
768
769         for (i = 0; i < num_bos; i++) {
770                 surf->bos[i] = tbm_bufmgr_internal_alloc_bo_with_bo_data(bufmgr, bo_data_array[i], flags);
771                 if (!surf->bos[i]) {
772                         TBM_ERR("fail to alloc bo idx:%d", i);
773                         *error = tbm_get_last_error();
774                         goto get_bo_fail;
775                 }
776
777                 _tbm_bo_set_surface(surf->bos[i], surf);
778         }
779
780         *error = TBM_ERROR_NONE;
781
782         return surf;
783
784 get_bo_fail:
785         for (j = 0; j < i; j++) {
786                 if (surf->bos[j])
787                         tbm_bo_unref(surf->bos[j]);
788         }
789 get_bos_fail:
790 query_plane_data_fail:
791         if (surf->surface_data)
792                 tbm_surface_data_free(surf->surface_data);
793 alloc_surface_data_fail:
794 num_planes_fail:
795 bpp_fail:
796         if (surf)
797                 free(surf);
798 alloc_surf_fail:
799
800         return NULL;
801 }
802
803 static struct _tbm_surface *
804 _tbm_surface_internal_import_surface_data(tbm_bufmgr bufmgr, int width, int height, int format, tbm_surface_buffer_data *buffer_data, tbm_error_e *error)
805 {
806         struct _tbm_surface *surf = NULL;
807         uint32_t size = 0, offset = 0, stride = 0;
808         int i, j, bo_idx;
809         tbm_bo_data **bo_data_array = NULL;
810         int num_bos = 0;
811         int flags;
812
813         surf = calloc(1, sizeof(struct _tbm_surface));
814         if (!surf) {
815                 /* LCOV_EXCL_START */
816                 TBM_ERR("fail to alloc surf");
817                 *error = TBM_ERROR_OUT_OF_MEMORY;
818                 goto alloc_surf_fail;
819                 /* LCOV_EXCL_STOP */
820         }
821         surf->refcnt = 1;
822
823         surf->magic = TBM_SURFACE_MAGIC;
824         surf->bufmgr = bufmgr;
825         surf->info.width = width;
826         surf->info.height = height;
827         surf->info.format = format;
828         surf->info.bpp = _tbm_surface_internal_get_bpp(format);
829         if (!surf->info.bpp) {
830                 TBM_ERR("fail to get bpp from format(%d), error(%s)", format, tbm_error_str(*error));
831                 *error = tbm_get_last_error();
832                 goto bpp_fail;
833         }
834
835         // get number of planes
836         surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
837         if (!surf->info.num_planes) {
838                 TBM_ERR("fail to get num_planes from format(%d), error(%s)", format, tbm_error_str(*error));
839                 *error = tbm_get_last_error();
840                 goto num_planes_fail;
841         }
842
843         // import surface
844         surf->surface_data = tbm_module_import_surface_data(bufmgr->module, width, height, format, buffer_data, error);
845         if (surf->surface_data) {
846                 TBM_ERR("tbm_module_import_surface_data failed. width:%d height:%d format:%d error:%s",
847                                 width, height, format, tbm_error_str(*error));
848                 goto import_surface_fail;
849         }
850
851         // set infomation of planes
852         for (i = 0; i < surf->info.num_planes; i++) {
853                 *error = tbm_surface_data_get_plane_data(surf->surface_data, i, &size, &offset, &stride, &bo_idx);
854                 if (*error != TBM_ERROR_NONE) {
855                         goto query_plane_data_fail;
856                 }
857                 surf->info.planes[i].size = size;
858                 surf->info.planes[i].offset = offset;
859                 surf->info.planes[i].stride = stride;
860                 surf->planes_bo_idx[i] = bo_idx;
861         }
862
863         // set infomation of bos
864         bo_data_array = tbm_surface_data_get_bo_data_array(surf->surface_data, &num_bos, error);
865         if (!bo_data_array) {
866                 TBM_ERR("tbm_surface_data_get_bo_data_array failed. error:%s", tbm_error_str(*error));
867                 goto get_bos_fail;
868         }
869         surf->num_bos = num_bos;
870
871         for (i = 0; i < surf->info.num_planes; i++) {
872                 surf->info.size += surf->info.planes[i].size;
873
874                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
875                         surf->num_bos = surf->planes_bo_idx[i] + 1;
876         }
877
878         // get memory_types(bo flags)
879         flags = tbm_module_bo_get_memory_types(bufmgr->module, NULL, bo_data_array[0], error);
880         if (*error != TBM_ERROR_NONE) {
881                 TBM_ERR("tbm_module_bo_get_memory_types failed.error:%s", tbm_error_str(*error));
882                 goto get_memory_types_fail;
883         }
884         surf->flags = flags;
885
886         for (i = 0; i < num_bos; i++) {
887                 surf->bos[i] = tbm_bufmgr_internal_alloc_bo_with_bo_data(bufmgr, bo_data_array[i], flags);
888                 if (!surf->bos[i]) {
889                         TBM_ERR("fail to alloc bo idx:%d", i);
890                         *error = tbm_get_last_error();
891                         goto get_bo_fail;
892                 }
893
894                 _tbm_bo_set_surface(surf->bos[i], surf);
895         }
896
897         return surf;
898
899 get_bo_fail:
900         for (j = 0; j < i; j++) {
901                 if (surf->bos[j])
902                         tbm_bo_unref(surf->bos[j]);
903         }
904 get_memory_types_fail:
905 get_bos_fail:
906 query_plane_data_fail:
907         if (surf->surface_data)
908                 tbm_surface_data_free(surf->surface_data);
909 import_surface_fail:
910 num_planes_fail:
911 bpp_fail:
912         if (surf)
913                 free(surf);
914 alloc_surf_fail:
915
916         return NULL;
917 }
918
919 int
920 tbm_surface_internal_is_valid(tbm_surface_h surface)
921 {
922         int ret = 0;
923
924         _tbm_surface_mutex_lock();
925         _tbm_set_last_result(TBM_ERROR_NONE);
926
927         /* Return silently if surface is null. */
928         if (!surface) {
929                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
930                 _tbm_surface_mutex_unlock();
931                 return 0;
932         }
933
934         ret = _tbm_surface_internal_is_valid(surface);
935
936         _tbm_surface_mutex_unlock();
937
938         return ret;
939 }
940
941 int
942 tbm_surface_internal_query_supported_formats(uint32_t **formats,
943                 uint32_t *num)
944 {
945         struct _tbm_bufmgr *bufmgr;
946         bool bufmgr_initialized = false;
947         tbm_error_e error;
948
949         _tbm_surface_mutex_lock();
950         _tbm_set_last_result(TBM_ERROR_NONE);
951
952         TBM_SURFACE_RETURN_VAL_IF_FAIL(formats, 0);
953         TBM_SURFACE_RETURN_VAL_IF_FAIL(num, 0);
954
955         if (!g_surface_bufmgr) {
956                 _init_surface_bufmgr();
957                 if (!g_surface_bufmgr) {
958                         TBM_ERR("fail bufmgr initialization\n");
959                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
960                         goto fail;
961                 }
962                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
963                 bufmgr_initialized = true;
964         }
965
966         bufmgr = g_surface_bufmgr;
967
968         error = tbm_module_get_supported_formats(bufmgr->module, formats, num);
969         if (error != TBM_ERROR_NONE) {
970                 _tbm_set_last_result(error);
971                 goto fail;
972         }
973
974         TBM_TRACE_SURFACE_INTERNAL("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
975
976         if (bufmgr_initialized) {
977                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
978                 _deinit_surface_bufmgr();
979         }
980
981         _tbm_surface_mutex_unlock();
982
983         return 1;
984
985 /* LCOV_EXCL_START */
986 fail:
987         if (bufmgr_initialized) {
988                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
989                 _deinit_surface_bufmgr();
990         }
991         _tbm_surface_mutex_unlock();
992
993         TBM_ERR("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
994
995         return 0;
996 /* LCOV_EXCL_STOP */
997 }
998
999 int
1000 tbm_surface_internal_get_num_planes(tbm_format format)
1001 {
1002         int num_planes = 0;
1003
1004         _tbm_surface_mutex_lock();
1005         _tbm_set_last_result(TBM_ERROR_NONE);
1006
1007         num_planes = _tbm_surface_internal_get_num_planes(format);
1008         if (!num_planes) {
1009                 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
1010                 _tbm_surface_mutex_unlock();
1011                 return 0;
1012         }
1013
1014         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
1015
1016         _tbm_surface_mutex_unlock();
1017
1018         return num_planes;
1019 }
1020
1021 int
1022 tbm_surface_internal_get_bpp(tbm_format format)
1023 {
1024         int bpp = 0;
1025
1026         _tbm_surface_mutex_lock();
1027         _tbm_set_last_result(TBM_ERROR_NONE);
1028
1029         bpp = _tbm_surface_internal_get_bpp(format);
1030         if (!bpp) {
1031                 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
1032                 _tbm_surface_mutex_unlock();
1033                 return 0;
1034         }
1035
1036         _tbm_surface_mutex_unlock();
1037
1038         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
1039
1040         return bpp;
1041 }
1042
1043 tbm_surface_h
1044 tbm_surface_internal_create_with_flags(int width, int height,
1045                                        int format, int flags)
1046 {
1047         struct _tbm_bufmgr *bufmgr;
1048         struct _tbm_surface *surf = NULL;
1049         tbm_error_e error = TBM_ERROR_INVALID_OPERATION;
1050         bool bufmgr_initialized = false;
1051
1052         _tbm_surface_mutex_lock();
1053         _tbm_set_last_result(TBM_ERROR_NONE);
1054
1055         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, NULL);
1056         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, NULL);
1057
1058         if (!g_surface_bufmgr) {
1059                 _init_surface_bufmgr();
1060                 if (!g_surface_bufmgr) {
1061                         TBM_ERR("fail bufmgr initialization\n");
1062                         error = 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("The bufmgr is invalid\n");
1072                 error = TBM_ERROR_INVALID_PARAMETER;
1073                 goto check_valid_fail;
1074         }
1075
1076         if (tbm_module_support_surface_data(bufmgr->module)) {
1077                 surf = _tbm_surface_internal_create_surface_data(bufmgr, width, height, format, flags, &error);
1078                 if (!surf) {
1079                         TBM_ERR("_tbm_surface_internal_create_surface_data failed.");
1080                         goto surface_alloc_fail;
1081                 }
1082         } else {
1083                 surf = _tbm_surface_internal_create_surface(bufmgr, width, height, format, flags, &error);
1084                 if (!surf) {
1085                         TBM_ERR("_tbm_surface_internal_create_surface failed.");
1086                         goto surface_alloc_fail;
1087                 }
1088         }
1089
1090         TBM_TRACE_SURFACE_INTERNAL("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n",
1091                         width, height, _tbm_surface_internal_format_to_str(format), flags, surf);
1092
1093         LIST_INITHEAD(&surf->user_data_list);
1094         LIST_INITHEAD(&surf->debug_data_list);
1095         LIST_INITHEAD(&surf->destroy_funcs);
1096
1097         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1098
1099         _tbm_set_last_result(error);
1100         _tbm_surface_mutex_unlock();
1101
1102         return surf;
1103
1104 /* LCOV_EXCL_START */
1105
1106 surface_alloc_fail:
1107 check_valid_fail:
1108         if (bufmgr_initialized && bufmgr) {
1109                 LIST_DELINIT(&bufmgr->surf_list);
1110                 _deinit_surface_bufmgr();
1111         }
1112
1113         TBM_ERR("error: width(%d) height(%d) format(%s) flags(%d)\n",
1114                 width, height, _tbm_surface_internal_format_to_str(format), flags);
1115
1116         _tbm_set_last_result(error);
1117         _tbm_surface_mutex_unlock();
1118
1119 /* LCOV_EXCL_STOP */
1120
1121         return NULL;
1122 }
1123
1124 tbm_surface_h
1125 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
1126                                      tbm_bo *bos, int num)
1127 {
1128         struct _tbm_bufmgr *bufmgr;
1129         struct _tbm_surface *surf = NULL;
1130         int i;
1131         bool bufmgr_initialized = false;
1132
1133         _tbm_surface_mutex_lock();
1134         _tbm_set_last_result(TBM_ERROR_NONE);
1135
1136         TBM_SURFACE_RETURN_VAL_IF_FAIL(bos, NULL);
1137         TBM_SURFACE_RETURN_VAL_IF_FAIL(info, NULL);
1138         TBM_SURFACE_RETURN_VAL_IF_FAIL(info->num_planes > 0, NULL);
1139         TBM_SURFACE_RETURN_VAL_IF_FAIL(num > 0, NULL);
1140         TBM_SURFACE_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
1141
1142         if (!g_surface_bufmgr) {
1143                 _init_surface_bufmgr();
1144                 if (!g_surface_bufmgr) {
1145                         TBM_ERR("fail bufmgr initialization\n");
1146                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1147                         goto check_valid_fail;
1148                 }
1149                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
1150                 bufmgr_initialized = true;
1151         }
1152
1153         bufmgr = g_surface_bufmgr;
1154         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
1155                 TBM_ERR("fail to validate the Bufmgr.\n");
1156                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1157                 goto check_valid_fail;
1158         }
1159
1160         surf = calloc(1, sizeof(struct _tbm_surface));
1161         if (!surf) {
1162                 /* LCOV_EXCL_START */
1163                 TBM_ERR("fail to allocate struct _tbm_surface.\n");
1164                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1165                 goto alloc_surf_fail;
1166                 /* LCOV_EXCL_STOP */
1167         }
1168
1169         surf->magic = TBM_SURFACE_MAGIC;
1170         surf->bufmgr = bufmgr;
1171         surf->info.width = info->width;
1172         surf->info.height = info->height;
1173         surf->info.format = info->format;
1174         if (info->bpp > 0)
1175                 surf->info.bpp = info->bpp;
1176         else {
1177                 surf->info.bpp = _tbm_surface_internal_get_bpp(info->format);
1178                 if (!surf->info.bpp) {
1179                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1180                         goto bpp_fail;
1181                 }
1182         }
1183         surf->info.num_planes = info->num_planes;
1184         surf->refcnt = 1;
1185
1186         /* get size, stride and offset */
1187         for (i = 0; i < info->num_planes; i++) {
1188                 surf->info.planes[i].offset = info->planes[i].offset;
1189                 surf->info.planes[i].stride = info->planes[i].stride;
1190
1191                 if (info->planes[i].size > 0)
1192                         surf->info.planes[i].size = info->planes[i].size;
1193                 else {
1194                         uint32_t size = 0, offset = 0, stride = 0;
1195                         int32_t bo_idx = 0;
1196
1197                         if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
1198                                 TBM_ERR("fail to get plane_data. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1199                                 goto plane_data_fail;
1200                         }
1201                         surf->info.planes[i].size = size;
1202                 }
1203
1204                 if (num == 1)
1205                         surf->planes_bo_idx[i] = 0;
1206                 else
1207                         surf->planes_bo_idx[i] = i;
1208         }
1209
1210         if (info->size > 0) {
1211                 surf->info.size = info->size;
1212         } else {
1213                 surf->info.size = 0;
1214                 for (i = 0; i < info->num_planes; i++)
1215                         surf->info.size += surf->info.planes[i].size;
1216         }
1217
1218         surf->flags = TBM_BO_DEFAULT;
1219
1220         /* create only one bo */
1221         surf->num_bos = num;
1222         for (i = 0; i < num; i++) {
1223                 if (bos[i] == NULL) {
1224                         TBM_ERR("bos[%d] is null.\n", i);
1225                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1226                         goto check_bo_fail;
1227                 }
1228
1229                 surf->bos[i] = tbm_bo_ref(bos[i]);
1230                 _tbm_bo_set_surface(bos[i], surf);
1231         }
1232
1233         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
1234                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
1235
1236         LIST_INITHEAD(&surf->user_data_list);
1237         LIST_INITHEAD(&surf->debug_data_list);
1238         LIST_INITHEAD(&surf->destroy_funcs);
1239
1240         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1241
1242         _tbm_surface_mutex_unlock();
1243
1244         return surf;
1245
1246 /* LCOV_EXCL_START */
1247 check_bo_fail:
1248 plane_data_fail:
1249 bpp_fail:
1250         for (i = 0; i < num; i++) {
1251                 if (surf->bos[i])
1252                         tbm_bo_unref(surf->bos[i]);
1253         }
1254         free(surf);
1255 alloc_surf_fail:
1256 check_valid_fail:
1257         if (bufmgr_initialized && bufmgr) {
1258                 LIST_DELINIT(&bufmgr->surf_list);
1259                 _deinit_surface_bufmgr();
1260         }
1261         _tbm_surface_mutex_unlock();
1262
1263         TBM_ERR("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
1264                         info->width, info->height,
1265                         _tbm_surface_internal_format_to_str(info->format), num);
1266 /* LCOV_EXCL_STOP */
1267
1268         return NULL;
1269 }
1270
1271 void
1272 tbm_surface_internal_destroy(tbm_surface_h surface)
1273 {
1274         _tbm_surface_mutex_lock();
1275         _tbm_set_last_result(TBM_ERROR_NONE);
1276
1277         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1278
1279         surface->refcnt--;
1280
1281         if (surface->refcnt > 0) {
1282                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1283                 _tbm_surface_mutex_unlock();
1284                 return;
1285         }
1286
1287         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1288
1289         if (surface->refcnt == 0)
1290                 _tbm_surface_internal_destroy(surface);
1291         else // if (surface->refcnt < 0)
1292                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1293
1294         _tbm_surface_mutex_unlock();
1295 }
1296
1297 void
1298 tbm_surface_internal_ref(tbm_surface_h surface)
1299 {
1300         _tbm_surface_mutex_lock();
1301         _tbm_set_last_result(TBM_ERROR_NONE);
1302
1303         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1304
1305         surface->refcnt++;
1306
1307         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1308
1309         _tbm_surface_mutex_unlock();
1310 }
1311
1312 void
1313 tbm_surface_internal_unref(tbm_surface_h surface)
1314 {
1315         _tbm_surface_mutex_lock();
1316         _tbm_set_last_result(TBM_ERROR_NONE);
1317
1318         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1319
1320         surface->refcnt--;
1321
1322         if (surface->refcnt > 0) {
1323                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1324                 _tbm_surface_mutex_unlock();
1325                 return;
1326         }
1327
1328         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1329
1330         if (surface->refcnt == 0)
1331                 _tbm_surface_internal_destroy(surface);
1332
1333         _tbm_surface_mutex_unlock();
1334 }
1335
1336 int
1337 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
1338 {
1339         struct _tbm_surface *surf;
1340         int num;
1341
1342         _tbm_surface_mutex_lock();
1343         _tbm_set_last_result(TBM_ERROR_NONE);
1344
1345         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1346
1347         surf = (struct _tbm_surface *)surface;
1348         num = surf->num_bos;
1349
1350         if (!num)
1351                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1352
1353         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) num_bos(%d)\n", surface, num);
1354
1355         _tbm_surface_mutex_unlock();
1356
1357         return num;
1358 }
1359
1360 tbm_bo
1361 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
1362 {
1363         struct _tbm_surface *surf;
1364         tbm_bo bo;
1365
1366         _tbm_surface_mutex_lock();
1367         _tbm_set_last_result(TBM_ERROR_NONE);
1368
1369         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
1370         TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
1371
1372         surf = (struct _tbm_surface *)surface;
1373         bo = surf->bos[bo_idx];
1374
1375         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
1376
1377         _tbm_surface_mutex_unlock();
1378
1379         return bo;
1380 }
1381
1382 unsigned int
1383 tbm_surface_internal_get_size(tbm_surface_h surface)
1384 {
1385         struct _tbm_surface *surf;
1386         unsigned int size;
1387
1388         _tbm_surface_mutex_lock();
1389         _tbm_set_last_result(TBM_ERROR_NONE);
1390
1391         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1392
1393         surf = (struct _tbm_surface *)surface;
1394         size = surf->info.size;
1395
1396         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) size(%u)\n", surface, size);
1397
1398         _tbm_surface_mutex_unlock();
1399
1400         return size;
1401 }
1402
1403 int
1404 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1405                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
1406 {
1407         struct _tbm_surface *surf;
1408
1409         _tbm_surface_mutex_lock();
1410         _tbm_set_last_result(TBM_ERROR_NONE);
1411
1412         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1413         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1414
1415         surf = (struct _tbm_surface *)surface;
1416
1417         if (plane_idx >= surf->info.num_planes) {
1418                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1419                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1420                 _tbm_surface_mutex_unlock();
1421                 return 0;
1422         }
1423
1424         if (size)
1425                 *size = surf->info.planes[plane_idx].size;
1426
1427         if (offset)
1428                 *offset = surf->info.planes[plane_idx].offset;
1429
1430         if (pitch)
1431                 *pitch = surf->info.planes[plane_idx].stride;
1432
1433         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1434                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1435                                 surf->info.planes[plane_idx].stride);
1436
1437         _tbm_surface_mutex_unlock();
1438
1439         return 1;
1440 }
1441
1442 int
1443 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1444                               tbm_surface_info_s *info, int map)
1445 {
1446         struct _tbm_surface *surf;
1447         tbm_bo_handle bo_handles[4];
1448         int num_bos = 0;
1449         tbm_bo bos[4];
1450         int planes_bo_idx[TBM_SURF_PLANE_MAX];
1451         int i, j;
1452
1453         _tbm_surface_mutex_lock();
1454         _tbm_set_last_result(TBM_ERROR_NONE);
1455
1456         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1457
1458         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1459
1460         surf = (struct _tbm_surface *)surface;
1461
1462         memset(info, 0x00, sizeof(tbm_surface_info_s));
1463         info->width = surf->info.width;
1464         info->height = surf->info.height;
1465         info->format = surf->info.format;
1466         info->bpp = surf->info.bpp;
1467         info->size = surf->info.size;
1468         info->num_planes = surf->info.num_planes;
1469
1470         for (i = 0; i < surf->info.num_planes; i++) {
1471                 info->planes[i].size = surf->info.planes[i].size;
1472                 info->planes[i].offset = surf->info.planes[i].offset;
1473                 info->planes[i].stride = surf->info.planes[i].stride;
1474                 planes_bo_idx[i] = surf->planes_bo_idx[i];
1475         }
1476
1477         for (i = 0; i < surf->num_bos; i++)
1478                 bos[i] = surf->bos[i];
1479
1480         num_bos = surf->num_bos;
1481
1482         if (map == 1) {
1483                 _tbm_surface_mutex_unlock();
1484                 for (i = 0; i < num_bos; i++) {
1485                         bo_handles[i] = tbm_bo_map(bos[i], TBM_DEVICE_CPU, opt);
1486                         if (bo_handles[i].ptr == NULL) {
1487                                 for (j = 0; j < i; j++)
1488                                         tbm_bo_unmap(bos[j]);
1489
1490                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1491                                 return 0;
1492                         }
1493                 }
1494                 _tbm_surface_mutex_lock();
1495         } else {
1496                 for (i = 0; i < num_bos; i++) {
1497                         bo_handles[i] = tbm_bo_get_handle(bos[i], TBM_DEVICE_CPU);
1498                         if (bo_handles[i].ptr == NULL) {
1499                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1500                                 _tbm_surface_mutex_unlock();
1501                                 return 0;
1502                         }
1503                 }
1504         }
1505
1506         for (i = 0; i < info->num_planes; i++) {
1507                 if (bo_handles[planes_bo_idx[i]].ptr)
1508                         info->planes[i].ptr = bo_handles[planes_bo_idx[i]].ptr + info->planes[i].offset;
1509         }
1510
1511         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1512
1513         _tbm_surface_mutex_unlock();
1514
1515         return 1;
1516 }
1517
1518 void
1519 tbm_surface_internal_unmap(tbm_surface_h surface)
1520 {
1521         struct _tbm_surface *surf;
1522         int i;
1523
1524         _tbm_surface_mutex_lock();
1525         _tbm_set_last_result(TBM_ERROR_NONE);
1526
1527         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1528
1529         surf = (struct _tbm_surface *)surface;
1530
1531         for (i = 0; i < surf->num_bos; i++)
1532                 tbm_bo_unmap(surf->bos[i]);
1533
1534         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)\n", surface);
1535
1536         _tbm_surface_mutex_unlock();
1537 }
1538
1539 unsigned int
1540 tbm_surface_internal_get_width(tbm_surface_h surface)
1541 {
1542         struct _tbm_surface *surf;
1543         unsigned int width;
1544
1545         _tbm_surface_mutex_lock();
1546         _tbm_set_last_result(TBM_ERROR_NONE);
1547
1548         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1549
1550         surf = (struct _tbm_surface *)surface;
1551         width = surf->info.width;
1552
1553         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u)\n", surface, width);
1554
1555         _tbm_surface_mutex_unlock();
1556
1557         return width;
1558 }
1559
1560 unsigned int
1561 tbm_surface_internal_get_height(tbm_surface_h surface)
1562 {
1563         struct _tbm_surface *surf;
1564         unsigned int height;
1565
1566         _tbm_surface_mutex_lock();
1567         _tbm_set_last_result(TBM_ERROR_NONE);
1568
1569         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1570
1571         surf = (struct _tbm_surface *)surface;
1572         height = surf->info.height;
1573
1574         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) height(%u)\n", surface, height);
1575
1576         _tbm_surface_mutex_unlock();
1577
1578         return height;
1579
1580 }
1581
1582 tbm_format
1583 tbm_surface_internal_get_format(tbm_surface_h surface)
1584 {
1585         struct _tbm_surface *surf;
1586         tbm_format format;
1587
1588         _tbm_surface_mutex_lock();
1589         _tbm_set_last_result(TBM_ERROR_NONE);
1590
1591         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1592
1593         surf = (struct _tbm_surface *)surface;
1594         format = surf->info.format;
1595
1596         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1597
1598         _tbm_surface_mutex_unlock();
1599
1600         return format;
1601 }
1602
1603 int
1604 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1605 {
1606         struct _tbm_surface *surf;
1607         int bo_idx;
1608
1609         _tbm_surface_mutex_lock();
1610         _tbm_set_last_result(TBM_ERROR_NONE);
1611
1612         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1613         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1614
1615         surf = (struct _tbm_surface *)surface;
1616         bo_idx = surf->planes_bo_idx[plane_idx];
1617
1618         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1619
1620         _tbm_surface_mutex_unlock();
1621
1622         return bo_idx;
1623 }
1624
1625 int
1626 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1627                                    tbm_data_free data_free_func)
1628 {
1629         tbm_user_data *data;
1630
1631         _tbm_surface_mutex_lock();
1632         _tbm_set_last_result(TBM_ERROR_NONE);
1633
1634         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1635
1636         /* check if the data according to the key exist if so, return false. */
1637         data = user_data_lookup(&surface->user_data_list, key);
1638         if (data) {
1639                 TBM_TRACE_SURFACE_INTERNAL("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1640                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1641                 _tbm_surface_mutex_unlock();
1642                 return 0;
1643         }
1644
1645         data = user_data_create(key, data_free_func);
1646         if (!data) {
1647                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1648                 _tbm_surface_mutex_unlock();
1649                 return 0;
1650         }
1651
1652         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1653
1654         LIST_ADD(&data->item_link, &surface->user_data_list);
1655
1656         _tbm_surface_mutex_unlock();
1657
1658         return 1;
1659 }
1660
1661 int
1662 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1663                                    void *data)
1664 {
1665         tbm_user_data *old_data;
1666
1667         _tbm_surface_mutex_lock();
1668         _tbm_set_last_result(TBM_ERROR_NONE);
1669
1670         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1671
1672         old_data = user_data_lookup(&surface->user_data_list, key);
1673         if (!old_data) {
1674                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1675                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1676                 _tbm_surface_mutex_unlock();
1677                 return 0;
1678         }
1679
1680         if (old_data->data && old_data->free_func)
1681                 old_data->free_func(old_data->data);
1682
1683         old_data->data = data;
1684
1685         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1686
1687         _tbm_surface_mutex_unlock();
1688
1689         return 1;
1690 }
1691
1692 int
1693 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1694                                    void **data)
1695 {
1696         tbm_user_data *old_data;
1697
1698         _tbm_surface_mutex_lock();
1699         _tbm_set_last_result(TBM_ERROR_NONE);
1700
1701         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1702
1703         if (!data) {
1704                 TBM_ERR("error: tbm_surface(%p) key(%lu)\n", surface, key);
1705                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1706                 _tbm_surface_mutex_unlock();
1707                 return 0;
1708         }
1709         *data = NULL;
1710
1711         old_data = user_data_lookup(&surface->user_data_list, key);
1712         if (!old_data) {
1713                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1714                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1715                 _tbm_surface_mutex_unlock();
1716                 return 0;
1717         }
1718
1719         *data = old_data->data;
1720
1721         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1722
1723         _tbm_surface_mutex_unlock();
1724
1725         return 1;
1726 }
1727
1728 int
1729 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1730                                       unsigned long key)
1731 {
1732         tbm_user_data *old_data = (void *)0;
1733
1734         _tbm_surface_mutex_lock();
1735         _tbm_set_last_result(TBM_ERROR_NONE);
1736
1737         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1738
1739         old_data = user_data_lookup(&surface->user_data_list, key);
1740         if (!old_data) {
1741                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1742                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1743                 _tbm_surface_mutex_unlock();
1744                 return 0;
1745         }
1746
1747         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1748
1749         user_data_delete(old_data);
1750
1751         _tbm_surface_mutex_unlock();
1752
1753         return 1;
1754 }
1755
1756 /* LCOV_EXCL_START */
1757 unsigned int
1758 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1759 {
1760         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1761
1762         return surface->debug_pid;
1763 }
1764
1765 void
1766 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1767 {
1768         _tbm_surface_mutex_lock();
1769         _tbm_set_last_result(TBM_ERROR_NONE);
1770
1771         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1772
1773         surface->debug_pid = pid;
1774
1775         _tbm_surface_mutex_unlock();
1776 }
1777
1778 static tbm_surface_debug_data *
1779 _tbm_surface_internal_debug_data_create(char *key, char *value)
1780 {
1781         tbm_surface_debug_data *debug_data = NULL;
1782
1783         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1784         if (!debug_data) {
1785                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1786                 TBM_ERR("fail to allocate the debug_data.");
1787                 return NULL;
1788         }
1789
1790         if (key) debug_data->key = strdup(key);
1791         if (value) debug_data->value = strdup(value);
1792
1793         return debug_data;
1794 }
1795
1796 static void
1797 _tbm_surface_internal_debug_data_value_update(tbm_surface_debug_data *debug_data, char *value)
1798 {
1799         if (!debug_data->value && !value)
1800                 return;
1801
1802         if (debug_data->value && value && !strncmp(debug_data->value, value, strlen(debug_data->value)))
1803                 return;
1804
1805         if (debug_data->value)
1806                 free(debug_data->value);
1807
1808         if (value)
1809                 debug_data->value = strdup(value);
1810         else
1811                 debug_data->value = NULL;
1812 }
1813
1814 static tbm_surface_debug_data *
1815 _tbm_surface_internal_debug_data_find(struct list_head *list, char *key)
1816 {
1817         tbm_surface_debug_data *debug_data = NULL;
1818
1819         if (LIST_IS_EMPTY(list))
1820                 return NULL;
1821
1822         LIST_FOR_EACH_ENTRY(debug_data, list, item_link) {
1823                 if (!strncmp(debug_data->key, key, strlen(debug_data->key)))
1824                         return debug_data;
1825         }
1826
1827         return NULL;
1828 }
1829
1830 int
1831 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1832 {
1833         tbm_surface_debug_data *debug_data = NULL;
1834         tbm_bufmgr bufmgr = NULL;
1835
1836         _tbm_surface_mutex_lock();
1837         _tbm_set_last_result(TBM_ERROR_NONE);
1838
1839         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1840         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1841
1842         bufmgr = surface->bufmgr;
1843
1844         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1845
1846         debug_data = _tbm_surface_internal_debug_data_find(&surface->debug_data_list, key);
1847         if (debug_data) {
1848                 _tbm_surface_internal_debug_data_value_update(debug_data, value);
1849         } else {
1850                 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1851                 if (!debug_data) {
1852                         TBM_ERR("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1853                         _tbm_surface_mutex_unlock();
1854                         return 0;
1855                 }
1856
1857                 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1858         }
1859
1860         /* add new debug key to list */
1861         debug_data = _tbm_surface_internal_debug_data_find(&bufmgr->debug_key_list, key);
1862         if (!debug_data) {
1863                 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1864                 if (debug_data)
1865                         LIST_ADDTAIL(&debug_data->item_link, &bufmgr->debug_key_list);
1866         }
1867
1868         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1869
1870         _tbm_surface_mutex_unlock();
1871
1872         return 1;
1873 }
1874
1875 char *
1876 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1877 {
1878         tbm_surface_debug_data *old_data = NULL;
1879
1880         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1881
1882         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1883                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1884                         if (!strcmp(old_data->key, key))
1885                                 return old_data->value;
1886                 }
1887         }
1888
1889         return NULL;
1890 }
1891
1892 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1893 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1894
1895 struct _tbm_surface_dump_buf_info {
1896         int index;
1897         tbm_bo bo;
1898         int size;
1899         int dirty;
1900         int dirty_shm;
1901         int shm_stride;
1902         int shm_h;
1903         char name[1024];
1904
1905         tbm_surface_info_s info;
1906
1907         struct list_head link;
1908 };
1909
1910 struct _tbm_surface_dump_info {
1911         char *path;  // copy???
1912         int dump_max;
1913         int count;
1914         struct list_head *link;
1915         struct list_head surface_list; /* link of surface */
1916 };
1917
1918 static tbm_surface_dump_info *g_dump_info = NULL;
1919 static const char *dump_postfix[2] = {"png", "yuv"};
1920 static double scale_factor;
1921
1922 static void
1923 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1924                                 void *data2, int size2, void *data3, int size3)
1925 {
1926         FILE *fp;
1927         unsigned int *blocks;
1928
1929         if (_tbm_surface_check_file_is_symbolic_link(file))
1930                 TBM_ERR("%s is symbolic link\n", file);
1931
1932         fp = fopen(file, "w+");
1933         TBM_RETURN_IF_FAIL(fp != NULL);
1934
1935         blocks = (unsigned int *)data1;
1936         fwrite(blocks, 1, size1, fp);
1937
1938         if (size2 > 0) {
1939                 blocks = (unsigned int *)data2;
1940                 fwrite(blocks, 1, size2, fp);
1941         }
1942
1943         if (size3 > 0) {
1944                 blocks = (unsigned int *)data3;
1945                 fwrite(blocks, 1, size3, fp);
1946         }
1947
1948         fclose(fp);
1949 }
1950
1951 static void
1952 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height, int stride, int format)
1953 {
1954         unsigned int *blocks = (unsigned int *)data;
1955         FILE *fp;
1956         int pixel_size;
1957         png_bytep *row_pointers;
1958         int depth = 8, y;
1959
1960         if (_tbm_surface_check_file_is_symbolic_link(file))
1961                 TBM_ERR("%s is symbolic link\n", file);
1962
1963         fp = fopen(file, "wb");
1964         TBM_RETURN_IF_FAIL(fp != NULL);
1965
1966         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1967                                                         NULL, NULL, NULL);
1968         if (!pPngStruct) {
1969                 TBM_ERR("fail to create a png write structure.\n");
1970                 fclose(fp);
1971                 return;
1972         }
1973
1974         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1975         if (!pPngInfo) {
1976                 TBM_ERR("fail to create a png info structure.\n");
1977                 png_destroy_write_struct(&pPngStruct, NULL);
1978                 fclose(fp);
1979                 return;
1980         }
1981
1982         if (setjmp(png_jmpbuf(pPngStruct))) {
1983                 /* if png has problem of writing the file, we get here */
1984                 TBM_ERR("fail to write png file.\n");
1985                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1986                 fclose(fp);
1987                 return;
1988         }
1989
1990         png_init_io(pPngStruct, fp);
1991         if (format == TBM_FORMAT_XRGB8888) {
1992                 pixel_size = 3;
1993                 png_set_IHDR(pPngStruct,
1994                                 pPngInfo,
1995                                 width,
1996                                 height,
1997                                 depth,
1998                                 PNG_COLOR_TYPE_RGB,
1999                                 PNG_INTERLACE_NONE,
2000                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
2001         } else {
2002                 pixel_size = 4;
2003                 png_set_IHDR(pPngStruct,
2004                                 pPngInfo,
2005                                 width,
2006                                 height,
2007                                 depth,
2008                                 PNG_COLOR_TYPE_RGBA,
2009                                 PNG_INTERLACE_NONE,
2010                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
2011         }
2012
2013         png_set_bgr(pPngStruct);
2014         png_write_info(pPngStruct, pPngInfo);
2015
2016         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
2017         if (!row_pointers) {
2018                 TBM_ERR("fail to allocate the png row_pointers.\n");
2019                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
2020                 fclose(fp);
2021                 return;
2022         }
2023
2024         for (y = 0; y < height; ++y) {
2025                 png_bytep row;
2026                 int x = 0;
2027
2028                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
2029                 if (!row) {
2030                         TBM_ERR("fail to allocate the png row.\n");
2031                         for (x = 0; x < y; x++)
2032                                 png_free(pPngStruct, row_pointers[x]);
2033                         png_free(pPngStruct, row_pointers);
2034                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
2035                         fclose(fp);
2036                         return;
2037                 }
2038                 row_pointers[y] = (png_bytep)row;
2039
2040                 for (x = 0; x < width; ++x) {
2041                         unsigned int curBlock = blocks[(y * (stride >> 2)) + x];
2042
2043                         if (pixel_size == 3) { // XRGB8888 or XBGR8888
2044                                 if (format == TBM_FORMAT_XRGB8888) {
2045                                         row[x * pixel_size] = (curBlock & 0xFF);
2046                                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
2047                                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
2048                                 } else {
2049                                         row[x * pixel_size] = (curBlock >> 16) & 0xFF;
2050                                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
2051                                         row[2 + x * pixel_size] = (curBlock & 0xFF);
2052                                 }
2053                         } else { // ARGB8888 or ABGR8888
2054                                 if (format == TBM_FORMAT_ARGB8888) {
2055                                         row[x * pixel_size] = (curBlock & 0xFF);
2056                                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
2057                                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
2058                                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
2059                                 } else {
2060                                         row[x * pixel_size] = (curBlock >> 16) & 0xFF;
2061                                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
2062                                         row[2 + x * pixel_size] =  (curBlock & 0xFF);
2063                                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
2064                                 }
2065                         }
2066                 }
2067         }
2068
2069         png_write_image(pPngStruct, row_pointers);
2070         png_write_end(pPngStruct, pPngInfo);
2071
2072         for (y = 0; y < height; y++)
2073                 png_free(pPngStruct, row_pointers[y]);
2074         png_free(pPngStruct, row_pointers);
2075
2076         png_destroy_write_struct(&pPngStruct, &pPngInfo);
2077
2078         fclose(fp);
2079 }
2080
2081 void
2082 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
2083 {
2084         TBM_RETURN_IF_FAIL(path != NULL);
2085         TBM_RETURN_IF_FAIL(w > 0);
2086         TBM_RETURN_IF_FAIL(h > 0);
2087         TBM_RETURN_IF_FAIL(count > 0);
2088
2089         tbm_surface_dump_buf_info *buf_info = NULL;
2090         tbm_surface_h tbm_surface;
2091         tbm_surface_info_s info;
2092         int buffer_size, i;
2093
2094         /* check running */
2095         if (g_dump_info) {
2096                 TBM_WRN("waring already running the tbm_surface_internal_dump.\n");
2097                 return;
2098         }
2099
2100         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
2101         TBM_RETURN_IF_FAIL(g_dump_info);
2102
2103         LIST_INITHEAD(&g_dump_info->surface_list);
2104         g_dump_info->count = 0;
2105         g_dump_info->dump_max = count;
2106
2107         /* get buffer size */
2108         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
2109         if (tbm_surface == NULL) {
2110                 TBM_ERR("tbm_surface_create fail\n");
2111                 free(g_dump_info);
2112                 g_dump_info = NULL;
2113                 return;
2114         }
2115
2116         if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
2117                 TBM_ERR("tbm_surface_get_info fail\n");
2118                 tbm_surface_destroy(tbm_surface);
2119                 free(g_dump_info);
2120                 g_dump_info = NULL;
2121                 return;
2122         }
2123         buffer_size = info.size;
2124         tbm_surface_destroy(tbm_surface);
2125
2126         /* create dump lists */
2127         for (i = 0; i < count; i++) {
2128                 tbm_bo bo = NULL;
2129
2130                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
2131                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
2132
2133                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
2134                 if (bo == NULL) {
2135                         TBM_ERR("fail to allocate the tbm_bo[%d]\n", i);
2136                         free(buf_info);
2137                         goto fail;
2138                 }
2139
2140                 buf_info->index = i;
2141                 buf_info->bo = bo;
2142                 buf_info->size = buffer_size;
2143
2144                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
2145         }
2146
2147         g_dump_info->path = path;
2148         g_dump_info->link = &g_dump_info->surface_list;
2149
2150         scale_factor = 0.0;
2151
2152         TBM_INFO("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
2153
2154         return;
2155
2156 fail:
2157         /* free resources */
2158         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2159                 tbm_surface_dump_buf_info *tmp;
2160
2161                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2162                         tbm_bo_unref(buf_info->bo);
2163                         LIST_DEL(&buf_info->link);
2164                         free(buf_info);
2165                 }
2166         }
2167
2168         TBM_ERR("Dump Start fail.. path:%s\n", g_dump_info->path);
2169
2170         free(g_dump_info);
2171         g_dump_info = NULL;
2172
2173         return;
2174 }
2175
2176 void
2177 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
2178 {
2179         if (scale > 0.0) {
2180                 w *= scale;
2181                 h *= scale;
2182         }
2183
2184         tbm_surface_internal_dump_start(path, w, h, count);
2185         scale_factor = scale;
2186 }
2187
2188 void
2189 tbm_surface_internal_dump_end(void)
2190 {
2191         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
2192         tbm_bo_handle bo_handle;
2193
2194         if (!g_dump_info)
2195                 return;
2196
2197         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2198                 free(g_dump_info);
2199                 g_dump_info = NULL;
2200                 return;
2201         }
2202
2203         /* make files */
2204         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2205                 char file[2048];
2206
2207                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
2208                 if (bo_handle.ptr == NULL) {
2209                         tbm_bo_unref(buf_info->bo);
2210                         LIST_DEL(&buf_info->link);
2211                         free(buf_info);
2212                         continue;
2213                 }
2214
2215                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
2216                 TBM_INFO("Dump File.. %s generated.\n", file);
2217
2218                 if (buf_info->dirty) {
2219                         void *ptr1 = NULL, *ptr2 = NULL;
2220
2221                         switch (buf_info->info.format) {
2222                         case TBM_FORMAT_ARGB8888:
2223                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2224                                                         buf_info->info.planes[0].stride >> 2,
2225                                                         buf_info->info.height,
2226                                                         buf_info->info.planes[0].stride,
2227                                                         TBM_FORMAT_ARGB8888);
2228                                 break;
2229                         case TBM_FORMAT_XRGB8888:
2230                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2231                                                         buf_info->info.planes[0].stride >> 2,
2232                                                         buf_info->info.height,
2233                                                         buf_info->info.planes[0].stride,
2234                                                         TBM_FORMAT_XRGB8888);
2235                                 break;
2236                         case TBM_FORMAT_ABGR8888:
2237                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2238                                                         buf_info->info.planes[0].stride >> 2,
2239                                                         buf_info->info.height,
2240                                                         buf_info->info.planes[0].stride,
2241                                                         TBM_FORMAT_ABGR8888);
2242                                 break;
2243                         case TBM_FORMAT_XBGR8888:
2244                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2245                                                         buf_info->info.planes[0].stride >> 2,
2246                                                         buf_info->info.height,
2247                                                         buf_info->info.planes[0].stride,
2248                                                         TBM_FORMAT_XBGR8888);
2249                                 break;
2250                         case TBM_FORMAT_YVU420:
2251                         case TBM_FORMAT_YUV420:
2252                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2253                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
2254                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2255                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2256                                                         ptr1,
2257                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2258                                                         ptr2,
2259                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
2260                                 break;
2261                         case TBM_FORMAT_NV12:
2262                         case TBM_FORMAT_NV21:
2263                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2264                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2265                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2266                                                         ptr1,
2267                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2268                                                         NULL, 0);
2269                                 break;
2270                         case TBM_FORMAT_YUYV:
2271                         case TBM_FORMAT_UYVY:
2272                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2273                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2274                                                         NULL, 0, NULL, 0);
2275                                 break;
2276                         default:
2277                                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
2278                                 break;
2279                         }
2280                 } else if (buf_info->dirty_shm)
2281                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2282                                                         buf_info->shm_stride >> 2,
2283                                                         buf_info->shm_h,
2284                                                         buf_info->shm_stride, 0);
2285
2286                 tbm_bo_unmap(buf_info->bo);
2287                 tbm_bo_unref(buf_info->bo);
2288                 LIST_DEL(&buf_info->link);
2289                 free(buf_info);
2290         }
2291
2292         free(g_dump_info);
2293         g_dump_info = NULL;
2294
2295         TBM_INFO("Dump End..\n");
2296 }
2297
2298 static pixman_format_code_t
2299 _tbm_surface_internal_pixman_format_get(tbm_format format)
2300 {
2301         switch (format) {
2302         case TBM_FORMAT_ARGB8888:
2303         case TBM_FORMAT_ABGR8888:
2304                 return PIXMAN_a8r8g8b8;
2305         case TBM_FORMAT_XRGB8888:
2306         case TBM_FORMAT_XBGR8888:
2307                 return PIXMAN_x8r8g8b8;
2308         default:
2309                 return 0;
2310         }
2311
2312         return 0;
2313 }
2314
2315 /**
2316  * This function supports only if a buffer has below formats.
2317  * - TBM_FORMAT_ARGB8888
2318  * - TBM_FORMAT_XRGB8888
2319  * - TBM_FORMAT_ABGR8888
2320  * - TBM_FORMAT_XBGR8888
2321  */
2322 static tbm_surface_error_e
2323 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
2324                                                                    int format, int src_stride, int src_w, int src_h,
2325                                                                    int dst_stride, int dst_w, int dst_h)
2326 {
2327         pixman_image_t *src_img = NULL, *dst_img = NULL;
2328         pixman_format_code_t pixman_format;
2329         pixman_transform_t t;
2330         struct pixman_f_transform ft;
2331         double scale_x, scale_y;
2332
2333         TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2334         TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2335
2336         pixman_format = _tbm_surface_internal_pixman_format_get(format);
2337         TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2338
2339         /* src */
2340         src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2341                                                                            (uint32_t*)src_ptr, src_stride);
2342         TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2343
2344         /* dst */
2345         dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2346                                                                            (uint32_t*)dst_ptr, dst_stride);
2347         TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2348
2349         pixman_f_transform_init_identity(&ft);
2350
2351         scale_x = (double)src_w / dst_w;
2352         scale_y = (double)src_h / dst_h;
2353
2354         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2355         pixman_f_transform_translate(&ft, NULL, 0, 0);
2356         pixman_transform_from_pixman_f_transform(&t, &ft);
2357         pixman_image_set_transform(src_img, &t);
2358
2359         pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2360                                                    0, 0, 0, 0, 0, 0, dst_w, dst_h);
2361
2362         pixman_image_unref(src_img);
2363         pixman_image_unref(dst_img);
2364
2365         return TBM_SURFACE_ERROR_NONE;
2366
2367 cant_convert:
2368         if (src_img)
2369                 pixman_image_unref(src_img);
2370
2371         return TBM_SURFACE_ERROR_INVALID_OPERATION;
2372 }
2373
2374 #define MAX_BOS         4       // This value is came from bos[4] in struct _tbm_surface
2375 #define KEY_LEN         5       // "_XXXX"
2376 #define KEYS_LEN        KEY_LEN * MAX_BOS
2377
2378 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2379 {
2380         char *keys, temp_key[KEY_LEN + 1];
2381         struct _tbm_surface *surf;
2382         int i, num_bos;
2383         tbm_bo bo;
2384
2385         _tbm_surface_mutex_lock();
2386
2387         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2388
2389         surf = (struct _tbm_surface *)surface;
2390
2391         num_bos = surf->num_bos;
2392         if (num_bos > MAX_BOS)
2393                 num_bos = MAX_BOS;
2394
2395         keys = calloc(KEYS_LEN + 1, sizeof(char));
2396         if (!keys) {
2397                 TBM_ERR("Failed to alloc memory");
2398                 _tbm_surface_mutex_unlock();
2399                 return NULL;
2400         }
2401
2402         for (i = 0; i < num_bos; i++) {
2403                 memset(temp_key, 0x00, KEY_LEN + 1);
2404                 bo = surf->bos[i];
2405                 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2406                 strncat(keys, temp_key, KEY_LEN + 1);
2407         }
2408
2409         _tbm_surface_mutex_unlock();
2410
2411         return keys;
2412 }
2413
2414 static void _tbm_surface_internal_put_keys(char *keys)
2415 {
2416         if (keys)
2417                 free(keys);
2418 }
2419
2420 void
2421 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2422 {
2423         TBM_RETURN_IF_FAIL(surface != NULL);
2424         TBM_RETURN_IF_FAIL(type != NULL);
2425
2426         tbm_surface_dump_buf_info *buf_info;
2427         struct list_head *next_link;
2428         tbm_surface_info_s info;
2429         tbm_bo_handle bo_handle;
2430         const char *postfix;
2431         const char *format = NULL;
2432         char *keys;
2433         int ret;
2434
2435         if (!g_dump_info)
2436                 return;
2437
2438         next_link = g_dump_info->link->next;
2439         TBM_RETURN_IF_FAIL(next_link != NULL);
2440
2441         if (next_link == &g_dump_info->surface_list) {
2442                 next_link = next_link->next;
2443                 TBM_RETURN_IF_FAIL(next_link != NULL);
2444         }
2445
2446         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2447         TBM_RETURN_IF_FAIL(buf_info != NULL);
2448
2449         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2450         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2451
2452         if (scale_factor > 0.0) {
2453                 const int bpp = 4;
2454
2455                 if ((info.format != TBM_FORMAT_ARGB8888) && (info.format != TBM_FORMAT_XRGB8888) &&
2456                     (info.format != TBM_FORMAT_ABGR8888) && (info.format != TBM_FORMAT_XBGR8888)) {
2457                         TBM_WRN("Dump with scale skip. unsupported format(%s)\n",
2458                                           _tbm_surface_internal_format_to_str(info.format));
2459                         tbm_surface_unmap(surface);
2460                         return;
2461                 }
2462
2463                 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2464
2465                 buf_info->info.width = info.width * scale_factor;
2466                 buf_info->info.height = info.height * scale_factor;
2467                 buf_info->info.format = info.format;
2468                 buf_info->info.bpp = _tbm_surface_internal_get_bpp(buf_info->info.format);
2469                 if (!buf_info->info.bpp) {
2470                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
2471                         tbm_surface_unmap(surface);
2472                         return;
2473                 }
2474                 buf_info->info.num_planes = 1;
2475                 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2476                 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2477
2478                 if (buf_info->info.size > buf_info->size) {
2479                         TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)\n",
2480                                         buf_info->info.size, buf_info->size);
2481                         tbm_surface_unmap(surface);
2482                         return;
2483                 }
2484         } else {
2485                 if (info.size > buf_info->size) {
2486                         TBM_WRN("Dump skip. surface over created buffer size(%u, %d)\n",
2487                                         info.size, buf_info->size);
2488                         tbm_surface_unmap(surface);
2489                         return;
2490                 }
2491
2492                 /* make the file information */
2493                 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2494         }
2495
2496         if ((info.format == TBM_FORMAT_ARGB8888) || (info.format == TBM_FORMAT_XRGB8888) ||
2497                 (info.format == TBM_FORMAT_ABGR8888) || (info.format == TBM_FORMAT_XBGR8888)) {
2498                 postfix = dump_postfix[0];
2499                 format = _tbm_surface_internal_format_to_str(info.format);
2500         } else
2501                 postfix = dump_postfix[1];
2502
2503         keys = _tbm_surface_internal_get_keys(surface);
2504         if (!keys) {
2505                 TBM_ERR("fail to get keys");
2506                 tbm_surface_unmap(surface);
2507                 return;
2508         }
2509
2510         /* dump */
2511         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2512         if (!bo_handle.ptr) {
2513                 TBM_ERR("fail to map bo");
2514                 _tbm_surface_internal_put_keys(keys);
2515                 tbm_surface_unmap(surface);
2516                 return;
2517         }
2518         memset(bo_handle.ptr, 0x00, buf_info->size);
2519
2520         switch (info.format) {
2521         case TBM_FORMAT_ARGB8888:
2522         case TBM_FORMAT_XRGB8888:
2523         case TBM_FORMAT_ABGR8888:
2524         case TBM_FORMAT_XBGR8888:
2525                 snprintf(buf_info->name, sizeof(buf_info->name),
2526                                 "%10.3f_%03d%s_%p_%s-%s.%s",
2527                                  _tbm_surface_internal_get_time(),
2528                                  g_dump_info->count++, keys, surface, format, type, postfix);
2529
2530                 if (scale_factor > 0.0) {
2531                         ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2532                                                                                                          bo_handle.ptr,
2533                                                                                                          buf_info->info.format,
2534                                                                                                          info.planes[0].stride,
2535                                                                                                          info.width, info.height,
2536                                                                                                          buf_info->info.planes[0].stride,
2537                                                                                                          buf_info->info.width,
2538                                                                                                          buf_info->info.height);
2539                         if (ret != TBM_SURFACE_ERROR_NONE) {
2540                                 TBM_ERR("fail to scale buffer");
2541                                 tbm_bo_unmap(buf_info->bo);
2542                                 _tbm_surface_internal_put_keys(keys);
2543                                 tbm_surface_unmap(surface);
2544                                 return;
2545                         }
2546                 } else
2547                         memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2548                 break;
2549         case TBM_FORMAT_YVU420:
2550         case TBM_FORMAT_YUV420:
2551                 snprintf(buf_info->name, sizeof(buf_info->name),
2552                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2553                                  _tbm_surface_internal_get_time(),
2554                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2555                                 info.height, FOURCC_STR(info.format), postfix);
2556                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2557                 bo_handle.ptr += info.planes[0].stride * info.height;
2558                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2559                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2560                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2561                 break;
2562         case TBM_FORMAT_NV12:
2563         case TBM_FORMAT_NV21:
2564                 snprintf(buf_info->name, sizeof(buf_info->name),
2565                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2566                                  _tbm_surface_internal_get_time(),
2567                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2568                                 info.height, FOURCC_STR(info.format), postfix);
2569                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2570                 bo_handle.ptr += info.planes[0].stride * info.height;
2571                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2572                 break;
2573         case TBM_FORMAT_YUYV:
2574         case TBM_FORMAT_UYVY:
2575                 snprintf(buf_info->name, sizeof(buf_info->name),
2576                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2577                                  _tbm_surface_internal_get_time(),
2578                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2579                                 info.height, FOURCC_STR(info.format), postfix);
2580                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2581                 break;
2582         default:
2583                 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2584                 tbm_bo_unmap(buf_info->bo);
2585                 _tbm_surface_internal_put_keys(keys);
2586                 tbm_surface_unmap(surface);
2587                 return;
2588         }
2589
2590         tbm_bo_unmap(buf_info->bo);
2591
2592         _tbm_surface_internal_put_keys(keys);
2593
2594         tbm_surface_unmap(surface);
2595
2596         buf_info->dirty = 1;
2597         buf_info->dirty_shm = 0;
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 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2608                                                 const char *type)
2609 {
2610         TBM_RETURN_IF_FAIL(ptr != NULL);
2611         TBM_RETURN_IF_FAIL(w > 0);
2612         TBM_RETURN_IF_FAIL(h > 0);
2613         TBM_RETURN_IF_FAIL(stride > 0);
2614         TBM_RETURN_IF_FAIL(type != NULL);
2615
2616         tbm_surface_dump_buf_info *buf_info;
2617         struct list_head *next_link;
2618         tbm_bo_handle bo_handle;
2619         int ret, size, dw = 0, dh = 0, dstride = 0;
2620
2621         if (!g_dump_info)
2622                 return;
2623
2624         next_link = g_dump_info->link->next;
2625         TBM_RETURN_IF_FAIL(next_link != NULL);
2626
2627         if (next_link == &g_dump_info->surface_list) {
2628                 next_link = next_link->next;
2629                 TBM_RETURN_IF_FAIL(next_link != NULL);
2630         }
2631
2632         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2633         TBM_RETURN_IF_FAIL(buf_info != NULL);
2634
2635         if (scale_factor > 0.0) {
2636                 const int bpp = 4;
2637
2638                 dw = w * scale_factor;
2639                 dh = h * scale_factor;
2640                 dstride = dw * bpp;
2641                 size = dstride * dh;
2642         } else
2643                 size = stride * h;
2644
2645         if (size > buf_info->size) {
2646                 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2647                                 size, buf_info->size);
2648                 return;
2649         }
2650
2651         /* dump */
2652         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2653         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2654
2655         memset(bo_handle.ptr, 0x00, buf_info->size);
2656         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2657
2658         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2659                          _tbm_surface_internal_get_time(),
2660                          g_dump_info->count++, type, dump_postfix[0]);
2661         if (scale_factor > 0.0) {
2662                 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2663                                                                                                  TBM_FORMAT_ARGB8888, stride,
2664                                                                                                  w, h, dstride, dw, dh);
2665                 if (ret != TBM_SURFACE_ERROR_NONE) {
2666                         TBM_ERR("fail to scale buffer");
2667                         tbm_bo_unmap(buf_info->bo);
2668                         return;
2669                 }
2670                 buf_info->shm_stride = dstride;
2671                 buf_info->shm_h = dh;
2672         } else {
2673                 memcpy(bo_handle.ptr, ptr, size);
2674                 buf_info->shm_stride = stride;
2675                 buf_info->shm_h = h;
2676         }
2677
2678         tbm_bo_unmap(buf_info->bo);
2679
2680         buf_info->dirty = 0;
2681         buf_info->dirty_shm = 1;
2682
2683         if (g_dump_info->count == 1000)
2684                 g_dump_info->count = 0;
2685
2686         g_dump_info->link = next_link;
2687
2688         TBM_INFO("Dump %s \n", buf_info->name);
2689 }
2690
2691 int
2692 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2693 {
2694         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2695         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2696         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2697
2698         tbm_surface_info_s info;
2699         const char *postfix;
2700         int ret;
2701         char file[1024];
2702
2703         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2704         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2705
2706         if ((info.format == TBM_FORMAT_ARGB8888) || (info.format == TBM_FORMAT_XRGB8888) ||
2707             (info.format == TBM_FORMAT_ABGR8888) || (info.format == TBM_FORMAT_XBGR8888))
2708                 postfix = dump_postfix[0];
2709         else
2710                 postfix = dump_postfix[1];
2711
2712         if (strcmp(postfix, type)) {
2713                 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2714                 tbm_surface_unmap(surface);
2715                 return 0;
2716         }
2717
2718         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2719
2720         if (!access(file, 0)) {
2721                 TBM_ERR("can't capture  buffer, exist file %s", file);
2722                 tbm_surface_unmap(surface);
2723                 return 0;
2724         }
2725
2726         switch (info.format) {
2727         case TBM_FORMAT_ARGB8888:
2728                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2729                                                         info.width,
2730                                                         info.height,
2731                                                         info.planes[0].stride,
2732                                                         TBM_FORMAT_ARGB8888);
2733                 break;
2734         case TBM_FORMAT_XRGB8888:
2735                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2736                                                         info.width,
2737                                                         info.height,
2738                                                         info.planes[0].stride,
2739                                                         TBM_FORMAT_XRGB8888);
2740                 break;
2741         case TBM_FORMAT_ABGR8888:
2742                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2743                                                         info.width,
2744                                                         info.height,
2745                                                         info.planes[0].stride,
2746                                                         TBM_FORMAT_ABGR8888);
2747                 break;
2748         case TBM_FORMAT_XBGR8888:
2749                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2750                                                         info.width,
2751                                                         info.height,
2752                                                         info.planes[0].stride,
2753                                                         TBM_FORMAT_XBGR8888);
2754                 break;
2755         case TBM_FORMAT_YVU420:
2756         case TBM_FORMAT_YUV420:
2757                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2758                                 info.planes[0].stride * info.height,
2759                                 info.planes[1].ptr,
2760                                 info.planes[1].stride * (info.height >> 1),
2761                                 info.planes[2].ptr,
2762                                 info.planes[2].stride * (info.height >> 1));
2763                 break;
2764         case TBM_FORMAT_NV12:
2765         case TBM_FORMAT_NV21:
2766                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2767                                         info.planes[0].stride * info.height,
2768                                         info.planes[1].ptr,
2769                                         info.planes[1].stride * (info.height >> 1),
2770                                         NULL, 0);
2771                 break;
2772         case TBM_FORMAT_YUYV:
2773         case TBM_FORMAT_UYVY:
2774                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2775                                         info.planes[0].stride * info.height,
2776                                         NULL, 0, NULL, 0);
2777                 break;
2778         default:
2779                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2780                 tbm_surface_unmap(surface);
2781                 return 0;
2782         }
2783
2784         tbm_surface_unmap(surface);
2785
2786         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2787
2788         return 1;
2789 }
2790
2791 int
2792 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2793                                                 const char *path, const char *name, const char *type)
2794 {
2795         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2796         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2797         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2798         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2799         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2800         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2801
2802         char file[1024];
2803
2804         if (strcmp(dump_postfix[0], type)) {
2805                 TBM_ERR("Not supported type:%s'", type);
2806                 return 0;
2807         }
2808
2809         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2810
2811         if (!access(file, 0)) {
2812                 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2813                 return 0;
2814         }
2815
2816         _tbm_surface_internal_dump_file_png(file, ptr, w, h, stride, 0);
2817
2818         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2819
2820         return 1;
2821 }
2822
2823 int
2824 tbm_surface_internal_set_damage(tbm_surface_h surface, int x, int y, int width, int height)
2825 {
2826         struct _tbm_surface *surf;
2827
2828         _tbm_surface_mutex_lock();
2829         _tbm_set_last_result(TBM_ERROR_NONE);
2830
2831         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, 0);
2832         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, 0);
2833         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2834
2835         surf = (struct _tbm_surface *)surface;
2836
2837         surf->damage.x = x;
2838         surf->damage.y = y;
2839         surf->damage.width = width;
2840         surf->damage.height = height;
2841
2842         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2843                                                         surface, x, y, width, height);
2844
2845         _tbm_surface_mutex_unlock();
2846
2847         return 1;
2848 }
2849
2850 int
2851 tbm_surface_internal_get_damage(tbm_surface_h surface, int *x, int *y, int *width, int *height)
2852 {
2853         struct _tbm_surface *surf;
2854
2855         _tbm_surface_mutex_lock();
2856         _tbm_set_last_result(TBM_ERROR_NONE);
2857
2858         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2859
2860         surf = (struct _tbm_surface *)surface;
2861
2862         if (x) *x = surf->damage.x;
2863         if (y) *y = surf->damage.y;
2864         if (width) *width = surf->damage.width;
2865         if (height) *height = surf->damage.height;
2866
2867         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2868                                                         surface, surf->damage.x, surf->damage.y, surf->damage.width, surf->damage.height);
2869
2870         _tbm_surface_mutex_unlock();
2871
2872         return 1;
2873 }
2874
2875 int
2876 tbm_surface_internal_add_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2877 {
2878         struct _tbm_surface *surf;
2879         tbm_surface_destroy_func_info *func_info = NULL;
2880
2881         _tbm_surface_mutex_lock();
2882         _tbm_set_last_result(TBM_ERROR_NONE);
2883
2884         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2885         TBM_SURFACE_RETURN_VAL_IF_FAIL(func != NULL, 0);
2886
2887         surf = (struct _tbm_surface *)surface;
2888         LIST_FOR_EACH_ENTRY(func_info, &surf->destroy_funcs, item_link) {
2889                 if (func_info->destroy_func == func && func_info->user_data == user_data) {
2890                         TBM_ERR("can't add twice");
2891                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
2892                         _tbm_surface_mutex_unlock();
2893                         return 0;
2894                 }
2895         }
2896
2897         func_info = calloc(1, sizeof(tbm_surface_destroy_func_info));
2898         if (func_info == NULL) {
2899                 TBM_ERR("alloc failed");
2900                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
2901                 _tbm_surface_mutex_unlock();
2902                 return 0;
2903         }
2904
2905         func_info->destroy_func = func;
2906         func_info->user_data = user_data;
2907
2908         LIST_ADDTAIL(&func_info->item_link, &surf->destroy_funcs);
2909
2910         _tbm_surface_mutex_unlock();
2911
2912         return 1;
2913 }
2914
2915 void
2916 tbm_surface_internal_remove_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2917 {
2918         struct _tbm_surface *surf;
2919         tbm_surface_destroy_func_info *func_info = NULL, *next = NULL;
2920
2921         _tbm_surface_mutex_lock();
2922         _tbm_set_last_result(TBM_ERROR_NONE);
2923
2924         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
2925         TBM_SURFACE_RETURN_IF_FAIL(func != NULL);
2926
2927         surf = (struct _tbm_surface *)surface;
2928         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &surf->destroy_funcs, item_link) {
2929                 if (func_info->destroy_func != func || func_info->user_data != user_data)
2930                         continue;
2931
2932                 LIST_DEL(&func_info->item_link);
2933                 free(func_info);
2934
2935                 _tbm_surface_mutex_unlock();
2936
2937                 return;
2938         }
2939
2940         _tbm_surface_mutex_unlock();
2941 }
2942
2943 tbm_surface_buffer_data *
2944 tbm_surface_internal_export(tbm_surface_h surface, tbm_error_e *error)
2945 {
2946         tbm_surface_buffer_data *buffer_data = NULL;
2947         struct _tbm_bufmgr *bufmgr;
2948
2949         _tbm_surface_mutex_lock();
2950
2951         bufmgr = g_surface_bufmgr;
2952         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr != NULL, NULL, error, TBM_ERROR_INVALID_OPERATION);
2953
2954         // this function supports when the module suppport surface_data.
2955         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(tbm_module_support_surface_data(bufmgr->module), NULL, error, TBM_ERROR_NOT_SUPPORTED);
2956
2957         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL, error, TBM_ERROR_INVALID_PARAMETER);
2958
2959         // export a surface
2960         buffer_data = tbm_surface_data_export(surface->surface_data, error);
2961         TBM_SURFACE_RETURN_VAL_ERR_IF_FAIL(buffer_data != NULL, NULL, *error);
2962
2963         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) buffer_data(%p)", surface, buffer_data);
2964
2965         _tbm_set_last_result(TBM_ERROR_NONE);
2966         _tbm_surface_mutex_unlock();
2967
2968         return buffer_data;
2969 }
2970
2971 tbm_surface_h
2972 tbm_surface_internal_import(tbm_surface_info_s *surface_info, tbm_surface_buffer_data *buffer_data, tbm_error_e *error)
2973 {
2974         struct _tbm_surface *surf;
2975         struct _tbm_bufmgr *bufmgr;
2976
2977         _tbm_surface_mutex_lock();
2978
2979         bufmgr = g_surface_bufmgr;
2980         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(bufmgr != NULL, NULL, error, TBM_ERROR_INVALID_OPERATION);
2981
2982         // this function supports when the module suppport surface_data.
2983         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(tbm_module_support_surface_data(bufmgr->module), NULL, error, TBM_ERROR_NOT_SUPPORTED);
2984
2985         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info != NULL, NULL, error, TBM_ERROR_INVALID_PARAMETER);
2986         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info->width > 0, NULL, error, TBM_ERROR_INVALID_PARAMETER);
2987         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(surface_info->height > 0, NULL, error, TBM_ERROR_INVALID_PARAMETER);
2988         TBM_SURFACE_RETURN_VAL_SET_ERR_IF_FAIL(buffer_data != NULL, NULL, error, TBM_ERROR_INVALID_PARAMETER);
2989
2990         // import a surface
2991         surf = _tbm_surface_internal_import_surface_data(bufmgr,
2992                                                                                                         (int)surface_info->width,
2993                                                                                                         (int)surface_info->height,
2994                                                                                                         (int)surface_info->format,
2995                                                                                                         buffer_data,
2996                                                                                                         error);
2997         TBM_SURFACE_RETURN_VAL_ERR_IF_FAIL(surf != NULL, NULL, *error);
2998
2999         LIST_INITHEAD(&surf->user_data_list);
3000         LIST_INITHEAD(&surf->debug_data_list);
3001         LIST_INITHEAD(&surf->destroy_funcs);
3002
3003         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
3004
3005         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)", surf);
3006
3007         _tbm_set_last_result(TBM_ERROR_NONE);
3008         _tbm_surface_mutex_unlock();
3009
3010         return (tbm_surface_h)surf;
3011 }
3012
3013 /*LCOV_EXCL_STOP*/