1 /**************************************************************************
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
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>
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:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
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.
30 **************************************************************************/
37 #include "tbm_bufmgr.h"
38 #include "tbm_bufmgr_int.h"
39 #include "tbm_surface_internal.h"
44 #define TBM_SURFACE_MAGIC 0xBF021234
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);
51 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
53 TBM_ERR("'%s' failed.\n", #cond);\
54 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
55 _tbm_surface_mutex_unlock();\
60 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
62 TBM_ERR("'%s' failed.\n", #cond);\
63 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
64 _tbm_surface_mutex_unlock();\
71 _tbm_surface_internal_get_time(void)
76 clock_gettime(CLOCK_MONOTONIC, &tp);
77 time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
83 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
85 LIST_DEL(&debug_data->item_link);
87 if (debug_data->key) free(debug_data->key);
88 if (debug_data->value) free(debug_data->value);
93 _tbm_surface_internal_format_to_str(tbm_format format)
97 return "TBM_FORMAT_C8";
98 case TBM_FORMAT_RGB332:
99 return "TBM_FORMAT_RGB332";
100 case TBM_FORMAT_BGR233:
101 return "TBM_FORMAT_BGR233";
102 case TBM_FORMAT_XRGB4444:
103 return "TBM_FORMAT_XRGB4444";
104 case TBM_FORMAT_XBGR4444:
105 return "TBM_FORMAT_XBGR4444";
106 case TBM_FORMAT_RGBX4444:
107 return "TBM_FORMAT_RGBX4444";
108 case TBM_FORMAT_BGRX4444:
109 return "TBM_FORMAT_BGRX4444";
110 case TBM_FORMAT_ARGB4444:
111 return "TBM_FORMAT_ARGB4444";
112 case TBM_FORMAT_ABGR4444:
113 return "TBM_FORMAT_ABGR4444";
114 case TBM_FORMAT_RGBA4444:
115 return "TBM_FORMAT_RGBA4444";
116 case TBM_FORMAT_BGRA4444:
117 return "TBM_FORMAT_BGRA4444";
118 case TBM_FORMAT_XRGB1555:
119 return "TBM_FORMAT_XRGB1555";
120 case TBM_FORMAT_XBGR1555:
121 return "TBM_FORMAT_XBGR1555";
122 case TBM_FORMAT_RGBX5551:
123 return "TBM_FORMAT_RGBX5551";
124 case TBM_FORMAT_BGRX5551:
125 return "TBM_FORMAT_BGRX5551";
126 case TBM_FORMAT_ARGB1555:
127 return "TBM_FORMAT_ARGB1555";
128 case TBM_FORMAT_ABGR1555:
129 return "TBM_FORMAT_ABGR1555";
130 case TBM_FORMAT_RGBA5551:
131 return "TBM_FORMAT_RGBA5551";
132 case TBM_FORMAT_BGRA5551:
133 return "TBM_FORMAT_BGRA5551";
134 case TBM_FORMAT_RGB565:
135 return "TBM_FORMAT_RGB565";
136 case TBM_FORMAT_BGR565:
137 return "TBM_FORMAT_BGR565";
138 case TBM_FORMAT_RGB888:
139 return "TBM_FORMAT_RGB888";
140 case TBM_FORMAT_BGR888:
141 return "TBM_FORMAT_BGR888";
142 case TBM_FORMAT_XRGB8888:
143 return "TBM_FORMAT_XRGB8888";
144 case TBM_FORMAT_XBGR8888:
145 return "TBM_FORMAT_XBGR8888";
146 case TBM_FORMAT_RGBX8888:
147 return "TBM_FORMAT_RGBX8888";
148 case TBM_FORMAT_BGRX8888:
149 return "TBM_FORMAT_BGRX8888";
150 case TBM_FORMAT_ARGB8888:
151 return "TBM_FORMAT_ARGB8888";
152 case TBM_FORMAT_ABGR8888:
153 return "TBM_FORMAT_ABGR8888";
154 case TBM_FORMAT_RGBA8888:
155 return "TBM_FORMAT_RGBA8888";
156 case TBM_FORMAT_BGRA8888:
157 return "TBM_FORMAT_BGRA8888";
158 case TBM_FORMAT_XRGB2101010:
159 return "TBM_FORMAT_XRGB2101010";
160 case TBM_FORMAT_XBGR2101010:
161 return "TBM_FORMAT_XBGR2101010";
162 case TBM_FORMAT_RGBX1010102:
163 return "TBM_FORMAT_RGBX1010102";
164 case TBM_FORMAT_BGRX1010102:
165 return "TBM_FORMAT_BGRX1010102";
166 case TBM_FORMAT_ARGB2101010:
167 return "TBM_FORMAT_ARGB2101010";
168 case TBM_FORMAT_ABGR2101010:
169 return "TBM_FORMAT_ABGR2101010";
170 case TBM_FORMAT_RGBA1010102:
171 return "TBM_FORMAT_RGBA1010102";
172 case TBM_FORMAT_BGRA1010102:
173 return "TBM_FORMAT_BGRA1010102";
174 case TBM_FORMAT_YUYV:
175 return "TBM_FORMAT_YUYV";
176 case TBM_FORMAT_YVYU:
177 return "TBM_FORMAT_YVYU";
178 case TBM_FORMAT_UYVY:
179 return "TBM_FORMAT_UYVY";
180 case TBM_FORMAT_VYUY:
181 return "TBM_FORMAT_VYUY";
182 case TBM_FORMAT_AYUV:
183 return "TBM_FORMAT_AYUV";
184 case TBM_FORMAT_NV12:
185 return "TBM_FORMAT_NV12";
186 case TBM_FORMAT_NV21:
187 return "TBM_FORMAT_NV21";
188 case TBM_FORMAT_NV16:
189 return "TBM_FORMAT_NV16";
190 case TBM_FORMAT_NV61:
191 return "TBM_FORMAT_NV61";
192 case TBM_FORMAT_YUV410:
193 return "TBM_FORMAT_YUV410";
194 case TBM_FORMAT_YVU410:
195 return "TBM_FORMAT_YVU410";
196 case TBM_FORMAT_YUV411:
197 return "TBM_FORMAT_YUV411";
198 case TBM_FORMAT_YVU411:
199 return "TBM_FORMAT_YVU411";
200 case TBM_FORMAT_YUV420:
201 return "TBM_FORMAT_YUV420";
202 case TBM_FORMAT_YVU420:
203 return "TBM_FORMAT_YVU420";
204 case TBM_FORMAT_YUV422:
205 return "TBM_FORMAT_YUV422";
206 case TBM_FORMAT_YVU422:
207 return "TBM_FORMAT_YVU422";
208 case TBM_FORMAT_YUV444:
209 return "TBM_FORMAT_YUV444";
210 case TBM_FORMAT_YVU444:
211 return "TBM_FORMAT_YVU444";
212 case TBM_FORMAT_NV12MT:
213 return "TBM_FORMAT_NV12MT";
220 _tbm_surface_mutex_lock(void)
222 pthread_mutex_lock(&tbm_surface_lock);
226 _tbm_surface_mutex_unlock(void)
228 pthread_mutex_unlock(&tbm_surface_lock);
232 _init_surface_bufmgr(void)
234 g_surface_bufmgr = tbm_bufmgr_init(-1);
238 _deinit_surface_bufmgr(void)
240 if (!g_surface_bufmgr)
243 tbm_bufmgr_deinit(g_surface_bufmgr);
244 g_surface_bufmgr = NULL;
249 _tbm_surface_internal_magic_check(tbm_surface_h surface)
251 if (surface->magic != TBM_SURFACE_MAGIC)
258 _tbm_surface_internal_is_valid(tbm_surface_h surface)
261 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
262 TBM_ERR("error: No valid tbm_surface is NULL\n");
266 if (!_tbm_surface_internal_magic_check(surface)) {
267 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
268 TBM_ERR("error: No valid tbm_surface(%p)\n", surface);
276 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
277 int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
279 TBM_RETURN_VAL_IF_FAIL(surface, 0);
280 TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
282 struct _tbm_surface *surf = (struct _tbm_surface *)surface;
283 struct _tbm_bufmgr *bufmgr = surf->bufmgr;
287 TBM_RETURN_VAL_IF_FAIL(bufmgr != NULL, 0);
288 TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
289 TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
290 TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
292 if (bufmgr->use_hal_tbm) {
293 error = (tbm_error_e)hal_tbm_bufmgr_get_plane_data(bufmgr->hal_bufmgr, (hal_tbm_format)surf->info.format,
294 plane_idx, surf->info.width, surf->info.height, size, offset, pitch, bo_idx);
295 /* LCOV_EXCL_START */
296 if (error == TBM_ERROR_NOT_SUPPORTED) {
297 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
299 } else if (error != TBM_ERROR_NONE) {
300 TBM_ERR("Fail to surface_get_plane_data. surface(%p) error(%d)\n", surface, error);
301 _tbm_set_last_result(error);
306 } else if (bufmgr->backend_module_data) {
307 if (!bufmgr->bufmgr_func->bufmgr_get_plane_data) {
308 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
312 error = bufmgr->bufmgr_func->bufmgr_get_plane_data(bufmgr->bufmgr_data, surf->info.format, plane_idx,
313 surf->info.width, surf->info.height, size, offset, pitch, bo_idx);
314 if (error != TBM_ERROR_NONE) {
315 /* LCOV_EXCL_START */
316 TBM_ERR("Fail to surface_get_plane_data. surface(%p) error(%d)\n", surface, error);
317 _tbm_set_last_result(error);
323 if (!bufmgr->backend->surface_get_plane_data) {
324 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
328 ret = bufmgr->backend->surface_get_plane_data(surf->info.width,
329 surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
331 /* LCOV_EXCL_START */
332 TBM_ERR("Fail to surface_get_plane_data. surface(%p)\n", surface);
333 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
343 _tbm_surface_internal_destroy(tbm_surface_h surface)
346 tbm_bufmgr bufmgr = surface->bufmgr;
347 tbm_user_data *old_data = NULL, *tmp = NULL;
348 tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
349 tbm_surface_destroy_func_info *func_info = NULL, *func_next = NULL;
351 if (!LIST_IS_EMPTY(&surface->destroy_funcs)) {
352 LIST_FOR_EACH_ENTRY_SAFE(func_info, func_next, &surface->destroy_funcs, item_link) {
353 func_info->destroy_func(surface, func_info->user_data);
355 TBM_DBG("free destroy_funcs %p\n", surface);
356 LIST_FOR_EACH_ENTRY_SAFE(func_info, func_next, &surface->destroy_funcs, item_link) {
357 LIST_DEL(&func_info->item_link);
362 /* destory the user_data_list */
363 if (!LIST_IS_EMPTY(&surface->user_data_list)) {
364 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
365 TBM_DBG("free user_data\n");
366 user_data_delete(old_data);
370 for (i = 0; i < surface->num_bos; i++) {
371 surface->bos[i]->surface = NULL;
373 tbm_bo_unref(surface->bos[i]);
374 surface->bos[i] = NULL;
377 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
378 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
379 _tbm_surface_internal_debug_data_delete(debug_old_data);
382 LIST_DEL(&surface->item_link);
388 if (bufmgr && LIST_IS_EMPTY(&bufmgr->surf_list)) {
389 LIST_DELINIT(&bufmgr->surf_list);
391 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
392 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
393 _tbm_surface_internal_debug_data_delete(debug_old_data);
397 _deinit_surface_bufmgr();
401 /* LCOV_EXCL_START */
403 _tbm_surface_check_file_is_symbolic_link(const char* path)
410 if (stat(path, &sb) != 0)
413 if (S_ISLNK(sb.st_mode))
421 _tbm_surface_internal_get_num_planes(tbm_format format)
427 case TBM_FORMAT_RGB332:
428 case TBM_FORMAT_BGR233:
429 case TBM_FORMAT_XRGB4444:
430 case TBM_FORMAT_XBGR4444:
431 case TBM_FORMAT_RGBX4444:
432 case TBM_FORMAT_BGRX4444:
433 case TBM_FORMAT_ARGB4444:
434 case TBM_FORMAT_ABGR4444:
435 case TBM_FORMAT_RGBA4444:
436 case TBM_FORMAT_BGRA4444:
437 case TBM_FORMAT_XRGB1555:
438 case TBM_FORMAT_XBGR1555:
439 case TBM_FORMAT_RGBX5551:
440 case TBM_FORMAT_BGRX5551:
441 case TBM_FORMAT_ARGB1555:
442 case TBM_FORMAT_ABGR1555:
443 case TBM_FORMAT_RGBA5551:
444 case TBM_FORMAT_BGRA5551:
445 case TBM_FORMAT_RGB565:
446 case TBM_FORMAT_BGR565:
447 case TBM_FORMAT_RGB888:
448 case TBM_FORMAT_BGR888:
449 case TBM_FORMAT_XRGB8888:
450 case TBM_FORMAT_XBGR8888:
451 case TBM_FORMAT_RGBX8888:
452 case TBM_FORMAT_BGRX8888:
453 case TBM_FORMAT_ARGB8888:
454 case TBM_FORMAT_ABGR8888:
455 case TBM_FORMAT_RGBA8888:
456 case TBM_FORMAT_BGRA8888:
457 case TBM_FORMAT_XRGB2101010:
458 case TBM_FORMAT_XBGR2101010:
459 case TBM_FORMAT_RGBX1010102:
460 case TBM_FORMAT_BGRX1010102:
461 case TBM_FORMAT_ARGB2101010:
462 case TBM_FORMAT_ABGR2101010:
463 case TBM_FORMAT_RGBA1010102:
464 case TBM_FORMAT_BGRA1010102:
465 case TBM_FORMAT_YUYV:
466 case TBM_FORMAT_YVYU:
467 case TBM_FORMAT_UYVY:
468 case TBM_FORMAT_VYUY:
469 case TBM_FORMAT_AYUV:
472 case TBM_FORMAT_NV12:
473 case TBM_FORMAT_NV12MT:
474 case TBM_FORMAT_NV21:
475 case TBM_FORMAT_NV16:
476 case TBM_FORMAT_NV61:
479 case TBM_FORMAT_YUV410:
480 case TBM_FORMAT_YVU410:
481 case TBM_FORMAT_YUV411:
482 case TBM_FORMAT_YVU411:
483 case TBM_FORMAT_YUV420:
484 case TBM_FORMAT_YVU420:
485 case TBM_FORMAT_YUV422:
486 case TBM_FORMAT_YVU422:
487 case TBM_FORMAT_YUV444:
488 case TBM_FORMAT_YVU444:
493 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
501 _tbm_surface_internal_get_bpp(tbm_format format)
508 case TBM_FORMAT_RGB332:
509 case TBM_FORMAT_BGR233:
512 case TBM_FORMAT_XRGB4444:
513 case TBM_FORMAT_XBGR4444:
514 case TBM_FORMAT_RGBX4444:
515 case TBM_FORMAT_BGRX4444:
516 case TBM_FORMAT_ARGB4444:
517 case TBM_FORMAT_ABGR4444:
518 case TBM_FORMAT_RGBA4444:
519 case TBM_FORMAT_BGRA4444:
520 case TBM_FORMAT_XRGB1555:
521 case TBM_FORMAT_XBGR1555:
522 case TBM_FORMAT_RGBX5551:
523 case TBM_FORMAT_BGRX5551:
524 case TBM_FORMAT_ARGB1555:
525 case TBM_FORMAT_ABGR1555:
526 case TBM_FORMAT_RGBA5551:
527 case TBM_FORMAT_BGRA5551:
528 case TBM_FORMAT_RGB565:
529 case TBM_FORMAT_BGR565:
532 case TBM_FORMAT_RGB888:
533 case TBM_FORMAT_BGR888:
536 case TBM_FORMAT_XRGB8888:
537 case TBM_FORMAT_XBGR8888:
538 case TBM_FORMAT_RGBX8888:
539 case TBM_FORMAT_BGRX8888:
540 case TBM_FORMAT_ARGB8888:
541 case TBM_FORMAT_ABGR8888:
542 case TBM_FORMAT_RGBA8888:
543 case TBM_FORMAT_BGRA8888:
544 case TBM_FORMAT_XRGB2101010:
545 case TBM_FORMAT_XBGR2101010:
546 case TBM_FORMAT_RGBX1010102:
547 case TBM_FORMAT_BGRX1010102:
548 case TBM_FORMAT_ARGB2101010:
549 case TBM_FORMAT_ABGR2101010:
550 case TBM_FORMAT_RGBA1010102:
551 case TBM_FORMAT_BGRA1010102:
552 case TBM_FORMAT_YUYV:
553 case TBM_FORMAT_YVYU:
554 case TBM_FORMAT_UYVY:
555 case TBM_FORMAT_VYUY:
556 case TBM_FORMAT_AYUV:
559 case TBM_FORMAT_NV12:
560 case TBM_FORMAT_NV12MT:
561 case TBM_FORMAT_NV21:
564 case TBM_FORMAT_NV16:
565 case TBM_FORMAT_NV61:
568 case TBM_FORMAT_YUV410:
569 case TBM_FORMAT_YVU410:
572 case TBM_FORMAT_YUV411:
573 case TBM_FORMAT_YVU411:
574 case TBM_FORMAT_YUV420:
575 case TBM_FORMAT_YVU420:
578 case TBM_FORMAT_YUV422:
579 case TBM_FORMAT_YVU422:
582 case TBM_FORMAT_YUV444:
583 case TBM_FORMAT_YVU444:
587 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
594 static struct _tbm_surface *
595 _tbm_surface_internal_create_surface(tbm_bufmgr bufmgr, int width, int height, int format, int flags, tbm_error_e *error)
597 struct _tbm_surface *surf = NULL;
598 uint32_t size = 0, offset = 0, stride = 0, bo_size = 0;
601 surf = calloc(1, sizeof(struct _tbm_surface));
603 /* LCOV_EXCL_START */
604 TBM_ERR("fail to alloc surf\n");
605 *error = TBM_ERROR_OUT_OF_MEMORY;
606 goto alloc_surf_fail;
610 surf->magic = TBM_SURFACE_MAGIC;
611 surf->bufmgr = bufmgr;
612 surf->info.width = width;
613 surf->info.height = height;
614 surf->info.format = format;
615 surf->info.bpp = _tbm_surface_internal_get_bpp(format);
616 if (!surf->info.bpp) {
617 TBM_ERR("fail to get bpp from format(%d), error(%s)\n", format, tbm_error_str(*error));
618 *error = tbm_get_last_error();
622 surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
623 if (!surf->info.num_planes) {
624 TBM_ERR("fail to get num_planes from format(%d), error(%s)\n", format, tbm_error_str(*error));
625 *error = tbm_get_last_error();
626 goto num_planes_fail;
630 /* get size, stride and offset bo_idx */
631 for (i = 0; i < surf->info.num_planes; i++) {
632 if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
633 TBM_ERR("fail to query plane data\n");
634 *error = tbm_get_last_error();
635 goto query_plane_data_fail;
638 surf->info.planes[i].size = size;
639 surf->info.planes[i].offset = offset;
640 surf->info.planes[i].stride = stride;
641 surf->planes_bo_idx[i] = bo_idx;
646 for (i = 0; i < surf->info.num_planes; i++) {
647 surf->info.size += surf->info.planes[i].size;
649 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
650 surf->num_bos = surf->planes_bo_idx[i] + 1;
655 for (i = 0; i < surf->num_bos; i++) {
657 for (j = 0; j < surf->info.num_planes; j++) {
658 if (surf->planes_bo_idx[j] == i)
659 bo_size += surf->info.planes[j].size;
662 if (bufmgr->use_hal_tbm) {
663 surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, surf->info.bpp/8, flags, error);
664 if (*error == TBM_ERROR_NOT_SUPPORTED) {
665 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
667 TBM_ERR("fail to alloc bo idx:%d\n", i);
668 *error = tbm_get_last_error();
672 } else if (bufmgr->backend_module_data) {
673 if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format) {
674 /* LCOV_EXCL_START */
675 surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, surf->info.bpp/8, flags, error);
677 TBM_ERR("fail to tbm_bo_alloc_with_format idx:%d\n", i);
678 *error = tbm_get_last_error();
682 } else if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format && (flags & TBM_BO_TILED)) {
683 /* LCOV_EXCL_START */
684 surf->bos[i] = tbm_bo_alloc_with_tiled_format(bufmgr, width, height, surf->info.bpp/8, format, flags, i, error);
686 TBM_ERR("fail to tbm_bo_alloc_with_tiled_format idx:%d\n", i);
687 *error = tbm_get_last_error();
692 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
694 TBM_ERR("fail to alloc bo idx:%d\n", i);
695 *error = tbm_get_last_error();
700 if (bufmgr->backend->surface_bo_alloc) {
701 /* LCOV_EXCL_START */
702 surf->bos[i] = tbm_bo_alloc_with_surface(bufmgr, width, height, format, flags, i);
704 TBM_ERR("fail to tbm_bo_alloc_with_surface idx:%d\n", i);
705 *error = tbm_get_last_error();
710 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
712 TBM_ERR("fail to alloc bo idx:%d\n", i);
713 *error = tbm_get_last_error();
719 _tbm_bo_set_surface(surf->bos[i], surf);
722 *error = TBM_ERROR_NONE;
727 for (j = 0; j < i; j++) {
729 tbm_bo_unref(surf->bos[j]);
731 query_plane_data_fail:
741 tbm_surface_internal_is_valid(tbm_surface_h surface)
745 _tbm_surface_mutex_lock();
746 _tbm_set_last_result(TBM_ERROR_NONE);
748 /* Return silently if surface is null. */
750 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
751 _tbm_surface_mutex_unlock();
755 ret = _tbm_surface_internal_is_valid(surface);
757 _tbm_surface_mutex_unlock();
763 tbm_surface_internal_query_supported_formats(uint32_t **formats,
766 struct _tbm_bufmgr *bufmgr;
768 bool bufmgr_initialized = false;
771 _tbm_surface_mutex_lock();
772 _tbm_set_last_result(TBM_ERROR_NONE);
774 TBM_SURFACE_RETURN_VAL_IF_FAIL(formats, 0);
775 TBM_SURFACE_RETURN_VAL_IF_FAIL(num, 0);
777 if (!g_surface_bufmgr) {
778 _init_surface_bufmgr();
779 if (!g_surface_bufmgr) {
780 TBM_ERR("fail bufmgr initialization\n");
781 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
784 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
785 bufmgr_initialized = true;
788 bufmgr = g_surface_bufmgr;
790 if (bufmgr->use_hal_tbm) {
791 error = (tbm_error_e)hal_tbm_bufmgr_get_supported_formats(bufmgr->hal_bufmgr, formats, num);
792 /* LCOV_EXCL_START */
793 if (error == TBM_ERROR_NOT_SUPPORTED) {
794 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
796 } else if (error != TBM_ERROR_NONE) {
797 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
802 } else if (bufmgr->backend_module_data) {
803 if (!bufmgr->bufmgr_func->bufmgr_get_supported_formats) {
804 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
808 error = bufmgr->bufmgr_func->bufmgr_get_supported_formats(bufmgr->bufmgr_data, formats, num);
809 if (error != TBM_ERROR_NONE) {
810 /* LCOV_EXCL_START */
811 TBM_ERR("Fail to surface_supported_format. error(%d)\n", error);
813 /* LCOV_EXCL_START */
817 if (!bufmgr->backend->surface_supported_format) {
818 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
822 ret = bufmgr->backend->surface_supported_format(formats, num);
824 /* LCOV_EXCL_START */
825 TBM_ERR("Fail to surface_supported_format.\n");
826 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
828 /* LCOV_EXCL_START */
832 TBM_TRACE_SURFACE_INTERNAL("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
834 if (bufmgr_initialized) {
835 LIST_DELINIT(&g_surface_bufmgr->surf_list);
836 _deinit_surface_bufmgr();
839 _tbm_surface_mutex_unlock();
843 /* LCOV_EXCL_START */
845 if (bufmgr_initialized) {
846 LIST_DELINIT(&g_surface_bufmgr->surf_list);
847 _deinit_surface_bufmgr();
849 _tbm_surface_mutex_unlock();
851 TBM_ERR("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
858 tbm_surface_internal_get_num_planes(tbm_format format)
862 _tbm_surface_mutex_lock();
863 _tbm_set_last_result(TBM_ERROR_NONE);
865 num_planes = _tbm_surface_internal_get_num_planes(format);
867 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
868 _tbm_surface_mutex_unlock();
872 TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
874 _tbm_surface_mutex_unlock();
880 tbm_surface_internal_get_bpp(tbm_format format)
884 _tbm_surface_mutex_lock();
885 _tbm_set_last_result(TBM_ERROR_NONE);
887 bpp = _tbm_surface_internal_get_bpp(format);
889 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
890 _tbm_surface_mutex_unlock();
894 _tbm_surface_mutex_unlock();
896 TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
902 tbm_surface_internal_create_with_flags(int width, int height,
903 int format, int flags)
905 struct _tbm_bufmgr *bufmgr;
906 struct _tbm_surface *surf = NULL;
907 tbm_error_e error = TBM_ERROR_INVALID_OPERATION;
908 bool bufmgr_initialized = false;
910 _tbm_surface_mutex_lock();
911 _tbm_set_last_result(TBM_ERROR_NONE);
913 TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, NULL);
914 TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, NULL);
916 if (!g_surface_bufmgr) {
917 _init_surface_bufmgr();
918 if (!g_surface_bufmgr) {
919 TBM_ERR("fail bufmgr initialization\n");
920 error = TBM_ERROR_INVALID_OPERATION;
921 goto check_valid_fail;
923 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
924 bufmgr_initialized = true;
927 bufmgr = g_surface_bufmgr;
928 if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
929 TBM_ERR("The bufmgr is invalid\n");
930 error = TBM_ERROR_INVALID_PARAMETER;
931 goto check_valid_fail;
935 surf = _tbm_surface_internal_create_surface(bufmgr, width, height, format, flags, &error);
937 TBM_ERR("_tbm_surface_internal_create_surface failed.");
938 goto surface_alloc_fail;
941 TBM_TRACE_SURFACE_INTERNAL("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n",
942 width, height, _tbm_surface_internal_format_to_str(format), flags, surf);
944 LIST_INITHEAD(&surf->user_data_list);
945 LIST_INITHEAD(&surf->debug_data_list);
946 LIST_INITHEAD(&surf->destroy_funcs);
948 LIST_ADD(&surf->item_link, &bufmgr->surf_list);
950 _tbm_set_last_result(error);
951 _tbm_surface_mutex_unlock();
955 /* LCOV_EXCL_START */
959 if (bufmgr_initialized && bufmgr) {
960 LIST_DELINIT(&bufmgr->surf_list);
961 _deinit_surface_bufmgr();
964 TBM_ERR("error: width(%d) height(%d) format(%s) flags(%d)\n",
965 width, height, _tbm_surface_internal_format_to_str(format), flags);
967 _tbm_set_last_result(error);
968 _tbm_surface_mutex_unlock();
976 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
977 tbm_bo *bos, int num)
979 struct _tbm_bufmgr *bufmgr;
980 struct _tbm_surface *surf = NULL;
982 bool bufmgr_initialized = false;
984 _tbm_surface_mutex_lock();
985 _tbm_set_last_result(TBM_ERROR_NONE);
987 TBM_SURFACE_RETURN_VAL_IF_FAIL(bos, NULL);
988 TBM_SURFACE_RETURN_VAL_IF_FAIL(info, NULL);
989 TBM_SURFACE_RETURN_VAL_IF_FAIL(info->num_planes > 0, NULL);
990 TBM_SURFACE_RETURN_VAL_IF_FAIL(num > 0, NULL);
991 TBM_SURFACE_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
993 if (!g_surface_bufmgr) {
994 _init_surface_bufmgr();
995 if (!g_surface_bufmgr) {
996 TBM_ERR("fail bufmgr initialization\n");
997 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
998 goto check_valid_fail;
1000 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
1001 bufmgr_initialized = true;
1004 bufmgr = g_surface_bufmgr;
1005 if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
1006 TBM_ERR("fail to validate the Bufmgr.\n");
1007 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1008 goto check_valid_fail;
1011 surf = calloc(1, sizeof(struct _tbm_surface));
1013 /* LCOV_EXCL_START */
1014 TBM_ERR("fail to allocate struct _tbm_surface.\n");
1015 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1016 goto alloc_surf_fail;
1017 /* LCOV_EXCL_STOP */
1020 surf->magic = TBM_SURFACE_MAGIC;
1021 surf->bufmgr = bufmgr;
1022 surf->info.width = info->width;
1023 surf->info.height = info->height;
1024 surf->info.format = info->format;
1026 surf->info.bpp = info->bpp;
1028 surf->info.bpp = _tbm_surface_internal_get_bpp(info->format);
1029 if (!surf->info.bpp) {
1030 TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1034 surf->info.num_planes = info->num_planes;
1037 /* get size, stride and offset */
1038 for (i = 0; i < info->num_planes; i++) {
1039 surf->info.planes[i].offset = info->planes[i].offset;
1040 surf->info.planes[i].stride = info->planes[i].stride;
1042 if (info->planes[i].size > 0)
1043 surf->info.planes[i].size = info->planes[i].size;
1045 uint32_t size = 0, offset = 0, stride = 0;
1048 if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
1049 TBM_ERR("fail to get plane_data. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1050 goto plane_data_fail;
1052 surf->info.planes[i].size = size;
1056 surf->planes_bo_idx[i] = 0;
1058 surf->planes_bo_idx[i] = i;
1061 if (info->size > 0) {
1062 surf->info.size = info->size;
1064 surf->info.size = 0;
1065 for (i = 0; i < info->num_planes; i++)
1066 surf->info.size += surf->info.planes[i].size;
1069 surf->flags = TBM_BO_DEFAULT;
1071 /* create only one bo */
1072 surf->num_bos = num;
1073 for (i = 0; i < num; i++) {
1074 if (bos[i] == NULL) {
1075 TBM_ERR("bos[%d] is null.\n", i);
1076 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1080 surf->bos[i] = tbm_bo_ref(bos[i]);
1081 _tbm_bo_set_surface(bos[i], surf);
1084 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
1085 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
1087 LIST_INITHEAD(&surf->user_data_list);
1088 LIST_INITHEAD(&surf->debug_data_list);
1089 LIST_INITHEAD(&surf->destroy_funcs);
1091 LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1093 _tbm_surface_mutex_unlock();
1097 /* LCOV_EXCL_START */
1101 for (i = 0; i < num; i++) {
1103 tbm_bo_unref(surf->bos[i]);
1108 if (bufmgr_initialized && bufmgr) {
1109 LIST_DELINIT(&bufmgr->surf_list);
1110 _deinit_surface_bufmgr();
1112 _tbm_surface_mutex_unlock();
1114 TBM_ERR("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
1115 info->width, info->height,
1116 _tbm_surface_internal_format_to_str(info->format), num);
1117 /* LCOV_EXCL_STOP */
1123 tbm_surface_internal_destroy(tbm_surface_h surface)
1125 _tbm_surface_mutex_lock();
1126 _tbm_set_last_result(TBM_ERROR_NONE);
1128 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1132 if (surface->refcnt > 0) {
1133 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1134 _tbm_surface_mutex_unlock();
1138 TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1140 if (surface->refcnt == 0)
1141 _tbm_surface_internal_destroy(surface);
1143 _tbm_surface_mutex_unlock();
1147 tbm_surface_internal_ref(tbm_surface_h surface)
1149 _tbm_surface_mutex_lock();
1150 _tbm_set_last_result(TBM_ERROR_NONE);
1152 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1156 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1158 _tbm_surface_mutex_unlock();
1162 tbm_surface_internal_unref(tbm_surface_h surface)
1164 _tbm_surface_mutex_lock();
1165 _tbm_set_last_result(TBM_ERROR_NONE);
1167 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1171 if (surface->refcnt > 0) {
1172 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1173 _tbm_surface_mutex_unlock();
1177 TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1179 if (surface->refcnt == 0)
1180 _tbm_surface_internal_destroy(surface);
1182 _tbm_surface_mutex_unlock();
1186 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
1188 struct _tbm_surface *surf;
1191 _tbm_surface_mutex_lock();
1192 _tbm_set_last_result(TBM_ERROR_NONE);
1194 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1196 surf = (struct _tbm_surface *)surface;
1197 num = surf->num_bos;
1200 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1202 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) num_bos(%d)\n", surface, num);
1204 _tbm_surface_mutex_unlock();
1210 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
1212 struct _tbm_surface *surf;
1215 _tbm_surface_mutex_lock();
1216 _tbm_set_last_result(TBM_ERROR_NONE);
1218 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
1219 TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
1221 surf = (struct _tbm_surface *)surface;
1222 bo = surf->bos[bo_idx];
1224 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
1226 _tbm_surface_mutex_unlock();
1232 tbm_surface_internal_get_size(tbm_surface_h surface)
1234 struct _tbm_surface *surf;
1237 _tbm_surface_mutex_lock();
1238 _tbm_set_last_result(TBM_ERROR_NONE);
1240 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1242 surf = (struct _tbm_surface *)surface;
1243 size = surf->info.size;
1245 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) size(%u)\n", surface, size);
1247 _tbm_surface_mutex_unlock();
1253 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1254 uint32_t *size, uint32_t *offset, uint32_t *pitch)
1256 struct _tbm_surface *surf;
1258 _tbm_surface_mutex_lock();
1259 _tbm_set_last_result(TBM_ERROR_NONE);
1261 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1262 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1264 surf = (struct _tbm_surface *)surface;
1266 if (plane_idx >= surf->info.num_planes) {
1267 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1268 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1269 _tbm_surface_mutex_unlock();
1274 *size = surf->info.planes[plane_idx].size;
1277 *offset = surf->info.planes[plane_idx].offset;
1280 *pitch = surf->info.planes[plane_idx].stride;
1282 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1283 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1284 surf->info.planes[plane_idx].stride);
1286 _tbm_surface_mutex_unlock();
1292 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1293 tbm_surface_info_s *info, int map)
1295 struct _tbm_surface *surf;
1296 tbm_bo_handle bo_handles[4];
1299 int planes_bo_idx[TBM_SURF_PLANE_MAX];
1302 _tbm_surface_mutex_lock();
1303 _tbm_set_last_result(TBM_ERROR_NONE);
1305 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1307 memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1309 surf = (struct _tbm_surface *)surface;
1311 memset(info, 0x00, sizeof(tbm_surface_info_s));
1312 info->width = surf->info.width;
1313 info->height = surf->info.height;
1314 info->format = surf->info.format;
1315 info->bpp = surf->info.bpp;
1316 info->size = surf->info.size;
1317 info->num_planes = surf->info.num_planes;
1319 for (i = 0; i < surf->info.num_planes; i++) {
1320 info->planes[i].size = surf->info.planes[i].size;
1321 info->planes[i].offset = surf->info.planes[i].offset;
1322 info->planes[i].stride = surf->info.planes[i].stride;
1323 planes_bo_idx[i] = surf->planes_bo_idx[i];
1326 for (i = 0; i < surf->num_bos; i++)
1327 bos[i] = surf->bos[i];
1329 num_bos = surf->num_bos;
1332 _tbm_surface_mutex_unlock();
1333 for (i = 0; i < num_bos; i++) {
1334 bo_handles[i] = tbm_bo_map(bos[i], TBM_DEVICE_CPU, opt);
1335 if (bo_handles[i].ptr == NULL) {
1336 for (j = 0; j < i; j++)
1337 tbm_bo_unmap(bos[j]);
1339 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1343 _tbm_surface_mutex_lock();
1345 for (i = 0; i < num_bos; i++) {
1346 bo_handles[i] = tbm_bo_get_handle(bos[i], TBM_DEVICE_CPU);
1347 if (bo_handles[i].ptr == NULL) {
1348 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1349 _tbm_surface_mutex_unlock();
1355 for (i = 0; i < info->num_planes; i++) {
1356 if (bo_handles[planes_bo_idx[i]].ptr)
1357 info->planes[i].ptr = bo_handles[planes_bo_idx[i]].ptr + info->planes[i].offset;
1360 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1362 _tbm_surface_mutex_unlock();
1368 tbm_surface_internal_unmap(tbm_surface_h surface)
1370 struct _tbm_surface *surf;
1373 _tbm_surface_mutex_lock();
1374 _tbm_set_last_result(TBM_ERROR_NONE);
1376 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1378 surf = (struct _tbm_surface *)surface;
1380 for (i = 0; i < surf->num_bos; i++)
1381 tbm_bo_unmap(surf->bos[i]);
1383 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)\n", surface);
1385 _tbm_surface_mutex_unlock();
1389 tbm_surface_internal_get_width(tbm_surface_h surface)
1391 struct _tbm_surface *surf;
1394 _tbm_surface_mutex_lock();
1395 _tbm_set_last_result(TBM_ERROR_NONE);
1397 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1399 surf = (struct _tbm_surface *)surface;
1400 width = surf->info.width;
1402 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u)\n", surface, width);
1404 _tbm_surface_mutex_unlock();
1410 tbm_surface_internal_get_height(tbm_surface_h surface)
1412 struct _tbm_surface *surf;
1413 unsigned int height;
1415 _tbm_surface_mutex_lock();
1416 _tbm_set_last_result(TBM_ERROR_NONE);
1418 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1420 surf = (struct _tbm_surface *)surface;
1421 height = surf->info.height;
1423 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) height(%u)\n", surface, height);
1425 _tbm_surface_mutex_unlock();
1432 tbm_surface_internal_get_format(tbm_surface_h surface)
1434 struct _tbm_surface *surf;
1437 _tbm_surface_mutex_lock();
1438 _tbm_set_last_result(TBM_ERROR_NONE);
1440 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1442 surf = (struct _tbm_surface *)surface;
1443 format = surf->info.format;
1445 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1447 _tbm_surface_mutex_unlock();
1453 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1455 struct _tbm_surface *surf;
1458 _tbm_surface_mutex_lock();
1459 _tbm_set_last_result(TBM_ERROR_NONE);
1461 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1462 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1464 surf = (struct _tbm_surface *)surface;
1465 bo_idx = surf->planes_bo_idx[plane_idx];
1467 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1469 _tbm_surface_mutex_unlock();
1475 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1476 tbm_data_free data_free_func)
1478 tbm_user_data *data;
1480 _tbm_surface_mutex_lock();
1481 _tbm_set_last_result(TBM_ERROR_NONE);
1483 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1485 /* check if the data according to the key exist if so, return false. */
1486 data = user_data_lookup(&surface->user_data_list, key);
1488 TBM_TRACE_SURFACE_INTERNAL("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1489 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1490 _tbm_surface_mutex_unlock();
1494 data = user_data_create(key, data_free_func);
1496 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1497 _tbm_surface_mutex_unlock();
1501 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1503 LIST_ADD(&data->item_link, &surface->user_data_list);
1505 _tbm_surface_mutex_unlock();
1511 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1514 tbm_user_data *old_data;
1516 _tbm_surface_mutex_lock();
1517 _tbm_set_last_result(TBM_ERROR_NONE);
1519 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1521 old_data = user_data_lookup(&surface->user_data_list, key);
1523 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1524 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1525 _tbm_surface_mutex_unlock();
1529 if (old_data->data && old_data->free_func)
1530 old_data->free_func(old_data->data);
1532 old_data->data = data;
1534 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1536 _tbm_surface_mutex_unlock();
1542 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1545 tbm_user_data *old_data;
1547 _tbm_surface_mutex_lock();
1548 _tbm_set_last_result(TBM_ERROR_NONE);
1550 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1553 TBM_ERR("error: tbm_surface(%p) key(%lu)\n", surface, key);
1554 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1555 _tbm_surface_mutex_unlock();
1560 old_data = user_data_lookup(&surface->user_data_list, key);
1562 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1563 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1564 _tbm_surface_mutex_unlock();
1568 *data = old_data->data;
1570 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1572 _tbm_surface_mutex_unlock();
1578 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1581 tbm_user_data *old_data = (void *)0;
1583 _tbm_surface_mutex_lock();
1584 _tbm_set_last_result(TBM_ERROR_NONE);
1586 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1588 old_data = user_data_lookup(&surface->user_data_list, key);
1590 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1591 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1592 _tbm_surface_mutex_unlock();
1596 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1598 user_data_delete(old_data);
1600 _tbm_surface_mutex_unlock();
1605 /* LCOV_EXCL_START */
1607 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1609 TBM_RETURN_VAL_IF_FAIL(surface, 0);
1611 return surface->debug_pid;
1615 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1617 _tbm_surface_mutex_lock();
1618 _tbm_set_last_result(TBM_ERROR_NONE);
1620 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1622 surface->debug_pid = pid;
1624 _tbm_surface_mutex_unlock();
1627 static tbm_surface_debug_data *
1628 _tbm_surface_internal_debug_data_create(char *key, char *value)
1630 tbm_surface_debug_data *debug_data = NULL;
1632 debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1634 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1635 TBM_ERR("fail to allocate the debug_data.");
1639 if (key) debug_data->key = strdup(key);
1640 if (value) debug_data->value = strdup(value);
1646 _tbm_surface_internal_debug_data_value_update(tbm_surface_debug_data *debug_data, char *value)
1648 if (!debug_data->value && !value)
1651 if (debug_data->value && value && !strncmp(debug_data->value, value, strlen(debug_data->value)))
1654 if (debug_data->value)
1655 free(debug_data->value);
1658 debug_data->value = strdup(value);
1660 debug_data->value = NULL;
1663 static tbm_surface_debug_data *
1664 _tbm_surface_internal_debug_data_find(struct list_head *list, char *key)
1666 tbm_surface_debug_data *debug_data = NULL;
1668 if (LIST_IS_EMPTY(list))
1671 LIST_FOR_EACH_ENTRY(debug_data, list, item_link) {
1672 if (!strncmp(debug_data->key, key, strlen(debug_data->key)))
1680 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1682 tbm_surface_debug_data *debug_data = NULL;
1683 tbm_bufmgr bufmgr = NULL;
1685 _tbm_surface_mutex_lock();
1686 _tbm_set_last_result(TBM_ERROR_NONE);
1688 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1689 TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1691 bufmgr = surface->bufmgr;
1693 TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1695 debug_data = _tbm_surface_internal_debug_data_find(&surface->debug_data_list, key);
1697 _tbm_surface_internal_debug_data_value_update(debug_data, value);
1699 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1701 TBM_ERR("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1702 _tbm_surface_mutex_unlock();
1706 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1709 /* add new debug key to list */
1710 debug_data = _tbm_surface_internal_debug_data_find(&bufmgr->debug_key_list, key);
1712 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1714 LIST_ADDTAIL(&debug_data->item_link, &bufmgr->debug_key_list);
1717 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1719 _tbm_surface_mutex_unlock();
1725 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1727 tbm_surface_debug_data *old_data = NULL;
1729 TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1731 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1732 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1733 if (!strcmp(old_data->key, key))
1734 return old_data->value;
1741 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1742 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1744 struct _tbm_surface_dump_buf_info {
1754 tbm_surface_info_s info;
1756 struct list_head link;
1759 struct _tbm_surface_dump_info {
1760 char *path; // copy???
1763 struct list_head *link;
1764 struct list_head surface_list; /* link of surface */
1767 static tbm_surface_dump_info *g_dump_info = NULL;
1768 static const char *dump_postfix[2] = {"png", "yuv"};
1769 static double scale_factor;
1772 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1773 void *data2, int size2, void *data3, int size3)
1776 unsigned int *blocks;
1778 if (_tbm_surface_check_file_is_symbolic_link(file))
1779 TBM_ERR("%s is symbolic link\n", file);
1781 fp = fopen(file, "w+");
1782 TBM_RETURN_IF_FAIL(fp != NULL);
1784 blocks = (unsigned int *)data1;
1785 fwrite(blocks, 1, size1, fp);
1788 blocks = (unsigned int *)data2;
1789 fwrite(blocks, 1, size2, fp);
1793 blocks = (unsigned int *)data3;
1794 fwrite(blocks, 1, size3, fp);
1801 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height, int stride, int format)
1803 unsigned int *blocks = (unsigned int *)data;
1806 png_bytep *row_pointers;
1809 if (_tbm_surface_check_file_is_symbolic_link(file))
1810 TBM_ERR("%s is symbolic link\n", file);
1812 fp = fopen(file, "wb");
1813 TBM_RETURN_IF_FAIL(fp != NULL);
1815 png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1818 TBM_ERR("fail to create a png write structure.\n");
1823 png_infop pPngInfo = png_create_info_struct(pPngStruct);
1825 TBM_ERR("fail to create a png info structure.\n");
1826 png_destroy_write_struct(&pPngStruct, NULL);
1831 if (setjmp(png_jmpbuf(pPngStruct))) {
1832 /* if png has problem of writing the file, we get here */
1833 TBM_ERR("fail to write png file.\n");
1834 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1839 png_init_io(pPngStruct, fp);
1840 if (format == TBM_FORMAT_XRGB8888) {
1842 png_set_IHDR(pPngStruct,
1849 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1852 png_set_IHDR(pPngStruct,
1857 PNG_COLOR_TYPE_RGBA,
1859 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1862 png_set_bgr(pPngStruct);
1863 png_write_info(pPngStruct, pPngInfo);
1865 row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1866 if (!row_pointers) {
1867 TBM_ERR("fail to allocate the png row_pointers.\n");
1868 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1873 for (y = 0; y < height; ++y) {
1877 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1879 TBM_ERR("fail to allocate the png row.\n");
1880 for (x = 0; x < y; x++)
1881 png_free(pPngStruct, row_pointers[x]);
1882 png_free(pPngStruct, row_pointers);
1883 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1887 row_pointers[y] = (png_bytep)row;
1889 for (x = 0; x < width; ++x) {
1890 unsigned int curBlock = blocks[(y * (stride >> 2)) + x];
1892 if (pixel_size == 3) { // XRGB8888
1893 row[x * pixel_size] = (curBlock & 0xFF);
1894 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1895 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1896 } else { // ARGB8888
1897 row[x * pixel_size] = (curBlock & 0xFF);
1898 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1899 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1900 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1905 png_write_image(pPngStruct, row_pointers);
1906 png_write_end(pPngStruct, pPngInfo);
1908 for (y = 0; y < height; y++)
1909 png_free(pPngStruct, row_pointers[y]);
1910 png_free(pPngStruct, row_pointers);
1912 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1918 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1920 TBM_RETURN_IF_FAIL(path != NULL);
1921 TBM_RETURN_IF_FAIL(w > 0);
1922 TBM_RETURN_IF_FAIL(h > 0);
1923 TBM_RETURN_IF_FAIL(count > 0);
1925 tbm_surface_dump_buf_info *buf_info = NULL;
1926 tbm_surface_h tbm_surface;
1927 tbm_surface_info_s info;
1932 TBM_WRN("waring already running the tbm_surface_internal_dump.\n");
1936 g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1937 TBM_RETURN_IF_FAIL(g_dump_info);
1939 LIST_INITHEAD(&g_dump_info->surface_list);
1940 g_dump_info->count = 0;
1941 g_dump_info->dump_max = count;
1943 /* get buffer size */
1944 tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1945 if (tbm_surface == NULL) {
1946 TBM_ERR("tbm_surface_create fail\n");
1952 if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
1953 TBM_ERR("tbm_surface_get_info fail\n");
1954 tbm_surface_destroy(tbm_surface);
1959 buffer_size = info.size;
1960 tbm_surface_destroy(tbm_surface);
1962 /* create dump lists */
1963 for (i = 0; i < count; i++) {
1966 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1967 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1969 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1971 TBM_ERR("fail to allocate the tbm_bo[%d]\n", i);
1976 buf_info->index = i;
1978 buf_info->size = buffer_size;
1980 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1983 g_dump_info->path = path;
1984 g_dump_info->link = &g_dump_info->surface_list;
1988 TBM_INFO("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1993 /* free resources */
1994 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1995 tbm_surface_dump_buf_info *tmp;
1997 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1998 tbm_bo_unref(buf_info->bo);
1999 LIST_DEL(&buf_info->link);
2004 TBM_ERR("Dump Start fail.. path:%s\n", g_dump_info->path);
2013 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
2020 tbm_surface_internal_dump_start(path, w, h, count);
2021 scale_factor = scale;
2025 tbm_surface_internal_dump_end(void)
2027 tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
2028 tbm_bo_handle bo_handle;
2033 if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2040 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2043 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
2044 if (bo_handle.ptr == NULL) {
2045 tbm_bo_unref(buf_info->bo);
2046 LIST_DEL(&buf_info->link);
2051 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
2052 TBM_INFO("Dump File.. %s generated.\n", file);
2054 if (buf_info->dirty) {
2055 void *ptr1 = NULL, *ptr2 = NULL;
2057 switch (buf_info->info.format) {
2058 case TBM_FORMAT_ARGB8888:
2059 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2060 buf_info->info.planes[0].stride >> 2,
2061 buf_info->info.height,
2062 buf_info->info.planes[0].stride,
2063 TBM_FORMAT_ARGB8888);
2065 case TBM_FORMAT_XRGB8888:
2066 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2067 buf_info->info.planes[0].stride >> 2,
2068 buf_info->info.height,
2069 buf_info->info.planes[0].stride,
2070 TBM_FORMAT_XRGB8888);
2072 case TBM_FORMAT_YVU420:
2073 case TBM_FORMAT_YUV420:
2074 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2075 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
2076 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2077 buf_info->info.planes[0].stride * buf_info->info.height,
2079 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2081 buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
2083 case TBM_FORMAT_NV12:
2084 case TBM_FORMAT_NV21:
2085 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2086 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2087 buf_info->info.planes[0].stride * buf_info->info.height,
2089 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2092 case TBM_FORMAT_YUYV:
2093 case TBM_FORMAT_UYVY:
2094 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2095 buf_info->info.planes[0].stride * buf_info->info.height,
2099 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
2102 } else if (buf_info->dirty_shm)
2103 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2104 buf_info->shm_stride >> 2,
2106 buf_info->shm_stride, 0);
2108 tbm_bo_unmap(buf_info->bo);
2109 tbm_bo_unref(buf_info->bo);
2110 LIST_DEL(&buf_info->link);
2117 TBM_INFO("Dump End..\n");
2120 static pixman_format_code_t
2121 _tbm_surface_internal_pixman_format_get(tbm_format format)
2124 case TBM_FORMAT_ARGB8888:
2125 return PIXMAN_a8r8g8b8;
2126 case TBM_FORMAT_XRGB8888:
2127 return PIXMAN_x8r8g8b8;
2136 * This function supports only if a buffer has below formats.
2137 * - TBM_FORMAT_ARGB8888
2138 * - TBM_FORMAT_XRGB8888
2140 static tbm_surface_error_e
2141 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
2142 int format, int src_stride, int src_w, int src_h,
2143 int dst_stride, int dst_w, int dst_h)
2145 pixman_image_t *src_img = NULL, *dst_img = NULL;
2146 pixman_format_code_t pixman_format;
2147 pixman_transform_t t;
2148 struct pixman_f_transform ft;
2149 double scale_x, scale_y;
2151 TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2152 TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2154 pixman_format = _tbm_surface_internal_pixman_format_get(format);
2155 TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2158 src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2159 (uint32_t*)src_ptr, src_stride);
2160 TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2163 dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2164 (uint32_t*)dst_ptr, dst_stride);
2165 TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2167 pixman_f_transform_init_identity(&ft);
2169 scale_x = (double)src_w / dst_w;
2170 scale_y = (double)src_h / dst_h;
2172 pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2173 pixman_f_transform_translate(&ft, NULL, 0, 0);
2174 pixman_transform_from_pixman_f_transform(&t, &ft);
2175 pixman_image_set_transform(src_img, &t);
2177 pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2178 0, 0, 0, 0, 0, 0, dst_w, dst_h);
2180 pixman_image_unref(src_img);
2181 pixman_image_unref(dst_img);
2183 return TBM_SURFACE_ERROR_NONE;
2187 pixman_image_unref(src_img);
2189 return TBM_SURFACE_ERROR_INVALID_OPERATION;
2192 #define MAX_BOS 4 // This value is came from bos[4] in struct _tbm_surface
2193 #define KEY_LEN 5 // "_XXXX"
2194 #define KEYS_LEN KEY_LEN * MAX_BOS
2196 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2198 char *keys, temp_key[KEY_LEN + 1];
2199 struct _tbm_surface *surf;
2203 _tbm_surface_mutex_lock();
2205 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2207 surf = (struct _tbm_surface *)surface;
2209 num_bos = surf->num_bos;
2210 if (num_bos > MAX_BOS)
2213 keys = calloc(KEYS_LEN + 1, sizeof(char));
2215 TBM_ERR("Failed to alloc memory");
2216 _tbm_surface_mutex_unlock();
2220 for (i = 0; i < num_bos; i++) {
2221 memset(temp_key, 0x00, KEY_LEN + 1);
2223 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2224 strncat(keys, temp_key, KEY_LEN + 1);
2227 _tbm_surface_mutex_unlock();
2232 static void _tbm_surface_internal_put_keys(char *keys)
2239 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2241 TBM_RETURN_IF_FAIL(surface != NULL);
2242 TBM_RETURN_IF_FAIL(type != NULL);
2244 tbm_surface_dump_buf_info *buf_info;
2245 struct list_head *next_link;
2246 tbm_surface_info_s info;
2247 tbm_bo_handle bo_handle;
2248 const char *postfix;
2249 const char *format = NULL;
2256 next_link = g_dump_info->link->next;
2257 TBM_RETURN_IF_FAIL(next_link != NULL);
2259 if (next_link == &g_dump_info->surface_list) {
2260 next_link = next_link->next;
2261 TBM_RETURN_IF_FAIL(next_link != NULL);
2264 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2265 TBM_RETURN_IF_FAIL(buf_info != NULL);
2267 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2268 TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2270 if (scale_factor > 0.0) {
2273 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
2274 TBM_WRN("Dump with scale skip. unsupported format(%s)\n",
2275 _tbm_surface_internal_format_to_str(info.format));
2276 tbm_surface_unmap(surface);
2280 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2282 buf_info->info.width = info.width * scale_factor;
2283 buf_info->info.height = info.height * scale_factor;
2284 buf_info->info.format = info.format;
2285 buf_info->info.bpp = _tbm_surface_internal_get_bpp(buf_info->info.format);
2286 if (!buf_info->info.bpp) {
2287 TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
2288 tbm_surface_unmap(surface);
2291 buf_info->info.num_planes = 1;
2292 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2293 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2295 if (buf_info->info.size > buf_info->size) {
2296 TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)\n",
2297 buf_info->info.size, buf_info->size);
2298 tbm_surface_unmap(surface);
2302 if (info.size > buf_info->size) {
2303 TBM_WRN("Dump skip. surface over created buffer size(%u, %d)\n",
2304 info.size, buf_info->size);
2305 tbm_surface_unmap(surface);
2309 /* make the file information */
2310 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2313 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888) {
2314 postfix = dump_postfix[0];
2315 format = _tbm_surface_internal_format_to_str(info.format);
2317 postfix = dump_postfix[1];
2319 keys = _tbm_surface_internal_get_keys(surface);
2321 TBM_ERR("fail to get keys");
2322 tbm_surface_unmap(surface);
2327 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2328 if (!bo_handle.ptr) {
2329 TBM_ERR("fail to map bo");
2330 _tbm_surface_internal_put_keys(keys);
2331 tbm_surface_unmap(surface);
2334 memset(bo_handle.ptr, 0x00, buf_info->size);
2336 switch (info.format) {
2337 case TBM_FORMAT_ARGB8888:
2338 case TBM_FORMAT_XRGB8888:
2339 snprintf(buf_info->name, sizeof(buf_info->name),
2340 "%10.3f_%03d%s_%p_%s-%s.%s",
2341 _tbm_surface_internal_get_time(),
2342 g_dump_info->count++, keys, surface, format, type, postfix);
2344 if (scale_factor > 0.0) {
2345 ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2347 buf_info->info.format,
2348 info.planes[0].stride,
2349 info.width, info.height,
2350 buf_info->info.planes[0].stride,
2351 buf_info->info.width,
2352 buf_info->info.height);
2353 if (ret != TBM_SURFACE_ERROR_NONE) {
2354 TBM_ERR("fail to scale buffer");
2355 tbm_bo_unmap(buf_info->bo);
2356 _tbm_surface_internal_put_keys(keys);
2357 tbm_surface_unmap(surface);
2361 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2363 case TBM_FORMAT_YVU420:
2364 case TBM_FORMAT_YUV420:
2365 snprintf(buf_info->name, sizeof(buf_info->name),
2366 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2367 _tbm_surface_internal_get_time(),
2368 g_dump_info->count++, keys, type, info.planes[0].stride,
2369 info.height, FOURCC_STR(info.format), postfix);
2370 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2371 bo_handle.ptr += info.planes[0].stride * info.height;
2372 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2373 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2374 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2376 case TBM_FORMAT_NV12:
2377 case TBM_FORMAT_NV21:
2378 snprintf(buf_info->name, sizeof(buf_info->name),
2379 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2380 _tbm_surface_internal_get_time(),
2381 g_dump_info->count++, keys, type, info.planes[0].stride,
2382 info.height, FOURCC_STR(info.format), postfix);
2383 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2384 bo_handle.ptr += info.planes[0].stride * info.height;
2385 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2387 case TBM_FORMAT_YUYV:
2388 case TBM_FORMAT_UYVY:
2389 snprintf(buf_info->name, sizeof(buf_info->name),
2390 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2391 _tbm_surface_internal_get_time(),
2392 g_dump_info->count++, keys, type, info.planes[0].stride,
2393 info.height, FOURCC_STR(info.format), postfix);
2394 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2397 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2398 tbm_bo_unmap(buf_info->bo);
2399 _tbm_surface_internal_put_keys(keys);
2400 tbm_surface_unmap(surface);
2404 tbm_bo_unmap(buf_info->bo);
2406 _tbm_surface_internal_put_keys(keys);
2408 tbm_surface_unmap(surface);
2410 buf_info->dirty = 1;
2411 buf_info->dirty_shm = 0;
2413 if (g_dump_info->count == 1000)
2414 g_dump_info->count = 0;
2416 g_dump_info->link = next_link;
2418 TBM_INFO("Dump %s \n", buf_info->name);
2421 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2424 TBM_RETURN_IF_FAIL(ptr != NULL);
2425 TBM_RETURN_IF_FAIL(w > 0);
2426 TBM_RETURN_IF_FAIL(h > 0);
2427 TBM_RETURN_IF_FAIL(stride > 0);
2428 TBM_RETURN_IF_FAIL(type != NULL);
2430 tbm_surface_dump_buf_info *buf_info;
2431 struct list_head *next_link;
2432 tbm_bo_handle bo_handle;
2433 int ret, size, dw = 0, dh = 0, dstride = 0;
2438 next_link = g_dump_info->link->next;
2439 TBM_RETURN_IF_FAIL(next_link != NULL);
2441 if (next_link == &g_dump_info->surface_list) {
2442 next_link = next_link->next;
2443 TBM_RETURN_IF_FAIL(next_link != NULL);
2446 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2447 TBM_RETURN_IF_FAIL(buf_info != NULL);
2449 if (scale_factor > 0.0) {
2452 dw = w * scale_factor;
2453 dh = h * scale_factor;
2455 size = dstride * dh;
2459 if (size > buf_info->size) {
2460 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2461 size, buf_info->size);
2466 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2467 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2469 memset(bo_handle.ptr, 0x00, buf_info->size);
2470 memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2472 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2473 _tbm_surface_internal_get_time(),
2474 g_dump_info->count++, type, dump_postfix[0]);
2475 if (scale_factor > 0.0) {
2476 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2477 TBM_FORMAT_ARGB8888, stride,
2478 w, h, dstride, dw, dh);
2479 if (ret != TBM_SURFACE_ERROR_NONE) {
2480 TBM_ERR("fail to scale buffer");
2481 tbm_bo_unmap(buf_info->bo);
2484 buf_info->shm_stride = dstride;
2485 buf_info->shm_h = dh;
2487 memcpy(bo_handle.ptr, ptr, size);
2488 buf_info->shm_stride = stride;
2489 buf_info->shm_h = h;
2492 tbm_bo_unmap(buf_info->bo);
2494 buf_info->dirty = 0;
2495 buf_info->dirty_shm = 1;
2497 if (g_dump_info->count == 1000)
2498 g_dump_info->count = 0;
2500 g_dump_info->link = next_link;
2502 TBM_INFO("Dump %s \n", buf_info->name);
2506 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2508 TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2509 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2510 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2512 tbm_surface_info_s info;
2513 const char *postfix;
2517 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2518 TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2520 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2521 postfix = dump_postfix[0];
2523 postfix = dump_postfix[1];
2525 if (strcmp(postfix, type)) {
2526 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2527 tbm_surface_unmap(surface);
2531 snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2533 if (!access(file, 0)) {
2534 TBM_ERR("can't capture buffer, exist file %s", file);
2535 tbm_surface_unmap(surface);
2539 switch (info.format) {
2540 case TBM_FORMAT_ARGB8888:
2541 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2544 info.planes[0].stride,
2545 TBM_FORMAT_ARGB8888);
2547 case TBM_FORMAT_XRGB8888:
2548 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2551 info.planes[0].stride,
2552 TBM_FORMAT_XRGB8888);
2554 case TBM_FORMAT_YVU420:
2555 case TBM_FORMAT_YUV420:
2556 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2557 info.planes[0].stride * info.height,
2559 info.planes[1].stride * (info.height >> 1),
2561 info.planes[2].stride * (info.height >> 1));
2563 case TBM_FORMAT_NV12:
2564 case TBM_FORMAT_NV21:
2565 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2566 info.planes[0].stride * info.height,
2568 info.planes[1].stride * (info.height >> 1),
2571 case TBM_FORMAT_YUYV:
2572 case TBM_FORMAT_UYVY:
2573 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2574 info.planes[0].stride * info.height,
2578 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2579 tbm_surface_unmap(surface);
2583 tbm_surface_unmap(surface);
2585 TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2591 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2592 const char *path, const char *name, const char *type)
2594 TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2595 TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2596 TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2597 TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2598 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2599 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2603 if (strcmp(dump_postfix[0], type)) {
2604 TBM_ERR("Not supported type:%s'", type);
2608 snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2610 if (!access(file, 0)) {
2611 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2615 _tbm_surface_internal_dump_file_png(file, ptr, w, h, stride, 0);
2617 TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2623 tbm_surface_internal_set_damage(tbm_surface_h surface, int x, int y, int width, int height)
2625 struct _tbm_surface *surf;
2627 _tbm_surface_mutex_lock();
2628 _tbm_set_last_result(TBM_ERROR_NONE);
2630 TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, 0);
2631 TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, 0);
2632 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2634 surf = (struct _tbm_surface *)surface;
2638 surf->damage.width = width;
2639 surf->damage.height = height;
2641 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2642 surface, x, y, width, height);
2644 _tbm_surface_mutex_unlock();
2650 tbm_surface_internal_get_damage(tbm_surface_h surface, int *x, int *y, int *width, int *height)
2652 struct _tbm_surface *surf;
2654 _tbm_surface_mutex_lock();
2655 _tbm_set_last_result(TBM_ERROR_NONE);
2657 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2659 surf = (struct _tbm_surface *)surface;
2661 if (x) *x = surf->damage.x;
2662 if (y) *y = surf->damage.y;
2663 if (width) *width = surf->damage.width;
2664 if (height) *height = surf->damage.height;
2666 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2667 surface, surf->damage.x, surf->damage.y, surf->damage.width, surf->damage.height);
2669 _tbm_surface_mutex_unlock();
2675 tbm_surface_internal_add_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2677 struct _tbm_surface *surf;
2678 tbm_surface_destroy_func_info *func_info = NULL;
2680 _tbm_surface_mutex_lock();
2681 _tbm_set_last_result(TBM_ERROR_NONE);
2683 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2684 TBM_SURFACE_RETURN_VAL_IF_FAIL(func != NULL, 0);
2686 surf = (struct _tbm_surface *)surface;
2687 LIST_FOR_EACH_ENTRY(func_info, &surf->destroy_funcs, item_link) {
2688 if (func_info->destroy_func == func && func_info->user_data == user_data) {
2689 TBM_ERR("can't add twice");
2690 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
2691 _tbm_surface_mutex_unlock();
2696 func_info = calloc(1, sizeof(tbm_surface_destroy_func_info));
2697 if (func_info == NULL) {
2698 TBM_ERR("alloc failed");
2699 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
2700 _tbm_surface_mutex_unlock();
2704 func_info->destroy_func = func;
2705 func_info->user_data = user_data;
2707 LIST_ADDTAIL(&func_info->item_link, &surf->destroy_funcs);
2709 _tbm_surface_mutex_unlock();
2715 tbm_surface_internal_remove_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2717 struct _tbm_surface *surf;
2718 tbm_surface_destroy_func_info *func_info = NULL, *next = NULL;
2720 _tbm_surface_mutex_lock();
2721 _tbm_set_last_result(TBM_ERROR_NONE);
2723 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
2724 TBM_SURFACE_RETURN_IF_FAIL(func != NULL);
2726 surf = (struct _tbm_surface *)surface;
2727 LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &surf->destroy_funcs, item_link) {
2728 if (func_info->destroy_func != func || func_info->user_data != user_data)
2731 LIST_DEL(&func_info->item_link);
2734 _tbm_surface_mutex_unlock();
2739 _tbm_surface_mutex_unlock();
2742 tbm_surface_buffer_data *
2743 tbm_surface_internal_export(tbm_surface_h surface, tbm_error_e *error)
2750 tbm_surface_internal_import(tbm_surface_info_s *surface_info, tbm_surface_buffer_data *buffer_data, tbm_error_e *error)