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