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);
385 if (surface->hal_surface) {
386 hal_tbm_surface_free(surface->hal_surface);
387 surface->hal_surface = NULL;
393 if (bufmgr && LIST_IS_EMPTY(&bufmgr->surf_list)) {
394 LIST_DELINIT(&bufmgr->surf_list);
396 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
397 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
398 _tbm_surface_internal_debug_data_delete(debug_old_data);
402 _deinit_surface_bufmgr();
406 /* LCOV_EXCL_START */
408 _tbm_surface_check_file_is_symbolic_link(const char* path)
415 if (stat(path, &sb) != 0)
418 if (S_ISLNK(sb.st_mode))
426 _tbm_surface_internal_get_num_planes(tbm_format format)
432 case TBM_FORMAT_RGB332:
433 case TBM_FORMAT_BGR233:
434 case TBM_FORMAT_XRGB4444:
435 case TBM_FORMAT_XBGR4444:
436 case TBM_FORMAT_RGBX4444:
437 case TBM_FORMAT_BGRX4444:
438 case TBM_FORMAT_ARGB4444:
439 case TBM_FORMAT_ABGR4444:
440 case TBM_FORMAT_RGBA4444:
441 case TBM_FORMAT_BGRA4444:
442 case TBM_FORMAT_XRGB1555:
443 case TBM_FORMAT_XBGR1555:
444 case TBM_FORMAT_RGBX5551:
445 case TBM_FORMAT_BGRX5551:
446 case TBM_FORMAT_ARGB1555:
447 case TBM_FORMAT_ABGR1555:
448 case TBM_FORMAT_RGBA5551:
449 case TBM_FORMAT_BGRA5551:
450 case TBM_FORMAT_RGB565:
451 case TBM_FORMAT_BGR565:
452 case TBM_FORMAT_RGB888:
453 case TBM_FORMAT_BGR888:
454 case TBM_FORMAT_XRGB8888:
455 case TBM_FORMAT_XBGR8888:
456 case TBM_FORMAT_RGBX8888:
457 case TBM_FORMAT_BGRX8888:
458 case TBM_FORMAT_ARGB8888:
459 case TBM_FORMAT_ABGR8888:
460 case TBM_FORMAT_RGBA8888:
461 case TBM_FORMAT_BGRA8888:
462 case TBM_FORMAT_XRGB2101010:
463 case TBM_FORMAT_XBGR2101010:
464 case TBM_FORMAT_RGBX1010102:
465 case TBM_FORMAT_BGRX1010102:
466 case TBM_FORMAT_ARGB2101010:
467 case TBM_FORMAT_ABGR2101010:
468 case TBM_FORMAT_RGBA1010102:
469 case TBM_FORMAT_BGRA1010102:
470 case TBM_FORMAT_YUYV:
471 case TBM_FORMAT_YVYU:
472 case TBM_FORMAT_UYVY:
473 case TBM_FORMAT_VYUY:
474 case TBM_FORMAT_AYUV:
477 case TBM_FORMAT_NV12:
478 case TBM_FORMAT_NV12MT:
479 case TBM_FORMAT_NV21:
480 case TBM_FORMAT_NV16:
481 case TBM_FORMAT_NV61:
484 case TBM_FORMAT_YUV410:
485 case TBM_FORMAT_YVU410:
486 case TBM_FORMAT_YUV411:
487 case TBM_FORMAT_YVU411:
488 case TBM_FORMAT_YUV420:
489 case TBM_FORMAT_YVU420:
490 case TBM_FORMAT_YUV422:
491 case TBM_FORMAT_YVU422:
492 case TBM_FORMAT_YUV444:
493 case TBM_FORMAT_YVU444:
498 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
506 _tbm_surface_internal_get_bpp(tbm_format format)
513 case TBM_FORMAT_RGB332:
514 case TBM_FORMAT_BGR233:
517 case TBM_FORMAT_XRGB4444:
518 case TBM_FORMAT_XBGR4444:
519 case TBM_FORMAT_RGBX4444:
520 case TBM_FORMAT_BGRX4444:
521 case TBM_FORMAT_ARGB4444:
522 case TBM_FORMAT_ABGR4444:
523 case TBM_FORMAT_RGBA4444:
524 case TBM_FORMAT_BGRA4444:
525 case TBM_FORMAT_XRGB1555:
526 case TBM_FORMAT_XBGR1555:
527 case TBM_FORMAT_RGBX5551:
528 case TBM_FORMAT_BGRX5551:
529 case TBM_FORMAT_ARGB1555:
530 case TBM_FORMAT_ABGR1555:
531 case TBM_FORMAT_RGBA5551:
532 case TBM_FORMAT_BGRA5551:
533 case TBM_FORMAT_RGB565:
534 case TBM_FORMAT_BGR565:
537 case TBM_FORMAT_RGB888:
538 case TBM_FORMAT_BGR888:
541 case TBM_FORMAT_XRGB8888:
542 case TBM_FORMAT_XBGR8888:
543 case TBM_FORMAT_RGBX8888:
544 case TBM_FORMAT_BGRX8888:
545 case TBM_FORMAT_ARGB8888:
546 case TBM_FORMAT_ABGR8888:
547 case TBM_FORMAT_RGBA8888:
548 case TBM_FORMAT_BGRA8888:
549 case TBM_FORMAT_XRGB2101010:
550 case TBM_FORMAT_XBGR2101010:
551 case TBM_FORMAT_RGBX1010102:
552 case TBM_FORMAT_BGRX1010102:
553 case TBM_FORMAT_ARGB2101010:
554 case TBM_FORMAT_ABGR2101010:
555 case TBM_FORMAT_RGBA1010102:
556 case TBM_FORMAT_BGRA1010102:
557 case TBM_FORMAT_YUYV:
558 case TBM_FORMAT_YVYU:
559 case TBM_FORMAT_UYVY:
560 case TBM_FORMAT_VYUY:
561 case TBM_FORMAT_AYUV:
564 case TBM_FORMAT_NV12:
565 case TBM_FORMAT_NV12MT:
566 case TBM_FORMAT_NV21:
569 case TBM_FORMAT_NV16:
570 case TBM_FORMAT_NV61:
573 case TBM_FORMAT_YUV410:
574 case TBM_FORMAT_YVU410:
577 case TBM_FORMAT_YUV411:
578 case TBM_FORMAT_YVU411:
579 case TBM_FORMAT_YUV420:
580 case TBM_FORMAT_YVU420:
583 case TBM_FORMAT_YUV422:
584 case TBM_FORMAT_YVU422:
587 case TBM_FORMAT_YUV444:
588 case TBM_FORMAT_YVU444:
592 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
599 static struct _tbm_surface *
600 _tbm_surface_internal_create_surface(tbm_bufmgr bufmgr, int width, int height, int format, int flags, tbm_error_e *error)
602 struct _tbm_surface *surf = NULL;
603 uint32_t size = 0, offset = 0, stride = 0, bo_size = 0;
606 surf = calloc(1, sizeof(struct _tbm_surface));
608 /* LCOV_EXCL_START */
609 TBM_ERR("fail to alloc surf\n");
610 *error = TBM_ERROR_OUT_OF_MEMORY;
611 goto alloc_surf_fail;
615 surf->magic = TBM_SURFACE_MAGIC;
616 surf->bufmgr = bufmgr;
617 surf->info.width = width;
618 surf->info.height = height;
619 surf->info.format = format;
620 surf->info.bpp = _tbm_surface_internal_get_bpp(format);
621 if (!surf->info.bpp) {
622 TBM_ERR("fail to get bpp from format(%d), error(%s)\n", format, tbm_error_str(*error));
623 *error = tbm_get_last_error();
627 surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
628 if (!surf->info.num_planes) {
629 TBM_ERR("fail to get num_planes from format(%d), error(%s)\n", format, tbm_error_str(*error));
630 *error = tbm_get_last_error();
631 goto num_planes_fail;
635 /* get size, stride and offset bo_idx */
636 for (i = 0; i < surf->info.num_planes; i++) {
637 if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
638 TBM_ERR("fail to query plane data\n");
639 *error = tbm_get_last_error();
640 goto query_plane_data_fail;
643 surf->info.planes[i].size = size;
644 surf->info.planes[i].offset = offset;
645 surf->info.planes[i].stride = stride;
646 surf->planes_bo_idx[i] = bo_idx;
651 for (i = 0; i < surf->info.num_planes; i++) {
652 surf->info.size += surf->info.planes[i].size;
654 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
655 surf->num_bos = surf->planes_bo_idx[i] + 1;
660 for (i = 0; i < surf->num_bos; i++) {
662 for (j = 0; j < surf->info.num_planes; j++) {
663 if (surf->planes_bo_idx[j] == i)
664 bo_size += surf->info.planes[j].size;
667 if (bufmgr->use_hal_tbm) {
668 surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, surf->info.bpp/8, flags, error);
669 if (*error == TBM_ERROR_NOT_SUPPORTED) {
670 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
672 TBM_ERR("fail to alloc bo idx:%d\n", i);
673 *error = tbm_get_last_error();
677 } else if (bufmgr->backend_module_data) {
678 if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format) {
679 /* LCOV_EXCL_START */
680 surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, surf->info.bpp/8, flags, error);
682 TBM_ERR("fail to tbm_bo_alloc_with_format idx:%d\n", i);
683 *error = tbm_get_last_error();
687 } else if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format && (flags & TBM_BO_TILED)) {
688 /* LCOV_EXCL_START */
689 surf->bos[i] = tbm_bo_alloc_with_tiled_format(bufmgr, width, height, surf->info.bpp/8, format, flags, i, error);
691 TBM_ERR("fail to tbm_bo_alloc_with_tiled_format idx:%d\n", i);
692 *error = tbm_get_last_error();
697 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
699 TBM_ERR("fail to alloc bo idx:%d\n", i);
700 *error = tbm_get_last_error();
705 if (bufmgr->backend->surface_bo_alloc) {
706 /* LCOV_EXCL_START */
707 surf->bos[i] = tbm_bo_alloc_with_surface(bufmgr, width, height, format, flags, i);
709 TBM_ERR("fail to tbm_bo_alloc_with_surface idx:%d\n", i);
710 *error = tbm_get_last_error();
715 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
717 TBM_ERR("fail to alloc bo idx:%d\n", i);
718 *error = tbm_get_last_error();
724 _tbm_bo_set_surface(surf->bos[i], surf);
727 *error = TBM_ERROR_NONE;
732 for (j = 0; j < i; j++) {
734 tbm_bo_unref(surf->bos[j]);
736 query_plane_data_fail:
745 static struct _tbm_surface *
746 _tbm_surface_internal_hal_tbm_create_surface(tbm_bufmgr bufmgr, int width, int height, int format, int flags, tbm_error_e *error)
748 struct _tbm_surface *surf = NULL;
749 uint32_t size = 0, offset = 0, stride = 0, bo_size = 0;
751 hal_tbm_surface *hal_surface = NULL;
752 hal_tbm_bo **hal_bos = NULL;
755 surf = calloc(1, sizeof(struct _tbm_surface));
757 /* LCOV_EXCL_START */
758 TBM_ERR("fail to alloc surf");
759 *error = TBM_ERROR_OUT_OF_MEMORY;
760 goto alloc_surf_fail;
765 surf->magic = TBM_SURFACE_MAGIC;
766 surf->bufmgr = bufmgr;
767 surf->info.width = width;
768 surf->info.height = height;
769 surf->info.format = format;
770 surf->info.bpp = _tbm_surface_internal_get_bpp(format);
771 if (!surf->info.bpp) {
772 TBM_ERR("fail to get bpp from format(%d), error(%s)", format, tbm_error_str(*error));
773 *error = tbm_get_last_error();
778 // get number of planes
779 surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
780 if (!surf->info.num_planes) {
781 TBM_ERR("fail to get num_planes from format(%d), error(%s)", format, tbm_error_str(*error));
782 *error = tbm_get_last_error();
783 goto num_planes_fail;
786 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);
789 surf->hal_surface = hal_surface;
791 // set infomation of planes
792 for (i = 0; i < surf->info.num_planes; i++) {
793 *error = (tbm_error_e)hal_tbm_surface_get_plane_data(hal_surface, i, &size, &offset, &stride, &bo_idx);
794 if (*error != TBM_ERROR_NONE) {
795 goto query_plane_data_fail;
797 surf->info.planes[i].size = size;
798 surf->info.planes[i].offset = offset;
799 surf->info.planes[i].stride = stride;
800 surf->planes_bo_idx[i] = bo_idx;
803 // set infomation of bos
804 hal_bos = hal_tbm_surface_get_bos(hal_surface, &num_bos, (hal_tbm_error *)error);
806 TBM_ERR("fail to get bos, error(%s)", tbm_error_str(*error));
809 surf->num_bos = num_bos;
811 for (i = 0; i < surf->info.num_planes; i++) {
812 surf->info.size += surf->info.planes[i].size;
814 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
815 surf->num_bos = surf->planes_bo_idx[i] + 1;
818 for (i = 0; i < num_bos; i++) {
819 surf->bos[i] = tbm_bo_alloc_with_bo_data(bufmgr, (tbm_backend_bo_data *)hal_bos[i], flags);
821 TBM_ERR("fail to alloc bo idx:%d", i);
822 *error = tbm_get_last_error();
826 _tbm_bo_set_surface(surf->bos[i], surf);
829 // set infomation of planes
830 for (i = 0; i < surf->info.num_planes; i++) {
831 if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
832 TBM_ERR("fail to query plane data");
833 *error = tbm_get_last_error();
834 goto query_plane_data_fail;
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;
842 // count number of bos
844 for (i = 0; i < surf->info.num_planes; i++) {
845 surf->info.size += surf->info.planes[i].size;
847 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
848 surf->num_bos = surf->planes_bo_idx[i] + 1;
851 // set infomation of bos
852 for (i = 0; i < surf->num_bos; i++) {
854 for (j = 0; j < surf->info.num_planes; j++) {
855 if (surf->planes_bo_idx[j] == i)
856 bo_size += surf->info.planes[j].size;
859 surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, surf->info.bpp / 8, flags, error);
860 if (*error == TBM_ERROR_NOT_SUPPORTED) {
861 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
863 TBM_ERR("fail to alloc bo idx:%d", i);
864 *error = tbm_get_last_error();
869 _tbm_bo_set_surface(surf->bos[i], surf);
873 *error = TBM_ERROR_NONE;
879 query_plane_data_fail:
881 hal_tbm_surface_free(hal_surface);
883 for (j = 0; j < i; j++) {
885 tbm_bo_unref(surf->bos[j]);
898 tbm_surface_internal_is_valid(tbm_surface_h surface)
902 _tbm_surface_mutex_lock();
903 _tbm_set_last_result(TBM_ERROR_NONE);
905 /* Return silently if surface is null. */
907 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
908 _tbm_surface_mutex_unlock();
912 ret = _tbm_surface_internal_is_valid(surface);
914 _tbm_surface_mutex_unlock();
920 tbm_surface_internal_query_supported_formats(uint32_t **formats,
923 struct _tbm_bufmgr *bufmgr;
925 bool bufmgr_initialized = false;
928 _tbm_surface_mutex_lock();
929 _tbm_set_last_result(TBM_ERROR_NONE);
931 TBM_SURFACE_RETURN_VAL_IF_FAIL(formats, 0);
932 TBM_SURFACE_RETURN_VAL_IF_FAIL(num, 0);
934 if (!g_surface_bufmgr) {
935 _init_surface_bufmgr();
936 if (!g_surface_bufmgr) {
937 TBM_ERR("fail bufmgr initialization\n");
938 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
941 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
942 bufmgr_initialized = true;
945 bufmgr = g_surface_bufmgr;
947 if (bufmgr->use_hal_tbm) {
948 error = (tbm_error_e)hal_tbm_bufmgr_get_supported_formats(bufmgr->hal_bufmgr, formats, num);
949 /* LCOV_EXCL_START */
950 if (error == TBM_ERROR_NOT_SUPPORTED) {
951 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
953 } else if (error != TBM_ERROR_NONE) {
954 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
959 } else if (bufmgr->backend_module_data) {
960 if (!bufmgr->bufmgr_func->bufmgr_get_supported_formats) {
961 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
965 error = bufmgr->bufmgr_func->bufmgr_get_supported_formats(bufmgr->bufmgr_data, formats, num);
966 if (error != TBM_ERROR_NONE) {
967 /* LCOV_EXCL_START */
968 TBM_ERR("Fail to surface_supported_format. error(%d)\n", error);
970 /* LCOV_EXCL_START */
974 if (!bufmgr->backend->surface_supported_format) {
975 _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
979 ret = bufmgr->backend->surface_supported_format(formats, num);
981 /* LCOV_EXCL_START */
982 TBM_ERR("Fail to surface_supported_format.\n");
983 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
985 /* LCOV_EXCL_START */
989 TBM_TRACE_SURFACE_INTERNAL("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
991 if (bufmgr_initialized) {
992 LIST_DELINIT(&g_surface_bufmgr->surf_list);
993 _deinit_surface_bufmgr();
996 _tbm_surface_mutex_unlock();
1000 /* LCOV_EXCL_START */
1002 if (bufmgr_initialized) {
1003 LIST_DELINIT(&g_surface_bufmgr->surf_list);
1004 _deinit_surface_bufmgr();
1006 _tbm_surface_mutex_unlock();
1008 TBM_ERR("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
1011 /* LCOV_EXCL_STOP */
1015 tbm_surface_internal_get_num_planes(tbm_format format)
1019 _tbm_surface_mutex_lock();
1020 _tbm_set_last_result(TBM_ERROR_NONE);
1022 num_planes = _tbm_surface_internal_get_num_planes(format);
1024 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
1025 _tbm_surface_mutex_unlock();
1029 TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
1031 _tbm_surface_mutex_unlock();
1037 tbm_surface_internal_get_bpp(tbm_format format)
1041 _tbm_surface_mutex_lock();
1042 _tbm_set_last_result(TBM_ERROR_NONE);
1044 bpp = _tbm_surface_internal_get_bpp(format);
1046 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
1047 _tbm_surface_mutex_unlock();
1051 _tbm_surface_mutex_unlock();
1053 TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
1059 tbm_surface_internal_create_with_flags(int width, int height,
1060 int format, int flags)
1062 struct _tbm_bufmgr *bufmgr;
1063 struct _tbm_surface *surf = NULL;
1064 tbm_error_e error = TBM_ERROR_INVALID_OPERATION;
1065 bool bufmgr_initialized = false;
1067 _tbm_surface_mutex_lock();
1068 _tbm_set_last_result(TBM_ERROR_NONE);
1070 TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, NULL);
1071 TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, NULL);
1073 if (!g_surface_bufmgr) {
1074 _init_surface_bufmgr();
1075 if (!g_surface_bufmgr) {
1076 TBM_ERR("fail bufmgr initialization\n");
1077 error = TBM_ERROR_INVALID_OPERATION;
1078 goto check_valid_fail;
1080 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
1081 bufmgr_initialized = true;
1084 bufmgr = g_surface_bufmgr;
1085 if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
1086 TBM_ERR("The bufmgr is invalid\n");
1087 error = TBM_ERROR_INVALID_PARAMETER;
1088 goto check_valid_fail;
1091 if (bufmgr->use_hal_tbm) {
1092 surf = _tbm_surface_internal_hal_tbm_create_surface(bufmgr, width, height, format, flags, &error);
1094 TBM_ERR("_tbm_surface_internal_hal_tbm_create_surface failed.");
1095 goto surface_alloc_fail;
1098 surf = _tbm_surface_internal_create_surface(bufmgr, width, height, format, flags, &error);
1100 TBM_ERR("_tbm_surface_internal_create_surface failed.");
1101 goto surface_alloc_fail;
1105 TBM_TRACE_SURFACE_INTERNAL("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n",
1106 width, height, _tbm_surface_internal_format_to_str(format), flags, surf);
1108 LIST_INITHEAD(&surf->user_data_list);
1109 LIST_INITHEAD(&surf->debug_data_list);
1110 LIST_INITHEAD(&surf->destroy_funcs);
1112 LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1114 _tbm_set_last_result(error);
1115 _tbm_surface_mutex_unlock();
1119 /* LCOV_EXCL_START */
1123 if (bufmgr_initialized && bufmgr) {
1124 LIST_DELINIT(&bufmgr->surf_list);
1125 _deinit_surface_bufmgr();
1128 TBM_ERR("error: width(%d) height(%d) format(%s) flags(%d)\n",
1129 width, height, _tbm_surface_internal_format_to_str(format), flags);
1131 _tbm_set_last_result(error);
1132 _tbm_surface_mutex_unlock();
1134 /* LCOV_EXCL_STOP */
1140 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
1141 tbm_bo *bos, int num)
1143 struct _tbm_bufmgr *bufmgr;
1144 struct _tbm_surface *surf = NULL;
1146 bool bufmgr_initialized = false;
1148 _tbm_surface_mutex_lock();
1149 _tbm_set_last_result(TBM_ERROR_NONE);
1151 TBM_SURFACE_RETURN_VAL_IF_FAIL(bos, NULL);
1152 TBM_SURFACE_RETURN_VAL_IF_FAIL(info, NULL);
1153 TBM_SURFACE_RETURN_VAL_IF_FAIL(info->num_planes > 0, NULL);
1154 TBM_SURFACE_RETURN_VAL_IF_FAIL(num > 0, NULL);
1155 TBM_SURFACE_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
1157 if (!g_surface_bufmgr) {
1158 _init_surface_bufmgr();
1159 if (!g_surface_bufmgr) {
1160 TBM_ERR("fail bufmgr initialization\n");
1161 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1162 goto check_valid_fail;
1164 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
1165 bufmgr_initialized = true;
1168 bufmgr = g_surface_bufmgr;
1169 if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
1170 TBM_ERR("fail to validate the Bufmgr.\n");
1171 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1172 goto check_valid_fail;
1175 surf = calloc(1, sizeof(struct _tbm_surface));
1177 /* LCOV_EXCL_START */
1178 TBM_ERR("fail to allocate struct _tbm_surface.\n");
1179 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1180 goto alloc_surf_fail;
1181 /* LCOV_EXCL_STOP */
1184 surf->magic = TBM_SURFACE_MAGIC;
1185 surf->bufmgr = bufmgr;
1186 surf->info.width = info->width;
1187 surf->info.height = info->height;
1188 surf->info.format = info->format;
1190 surf->info.bpp = info->bpp;
1192 surf->info.bpp = _tbm_surface_internal_get_bpp(info->format);
1193 if (!surf->info.bpp) {
1194 TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1198 surf->info.num_planes = info->num_planes;
1201 /* get size, stride and offset */
1202 for (i = 0; i < info->num_planes; i++) {
1203 surf->info.planes[i].offset = info->planes[i].offset;
1204 surf->info.planes[i].stride = info->planes[i].stride;
1206 if (info->planes[i].size > 0)
1207 surf->info.planes[i].size = info->planes[i].size;
1209 uint32_t size = 0, offset = 0, stride = 0;
1212 if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
1213 TBM_ERR("fail to get plane_data. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1214 goto plane_data_fail;
1216 surf->info.planes[i].size = size;
1220 surf->planes_bo_idx[i] = 0;
1222 surf->planes_bo_idx[i] = i;
1225 if (info->size > 0) {
1226 surf->info.size = info->size;
1228 surf->info.size = 0;
1229 for (i = 0; i < info->num_planes; i++)
1230 surf->info.size += surf->info.planes[i].size;
1233 surf->flags = TBM_BO_DEFAULT;
1235 /* create only one bo */
1236 surf->num_bos = num;
1237 for (i = 0; i < num; i++) {
1238 if (bos[i] == NULL) {
1239 TBM_ERR("bos[%d] is null.\n", i);
1240 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1244 surf->bos[i] = tbm_bo_ref(bos[i]);
1245 _tbm_bo_set_surface(bos[i], surf);
1248 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
1249 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
1251 LIST_INITHEAD(&surf->user_data_list);
1252 LIST_INITHEAD(&surf->debug_data_list);
1253 LIST_INITHEAD(&surf->destroy_funcs);
1255 LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1257 _tbm_surface_mutex_unlock();
1261 /* LCOV_EXCL_START */
1265 for (i = 0; i < num; i++) {
1267 tbm_bo_unref(surf->bos[i]);
1272 if (bufmgr_initialized && bufmgr) {
1273 LIST_DELINIT(&bufmgr->surf_list);
1274 _deinit_surface_bufmgr();
1276 _tbm_surface_mutex_unlock();
1278 TBM_ERR("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
1279 info->width, info->height,
1280 _tbm_surface_internal_format_to_str(info->format), num);
1281 /* LCOV_EXCL_STOP */
1287 tbm_surface_internal_destroy(tbm_surface_h surface)
1289 _tbm_surface_mutex_lock();
1290 _tbm_set_last_result(TBM_ERROR_NONE);
1292 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1296 if (surface->refcnt > 0) {
1297 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1298 _tbm_surface_mutex_unlock();
1302 TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1304 if (surface->refcnt == 0)
1305 _tbm_surface_internal_destroy(surface);
1306 else // if (surface->refcnt < 0)
1307 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1309 _tbm_surface_mutex_unlock();
1313 tbm_surface_internal_ref(tbm_surface_h surface)
1315 _tbm_surface_mutex_lock();
1316 _tbm_set_last_result(TBM_ERROR_NONE);
1318 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1322 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1324 _tbm_surface_mutex_unlock();
1328 tbm_surface_internal_unref(tbm_surface_h surface)
1330 _tbm_surface_mutex_lock();
1331 _tbm_set_last_result(TBM_ERROR_NONE);
1333 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1337 if (surface->refcnt > 0) {
1338 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1339 _tbm_surface_mutex_unlock();
1343 TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1345 if (surface->refcnt == 0)
1346 _tbm_surface_internal_destroy(surface);
1348 _tbm_surface_mutex_unlock();
1352 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
1354 struct _tbm_surface *surf;
1357 _tbm_surface_mutex_lock();
1358 _tbm_set_last_result(TBM_ERROR_NONE);
1360 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1362 surf = (struct _tbm_surface *)surface;
1363 num = surf->num_bos;
1366 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1368 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) num_bos(%d)\n", surface, num);
1370 _tbm_surface_mutex_unlock();
1376 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
1378 struct _tbm_surface *surf;
1381 _tbm_surface_mutex_lock();
1382 _tbm_set_last_result(TBM_ERROR_NONE);
1384 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
1385 TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
1387 surf = (struct _tbm_surface *)surface;
1388 bo = surf->bos[bo_idx];
1390 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
1392 _tbm_surface_mutex_unlock();
1398 tbm_surface_internal_get_size(tbm_surface_h surface)
1400 struct _tbm_surface *surf;
1403 _tbm_surface_mutex_lock();
1404 _tbm_set_last_result(TBM_ERROR_NONE);
1406 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1408 surf = (struct _tbm_surface *)surface;
1409 size = surf->info.size;
1411 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) size(%u)\n", surface, size);
1413 _tbm_surface_mutex_unlock();
1419 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1420 uint32_t *size, uint32_t *offset, uint32_t *pitch)
1422 struct _tbm_surface *surf;
1424 _tbm_surface_mutex_lock();
1425 _tbm_set_last_result(TBM_ERROR_NONE);
1427 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1428 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1430 surf = (struct _tbm_surface *)surface;
1432 if (plane_idx >= surf->info.num_planes) {
1433 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1434 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1435 _tbm_surface_mutex_unlock();
1440 *size = surf->info.planes[plane_idx].size;
1443 *offset = surf->info.planes[plane_idx].offset;
1446 *pitch = surf->info.planes[plane_idx].stride;
1448 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1449 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1450 surf->info.planes[plane_idx].stride);
1452 _tbm_surface_mutex_unlock();
1458 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1459 tbm_surface_info_s *info, int map)
1461 struct _tbm_surface *surf;
1462 tbm_bo_handle bo_handles[4];
1465 int planes_bo_idx[TBM_SURF_PLANE_MAX];
1468 _tbm_surface_mutex_lock();
1469 _tbm_set_last_result(TBM_ERROR_NONE);
1471 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1473 memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1475 surf = (struct _tbm_surface *)surface;
1477 memset(info, 0x00, sizeof(tbm_surface_info_s));
1478 info->width = surf->info.width;
1479 info->height = surf->info.height;
1480 info->format = surf->info.format;
1481 info->bpp = surf->info.bpp;
1482 info->size = surf->info.size;
1483 info->num_planes = surf->info.num_planes;
1485 for (i = 0; i < surf->info.num_planes; i++) {
1486 info->planes[i].size = surf->info.planes[i].size;
1487 info->planes[i].offset = surf->info.planes[i].offset;
1488 info->planes[i].stride = surf->info.planes[i].stride;
1489 planes_bo_idx[i] = surf->planes_bo_idx[i];
1492 for (i = 0; i < surf->num_bos; i++)
1493 bos[i] = surf->bos[i];
1495 num_bos = surf->num_bos;
1498 _tbm_surface_mutex_unlock();
1499 for (i = 0; i < num_bos; i++) {
1500 bo_handles[i] = tbm_bo_map(bos[i], TBM_DEVICE_CPU, opt);
1501 if (bo_handles[i].ptr == NULL) {
1502 for (j = 0; j < i; j++)
1503 tbm_bo_unmap(bos[j]);
1505 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1509 _tbm_surface_mutex_lock();
1511 for (i = 0; i < num_bos; i++) {
1512 bo_handles[i] = tbm_bo_get_handle(bos[i], TBM_DEVICE_CPU);
1513 if (bo_handles[i].ptr == NULL) {
1514 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1515 _tbm_surface_mutex_unlock();
1521 for (i = 0; i < info->num_planes; i++) {
1522 if (bo_handles[planes_bo_idx[i]].ptr)
1523 info->planes[i].ptr = bo_handles[planes_bo_idx[i]].ptr + info->planes[i].offset;
1526 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1528 _tbm_surface_mutex_unlock();
1534 tbm_surface_internal_unmap(tbm_surface_h surface)
1536 struct _tbm_surface *surf;
1539 _tbm_surface_mutex_lock();
1540 _tbm_set_last_result(TBM_ERROR_NONE);
1542 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1544 surf = (struct _tbm_surface *)surface;
1546 for (i = 0; i < surf->num_bos; i++)
1547 tbm_bo_unmap(surf->bos[i]);
1549 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)\n", surface);
1551 _tbm_surface_mutex_unlock();
1555 tbm_surface_internal_get_width(tbm_surface_h surface)
1557 struct _tbm_surface *surf;
1560 _tbm_surface_mutex_lock();
1561 _tbm_set_last_result(TBM_ERROR_NONE);
1563 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1565 surf = (struct _tbm_surface *)surface;
1566 width = surf->info.width;
1568 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u)\n", surface, width);
1570 _tbm_surface_mutex_unlock();
1576 tbm_surface_internal_get_height(tbm_surface_h surface)
1578 struct _tbm_surface *surf;
1579 unsigned int height;
1581 _tbm_surface_mutex_lock();
1582 _tbm_set_last_result(TBM_ERROR_NONE);
1584 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1586 surf = (struct _tbm_surface *)surface;
1587 height = surf->info.height;
1589 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) height(%u)\n", surface, height);
1591 _tbm_surface_mutex_unlock();
1598 tbm_surface_internal_get_format(tbm_surface_h surface)
1600 struct _tbm_surface *surf;
1603 _tbm_surface_mutex_lock();
1604 _tbm_set_last_result(TBM_ERROR_NONE);
1606 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1608 surf = (struct _tbm_surface *)surface;
1609 format = surf->info.format;
1611 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1613 _tbm_surface_mutex_unlock();
1619 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1621 struct _tbm_surface *surf;
1624 _tbm_surface_mutex_lock();
1625 _tbm_set_last_result(TBM_ERROR_NONE);
1627 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1628 TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1630 surf = (struct _tbm_surface *)surface;
1631 bo_idx = surf->planes_bo_idx[plane_idx];
1633 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1635 _tbm_surface_mutex_unlock();
1641 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1642 tbm_data_free data_free_func)
1644 tbm_user_data *data;
1646 _tbm_surface_mutex_lock();
1647 _tbm_set_last_result(TBM_ERROR_NONE);
1649 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1651 /* check if the data according to the key exist if so, return false. */
1652 data = user_data_lookup(&surface->user_data_list, key);
1654 TBM_TRACE_SURFACE_INTERNAL("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1655 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1656 _tbm_surface_mutex_unlock();
1660 data = user_data_create(key, data_free_func);
1662 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1663 _tbm_surface_mutex_unlock();
1667 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1669 LIST_ADD(&data->item_link, &surface->user_data_list);
1671 _tbm_surface_mutex_unlock();
1677 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1680 tbm_user_data *old_data;
1682 _tbm_surface_mutex_lock();
1683 _tbm_set_last_result(TBM_ERROR_NONE);
1685 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1687 old_data = user_data_lookup(&surface->user_data_list, key);
1689 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1690 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1691 _tbm_surface_mutex_unlock();
1695 if (old_data->data && old_data->free_func)
1696 old_data->free_func(old_data->data);
1698 old_data->data = data;
1700 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1702 _tbm_surface_mutex_unlock();
1708 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1711 tbm_user_data *old_data;
1713 _tbm_surface_mutex_lock();
1714 _tbm_set_last_result(TBM_ERROR_NONE);
1716 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1719 TBM_ERR("error: tbm_surface(%p) key(%lu)\n", surface, key);
1720 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1721 _tbm_surface_mutex_unlock();
1726 old_data = user_data_lookup(&surface->user_data_list, key);
1728 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1729 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1730 _tbm_surface_mutex_unlock();
1734 *data = old_data->data;
1736 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1738 _tbm_surface_mutex_unlock();
1744 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1747 tbm_user_data *old_data = (void *)0;
1749 _tbm_surface_mutex_lock();
1750 _tbm_set_last_result(TBM_ERROR_NONE);
1752 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1754 old_data = user_data_lookup(&surface->user_data_list, key);
1756 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1757 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1758 _tbm_surface_mutex_unlock();
1762 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1764 user_data_delete(old_data);
1766 _tbm_surface_mutex_unlock();
1771 /* LCOV_EXCL_START */
1773 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1775 TBM_RETURN_VAL_IF_FAIL(surface, 0);
1777 return surface->debug_pid;
1781 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1783 _tbm_surface_mutex_lock();
1784 _tbm_set_last_result(TBM_ERROR_NONE);
1786 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1788 surface->debug_pid = pid;
1790 _tbm_surface_mutex_unlock();
1793 static tbm_surface_debug_data *
1794 _tbm_surface_internal_debug_data_create(char *key, char *value)
1796 tbm_surface_debug_data *debug_data = NULL;
1798 debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1800 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1801 TBM_ERR("fail to allocate the debug_data.");
1805 if (key) debug_data->key = strdup(key);
1806 if (value) debug_data->value = strdup(value);
1812 _tbm_surface_internal_debug_data_value_update(tbm_surface_debug_data *debug_data, char *value)
1814 if (!debug_data->value && !value)
1817 if (debug_data->value && value && !strncmp(debug_data->value, value, strlen(debug_data->value)))
1820 if (debug_data->value)
1821 free(debug_data->value);
1824 debug_data->value = strdup(value);
1826 debug_data->value = NULL;
1829 static tbm_surface_debug_data *
1830 _tbm_surface_internal_debug_data_find(struct list_head *list, char *key)
1832 tbm_surface_debug_data *debug_data = NULL;
1834 if (LIST_IS_EMPTY(list))
1837 LIST_FOR_EACH_ENTRY(debug_data, list, item_link) {
1838 if (!strncmp(debug_data->key, key, strlen(debug_data->key)))
1846 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1848 tbm_surface_debug_data *debug_data = NULL;
1849 tbm_bufmgr bufmgr = NULL;
1851 _tbm_surface_mutex_lock();
1852 _tbm_set_last_result(TBM_ERROR_NONE);
1854 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1855 TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1857 bufmgr = surface->bufmgr;
1859 TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1861 debug_data = _tbm_surface_internal_debug_data_find(&surface->debug_data_list, key);
1863 _tbm_surface_internal_debug_data_value_update(debug_data, value);
1865 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1867 TBM_ERR("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1868 _tbm_surface_mutex_unlock();
1872 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1875 /* add new debug key to list */
1876 debug_data = _tbm_surface_internal_debug_data_find(&bufmgr->debug_key_list, key);
1878 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1880 LIST_ADDTAIL(&debug_data->item_link, &bufmgr->debug_key_list);
1883 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1885 _tbm_surface_mutex_unlock();
1891 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1893 tbm_surface_debug_data *old_data = NULL;
1895 TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1897 if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1898 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1899 if (!strcmp(old_data->key, key))
1900 return old_data->value;
1907 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1908 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1910 struct _tbm_surface_dump_buf_info {
1920 tbm_surface_info_s info;
1922 struct list_head link;
1925 struct _tbm_surface_dump_info {
1926 char *path; // copy???
1929 struct list_head *link;
1930 struct list_head surface_list; /* link of surface */
1933 static tbm_surface_dump_info *g_dump_info = NULL;
1934 static const char *dump_postfix[2] = {"png", "yuv"};
1935 static double scale_factor;
1938 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1939 void *data2, int size2, void *data3, int size3)
1942 unsigned int *blocks;
1944 if (_tbm_surface_check_file_is_symbolic_link(file))
1945 TBM_ERR("%s is symbolic link\n", file);
1947 fp = fopen(file, "w+");
1948 TBM_RETURN_IF_FAIL(fp != NULL);
1950 blocks = (unsigned int *)data1;
1951 fwrite(blocks, 1, size1, fp);
1954 blocks = (unsigned int *)data2;
1955 fwrite(blocks, 1, size2, fp);
1959 blocks = (unsigned int *)data3;
1960 fwrite(blocks, 1, size3, fp);
1967 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height, int stride, int format)
1969 unsigned int *blocks = (unsigned int *)data;
1972 png_bytep *row_pointers;
1975 if (_tbm_surface_check_file_is_symbolic_link(file))
1976 TBM_ERR("%s is symbolic link\n", file);
1978 fp = fopen(file, "wb");
1979 TBM_RETURN_IF_FAIL(fp != NULL);
1981 png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1984 TBM_ERR("fail to create a png write structure.\n");
1989 png_infop pPngInfo = png_create_info_struct(pPngStruct);
1991 TBM_ERR("fail to create a png info structure.\n");
1992 png_destroy_write_struct(&pPngStruct, NULL);
1997 if (setjmp(png_jmpbuf(pPngStruct))) {
1998 /* if png has problem of writing the file, we get here */
1999 TBM_ERR("fail to write png file.\n");
2000 png_destroy_write_struct(&pPngStruct, &pPngInfo);
2005 png_init_io(pPngStruct, fp);
2006 if (format == TBM_FORMAT_XRGB8888) {
2008 png_set_IHDR(pPngStruct,
2015 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
2018 png_set_IHDR(pPngStruct,
2023 PNG_COLOR_TYPE_RGBA,
2025 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
2028 png_set_bgr(pPngStruct);
2029 png_write_info(pPngStruct, pPngInfo);
2031 row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
2032 if (!row_pointers) {
2033 TBM_ERR("fail to allocate the png row_pointers.\n");
2034 png_destroy_write_struct(&pPngStruct, &pPngInfo);
2039 for (y = 0; y < height; ++y) {
2043 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
2045 TBM_ERR("fail to allocate the png row.\n");
2046 for (x = 0; x < y; x++)
2047 png_free(pPngStruct, row_pointers[x]);
2048 png_free(pPngStruct, row_pointers);
2049 png_destroy_write_struct(&pPngStruct, &pPngInfo);
2053 row_pointers[y] = (png_bytep)row;
2055 for (x = 0; x < width; ++x) {
2056 unsigned int curBlock = blocks[(y * (stride >> 2)) + x];
2058 if (pixel_size == 3) { // XRGB8888
2059 row[x * pixel_size] = (curBlock & 0xFF);
2060 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
2061 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
2062 } else { // ARGB8888
2063 row[x * pixel_size] = (curBlock & 0xFF);
2064 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
2065 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
2066 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
2071 png_write_image(pPngStruct, row_pointers);
2072 png_write_end(pPngStruct, pPngInfo);
2074 for (y = 0; y < height; y++)
2075 png_free(pPngStruct, row_pointers[y]);
2076 png_free(pPngStruct, row_pointers);
2078 png_destroy_write_struct(&pPngStruct, &pPngInfo);
2084 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
2086 TBM_RETURN_IF_FAIL(path != NULL);
2087 TBM_RETURN_IF_FAIL(w > 0);
2088 TBM_RETURN_IF_FAIL(h > 0);
2089 TBM_RETURN_IF_FAIL(count > 0);
2091 tbm_surface_dump_buf_info *buf_info = NULL;
2092 tbm_surface_h tbm_surface;
2093 tbm_surface_info_s info;
2098 TBM_WRN("waring already running the tbm_surface_internal_dump.\n");
2102 g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
2103 TBM_RETURN_IF_FAIL(g_dump_info);
2105 LIST_INITHEAD(&g_dump_info->surface_list);
2106 g_dump_info->count = 0;
2107 g_dump_info->dump_max = count;
2109 /* get buffer size */
2110 tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
2111 if (tbm_surface == NULL) {
2112 TBM_ERR("tbm_surface_create fail\n");
2118 if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
2119 TBM_ERR("tbm_surface_get_info fail\n");
2120 tbm_surface_destroy(tbm_surface);
2125 buffer_size = info.size;
2126 tbm_surface_destroy(tbm_surface);
2128 /* create dump lists */
2129 for (i = 0; i < count; i++) {
2132 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
2133 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
2135 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
2137 TBM_ERR("fail to allocate the tbm_bo[%d]\n", i);
2142 buf_info->index = i;
2144 buf_info->size = buffer_size;
2146 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
2149 g_dump_info->path = path;
2150 g_dump_info->link = &g_dump_info->surface_list;
2154 TBM_INFO("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
2159 /* free resources */
2160 if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2161 tbm_surface_dump_buf_info *tmp;
2163 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2164 tbm_bo_unref(buf_info->bo);
2165 LIST_DEL(&buf_info->link);
2170 TBM_ERR("Dump Start fail.. path:%s\n", g_dump_info->path);
2179 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
2186 tbm_surface_internal_dump_start(path, w, h, count);
2187 scale_factor = scale;
2191 tbm_surface_internal_dump_end(void)
2193 tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
2194 tbm_bo_handle bo_handle;
2199 if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2206 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2209 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
2210 if (bo_handle.ptr == NULL) {
2211 tbm_bo_unref(buf_info->bo);
2212 LIST_DEL(&buf_info->link);
2217 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
2218 TBM_INFO("Dump File.. %s generated.\n", file);
2220 if (buf_info->dirty) {
2221 void *ptr1 = NULL, *ptr2 = NULL;
2223 switch (buf_info->info.format) {
2224 case TBM_FORMAT_ARGB8888:
2225 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2226 buf_info->info.planes[0].stride >> 2,
2227 buf_info->info.height,
2228 buf_info->info.planes[0].stride,
2229 TBM_FORMAT_ARGB8888);
2231 case TBM_FORMAT_XRGB8888:
2232 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2233 buf_info->info.planes[0].stride >> 2,
2234 buf_info->info.height,
2235 buf_info->info.planes[0].stride,
2236 TBM_FORMAT_XRGB8888);
2238 case TBM_FORMAT_YVU420:
2239 case TBM_FORMAT_YUV420:
2240 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2241 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
2242 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2243 buf_info->info.planes[0].stride * buf_info->info.height,
2245 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2247 buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
2249 case TBM_FORMAT_NV12:
2250 case TBM_FORMAT_NV21:
2251 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2252 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2253 buf_info->info.planes[0].stride * buf_info->info.height,
2255 buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2258 case TBM_FORMAT_YUYV:
2259 case TBM_FORMAT_UYVY:
2260 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2261 buf_info->info.planes[0].stride * buf_info->info.height,
2265 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
2268 } else if (buf_info->dirty_shm)
2269 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2270 buf_info->shm_stride >> 2,
2272 buf_info->shm_stride, 0);
2274 tbm_bo_unmap(buf_info->bo);
2275 tbm_bo_unref(buf_info->bo);
2276 LIST_DEL(&buf_info->link);
2283 TBM_INFO("Dump End..\n");
2286 static pixman_format_code_t
2287 _tbm_surface_internal_pixman_format_get(tbm_format format)
2290 case TBM_FORMAT_ARGB8888:
2291 return PIXMAN_a8r8g8b8;
2292 case TBM_FORMAT_XRGB8888:
2293 return PIXMAN_x8r8g8b8;
2302 * This function supports only if a buffer has below formats.
2303 * - TBM_FORMAT_ARGB8888
2304 * - TBM_FORMAT_XRGB8888
2306 static tbm_surface_error_e
2307 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
2308 int format, int src_stride, int src_w, int src_h,
2309 int dst_stride, int dst_w, int dst_h)
2311 pixman_image_t *src_img = NULL, *dst_img = NULL;
2312 pixman_format_code_t pixman_format;
2313 pixman_transform_t t;
2314 struct pixman_f_transform ft;
2315 double scale_x, scale_y;
2317 TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2318 TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2320 pixman_format = _tbm_surface_internal_pixman_format_get(format);
2321 TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2324 src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2325 (uint32_t*)src_ptr, src_stride);
2326 TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2329 dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2330 (uint32_t*)dst_ptr, dst_stride);
2331 TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2333 pixman_f_transform_init_identity(&ft);
2335 scale_x = (double)src_w / dst_w;
2336 scale_y = (double)src_h / dst_h;
2338 pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2339 pixman_f_transform_translate(&ft, NULL, 0, 0);
2340 pixman_transform_from_pixman_f_transform(&t, &ft);
2341 pixman_image_set_transform(src_img, &t);
2343 pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2344 0, 0, 0, 0, 0, 0, dst_w, dst_h);
2346 pixman_image_unref(src_img);
2347 pixman_image_unref(dst_img);
2349 return TBM_SURFACE_ERROR_NONE;
2353 pixman_image_unref(src_img);
2355 return TBM_SURFACE_ERROR_INVALID_OPERATION;
2358 #define MAX_BOS 4 // This value is came from bos[4] in struct _tbm_surface
2359 #define KEY_LEN 5 // "_XXXX"
2360 #define KEYS_LEN KEY_LEN * MAX_BOS
2362 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2364 char *keys, temp_key[KEY_LEN + 1];
2365 struct _tbm_surface *surf;
2369 _tbm_surface_mutex_lock();
2371 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2373 surf = (struct _tbm_surface *)surface;
2375 num_bos = surf->num_bos;
2376 if (num_bos > MAX_BOS)
2379 keys = calloc(KEYS_LEN + 1, sizeof(char));
2381 TBM_ERR("Failed to alloc memory");
2382 _tbm_surface_mutex_unlock();
2386 for (i = 0; i < num_bos; i++) {
2387 memset(temp_key, 0x00, KEY_LEN + 1);
2389 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2390 strncat(keys, temp_key, KEY_LEN + 1);
2393 _tbm_surface_mutex_unlock();
2398 static void _tbm_surface_internal_put_keys(char *keys)
2405 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2407 TBM_RETURN_IF_FAIL(surface != NULL);
2408 TBM_RETURN_IF_FAIL(type != NULL);
2410 tbm_surface_dump_buf_info *buf_info;
2411 struct list_head *next_link;
2412 tbm_surface_info_s info;
2413 tbm_bo_handle bo_handle;
2414 const char *postfix;
2415 const char *format = NULL;
2422 next_link = g_dump_info->link->next;
2423 TBM_RETURN_IF_FAIL(next_link != NULL);
2425 if (next_link == &g_dump_info->surface_list) {
2426 next_link = next_link->next;
2427 TBM_RETURN_IF_FAIL(next_link != NULL);
2430 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2431 TBM_RETURN_IF_FAIL(buf_info != NULL);
2433 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2434 TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2436 if (scale_factor > 0.0) {
2439 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
2440 TBM_WRN("Dump with scale skip. unsupported format(%s)\n",
2441 _tbm_surface_internal_format_to_str(info.format));
2442 tbm_surface_unmap(surface);
2446 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2448 buf_info->info.width = info.width * scale_factor;
2449 buf_info->info.height = info.height * scale_factor;
2450 buf_info->info.format = info.format;
2451 buf_info->info.bpp = _tbm_surface_internal_get_bpp(buf_info->info.format);
2452 if (!buf_info->info.bpp) {
2453 TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
2454 tbm_surface_unmap(surface);
2457 buf_info->info.num_planes = 1;
2458 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2459 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2461 if (buf_info->info.size > buf_info->size) {
2462 TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)\n",
2463 buf_info->info.size, buf_info->size);
2464 tbm_surface_unmap(surface);
2468 if (info.size > buf_info->size) {
2469 TBM_WRN("Dump skip. surface over created buffer size(%u, %d)\n",
2470 info.size, buf_info->size);
2471 tbm_surface_unmap(surface);
2475 /* make the file information */
2476 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2479 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888) {
2480 postfix = dump_postfix[0];
2481 format = _tbm_surface_internal_format_to_str(info.format);
2483 postfix = dump_postfix[1];
2485 keys = _tbm_surface_internal_get_keys(surface);
2487 TBM_ERR("fail to get keys");
2488 tbm_surface_unmap(surface);
2493 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2494 if (!bo_handle.ptr) {
2495 TBM_ERR("fail to map bo");
2496 _tbm_surface_internal_put_keys(keys);
2497 tbm_surface_unmap(surface);
2500 memset(bo_handle.ptr, 0x00, buf_info->size);
2502 switch (info.format) {
2503 case TBM_FORMAT_ARGB8888:
2504 case TBM_FORMAT_XRGB8888:
2505 snprintf(buf_info->name, sizeof(buf_info->name),
2506 "%10.3f_%03d%s_%p_%s-%s.%s",
2507 _tbm_surface_internal_get_time(),
2508 g_dump_info->count++, keys, surface, format, type, postfix);
2510 if (scale_factor > 0.0) {
2511 ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2513 buf_info->info.format,
2514 info.planes[0].stride,
2515 info.width, info.height,
2516 buf_info->info.planes[0].stride,
2517 buf_info->info.width,
2518 buf_info->info.height);
2519 if (ret != TBM_SURFACE_ERROR_NONE) {
2520 TBM_ERR("fail to scale buffer");
2521 tbm_bo_unmap(buf_info->bo);
2522 _tbm_surface_internal_put_keys(keys);
2523 tbm_surface_unmap(surface);
2527 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2529 case TBM_FORMAT_YVU420:
2530 case TBM_FORMAT_YUV420:
2531 snprintf(buf_info->name, sizeof(buf_info->name),
2532 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2533 _tbm_surface_internal_get_time(),
2534 g_dump_info->count++, keys, type, info.planes[0].stride,
2535 info.height, FOURCC_STR(info.format), postfix);
2536 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2537 bo_handle.ptr += info.planes[0].stride * info.height;
2538 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2539 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2540 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2542 case TBM_FORMAT_NV12:
2543 case TBM_FORMAT_NV21:
2544 snprintf(buf_info->name, sizeof(buf_info->name),
2545 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2546 _tbm_surface_internal_get_time(),
2547 g_dump_info->count++, keys, type, info.planes[0].stride,
2548 info.height, FOURCC_STR(info.format), postfix);
2549 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2550 bo_handle.ptr += info.planes[0].stride * info.height;
2551 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2553 case TBM_FORMAT_YUYV:
2554 case TBM_FORMAT_UYVY:
2555 snprintf(buf_info->name, sizeof(buf_info->name),
2556 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2557 _tbm_surface_internal_get_time(),
2558 g_dump_info->count++, keys, type, info.planes[0].stride,
2559 info.height, FOURCC_STR(info.format), postfix);
2560 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2563 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2564 tbm_bo_unmap(buf_info->bo);
2565 _tbm_surface_internal_put_keys(keys);
2566 tbm_surface_unmap(surface);
2570 tbm_bo_unmap(buf_info->bo);
2572 _tbm_surface_internal_put_keys(keys);
2574 tbm_surface_unmap(surface);
2576 buf_info->dirty = 1;
2577 buf_info->dirty_shm = 0;
2579 if (g_dump_info->count == 1000)
2580 g_dump_info->count = 0;
2582 g_dump_info->link = next_link;
2584 TBM_INFO("Dump %s \n", buf_info->name);
2587 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2590 TBM_RETURN_IF_FAIL(ptr != NULL);
2591 TBM_RETURN_IF_FAIL(w > 0);
2592 TBM_RETURN_IF_FAIL(h > 0);
2593 TBM_RETURN_IF_FAIL(stride > 0);
2594 TBM_RETURN_IF_FAIL(type != NULL);
2596 tbm_surface_dump_buf_info *buf_info;
2597 struct list_head *next_link;
2598 tbm_bo_handle bo_handle;
2599 int ret, size, dw = 0, dh = 0, dstride = 0;
2604 next_link = g_dump_info->link->next;
2605 TBM_RETURN_IF_FAIL(next_link != NULL);
2607 if (next_link == &g_dump_info->surface_list) {
2608 next_link = next_link->next;
2609 TBM_RETURN_IF_FAIL(next_link != NULL);
2612 buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2613 TBM_RETURN_IF_FAIL(buf_info != NULL);
2615 if (scale_factor > 0.0) {
2618 dw = w * scale_factor;
2619 dh = h * scale_factor;
2621 size = dstride * dh;
2625 if (size > buf_info->size) {
2626 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2627 size, buf_info->size);
2632 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2633 TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2635 memset(bo_handle.ptr, 0x00, buf_info->size);
2636 memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2638 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2639 _tbm_surface_internal_get_time(),
2640 g_dump_info->count++, type, dump_postfix[0]);
2641 if (scale_factor > 0.0) {
2642 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2643 TBM_FORMAT_ARGB8888, stride,
2644 w, h, dstride, dw, dh);
2645 if (ret != TBM_SURFACE_ERROR_NONE) {
2646 TBM_ERR("fail to scale buffer");
2647 tbm_bo_unmap(buf_info->bo);
2650 buf_info->shm_stride = dstride;
2651 buf_info->shm_h = dh;
2653 memcpy(bo_handle.ptr, ptr, size);
2654 buf_info->shm_stride = stride;
2655 buf_info->shm_h = h;
2658 tbm_bo_unmap(buf_info->bo);
2660 buf_info->dirty = 0;
2661 buf_info->dirty_shm = 1;
2663 if (g_dump_info->count == 1000)
2664 g_dump_info->count = 0;
2666 g_dump_info->link = next_link;
2668 TBM_INFO("Dump %s \n", buf_info->name);
2672 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2674 TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2675 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2676 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2678 tbm_surface_info_s info;
2679 const char *postfix;
2683 ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2684 TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2686 if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2687 postfix = dump_postfix[0];
2689 postfix = dump_postfix[1];
2691 if (strcmp(postfix, type)) {
2692 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2693 tbm_surface_unmap(surface);
2697 snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2699 if (!access(file, 0)) {
2700 TBM_ERR("can't capture buffer, exist file %s", file);
2701 tbm_surface_unmap(surface);
2705 switch (info.format) {
2706 case TBM_FORMAT_ARGB8888:
2707 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2710 info.planes[0].stride,
2711 TBM_FORMAT_ARGB8888);
2713 case TBM_FORMAT_XRGB8888:
2714 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2717 info.planes[0].stride,
2718 TBM_FORMAT_XRGB8888);
2720 case TBM_FORMAT_YVU420:
2721 case TBM_FORMAT_YUV420:
2722 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2723 info.planes[0].stride * info.height,
2725 info.planes[1].stride * (info.height >> 1),
2727 info.planes[2].stride * (info.height >> 1));
2729 case TBM_FORMAT_NV12:
2730 case TBM_FORMAT_NV21:
2731 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2732 info.planes[0].stride * info.height,
2734 info.planes[1].stride * (info.height >> 1),
2737 case TBM_FORMAT_YUYV:
2738 case TBM_FORMAT_UYVY:
2739 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2740 info.planes[0].stride * info.height,
2744 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2745 tbm_surface_unmap(surface);
2749 tbm_surface_unmap(surface);
2751 TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2757 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2758 const char *path, const char *name, const char *type)
2760 TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2761 TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2762 TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2763 TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2764 TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2765 TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2769 if (strcmp(dump_postfix[0], type)) {
2770 TBM_ERR("Not supported type:%s'", type);
2774 snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2776 if (!access(file, 0)) {
2777 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2781 _tbm_surface_internal_dump_file_png(file, ptr, w, h, stride, 0);
2783 TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2789 tbm_surface_internal_set_damage(tbm_surface_h surface, int x, int y, int width, int height)
2791 struct _tbm_surface *surf;
2793 _tbm_surface_mutex_lock();
2794 _tbm_set_last_result(TBM_ERROR_NONE);
2796 TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, 0);
2797 TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, 0);
2798 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2800 surf = (struct _tbm_surface *)surface;
2804 surf->damage.width = width;
2805 surf->damage.height = height;
2807 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2808 surface, x, y, width, height);
2810 _tbm_surface_mutex_unlock();
2816 tbm_surface_internal_get_damage(tbm_surface_h surface, int *x, int *y, int *width, int *height)
2818 struct _tbm_surface *surf;
2820 _tbm_surface_mutex_lock();
2821 _tbm_set_last_result(TBM_ERROR_NONE);
2823 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2825 surf = (struct _tbm_surface *)surface;
2827 if (x) *x = surf->damage.x;
2828 if (y) *y = surf->damage.y;
2829 if (width) *width = surf->damage.width;
2830 if (height) *height = surf->damage.height;
2832 TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2833 surface, surf->damage.x, surf->damage.y, surf->damage.width, surf->damage.height);
2835 _tbm_surface_mutex_unlock();
2841 tbm_surface_internal_add_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2843 struct _tbm_surface *surf;
2844 tbm_surface_destroy_func_info *func_info = NULL;
2846 _tbm_surface_mutex_lock();
2847 _tbm_set_last_result(TBM_ERROR_NONE);
2849 TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2850 TBM_SURFACE_RETURN_VAL_IF_FAIL(func != NULL, 0);
2852 surf = (struct _tbm_surface *)surface;
2853 LIST_FOR_EACH_ENTRY(func_info, &surf->destroy_funcs, item_link) {
2854 if (func_info->destroy_func == func && func_info->user_data == user_data) {
2855 TBM_ERR("can't add twice");
2856 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
2857 _tbm_surface_mutex_unlock();
2862 func_info = calloc(1, sizeof(tbm_surface_destroy_func_info));
2863 if (func_info == NULL) {
2864 TBM_ERR("alloc failed");
2865 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
2866 _tbm_surface_mutex_unlock();
2870 func_info->destroy_func = func;
2871 func_info->user_data = user_data;
2873 LIST_ADDTAIL(&func_info->item_link, &surf->destroy_funcs);
2875 _tbm_surface_mutex_unlock();
2881 tbm_surface_internal_remove_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2883 struct _tbm_surface *surf;
2884 tbm_surface_destroy_func_info *func_info = NULL, *next = NULL;
2886 _tbm_surface_mutex_lock();
2887 _tbm_set_last_result(TBM_ERROR_NONE);
2889 TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
2890 TBM_SURFACE_RETURN_IF_FAIL(func != NULL);
2892 surf = (struct _tbm_surface *)surface;
2893 LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &surf->destroy_funcs, item_link) {
2894 if (func_info->destroy_func != func || func_info->user_data != user_data)
2897 LIST_DEL(&func_info->item_link);
2900 _tbm_surface_mutex_unlock();
2905 _tbm_surface_mutex_unlock();
2908 tbm_surface_buffer_data *
2909 tbm_surface_internal_export(tbm_surface_h surface, tbm_error_e *error)
2916 tbm_surface_internal_import(tbm_surface_info_s *surface_info, tbm_surface_buffer_data *buffer_data, tbm_error_e *error)