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