tbm_surface_internal: check bufmgr init success before list init
[platform/core/uifw/libtbm.git] / src / tbm_surface_internal.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2014 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: SooChan Lim <sc1.lim@samsung.com>, Sangjin Lee <lsj119@samsung.com>
8 Boram Park <boram1288.park@samsung.com>, Changyeon Lee <cyeon.lee@samsung.com>
9
10 Permission is hereby granted, free of charge, to any person obtaining a
11 copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sub license, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
17
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial portions
20 of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
25 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
27 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
28 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 **************************************************************************/
31
32 #include "config.h"
33
34 #include <stdio.h>
35 #include <time.h>
36 #include <sys/time.h>
37 #include "tbm_bufmgr.h"
38 #include "tbm_bufmgr_int.h"
39 #include "tbm_surface_internal.h"
40 #include "list.h"
41 #include <png.h>
42 #include <pixman.h>
43
44 #define TBM_SURFACE_MAGIC 0xBF021234
45
46 static tbm_bufmgr g_surface_bufmgr;
47 static pthread_mutex_t tbm_surface_lock = PTHREAD_MUTEX_INITIALIZER;
48 void _tbm_surface_mutex_unlock(void);
49
50 /* check condition */
51 #define TBM_SURFACE_RETURN_IF_FAIL(cond) {\
52         if (!(cond)) {\
53                 TBM_ERR("'%s' failed.\n", #cond);\
54                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
55                 _tbm_surface_mutex_unlock();\
56                 return;\
57         } \
58 }
59
60 #define TBM_SURFACE_RETURN_VAL_IF_FAIL(cond, val) {\
61         if (!(cond)) {\
62                 TBM_ERR("'%s' failed.\n", #cond);\
63                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
64                 _tbm_surface_mutex_unlock();\
65                 return val;\
66         } \
67 }
68
69 /* LCOV_EXCL_START */
70 static double
71 _tbm_surface_internal_get_time(void)
72 {
73         struct timespec tp;
74         unsigned int time;
75
76         clock_gettime(CLOCK_MONOTONIC, &tp);
77         time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
78
79         return time / 1000.0;
80 }
81
82 static void
83 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
84 {
85         LIST_DEL(&debug_data->item_link);
86
87         if (debug_data->key) free(debug_data->key);
88         if (debug_data->value) free(debug_data->value);
89         free(debug_data);
90 }
91
92 char *
93 _tbm_surface_internal_format_to_str(tbm_format format)
94 {
95         switch (format) {
96         case TBM_FORMAT_C8:
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";
214         default:
215                 return "unknwon";
216         }
217 }
218
219 void
220 _tbm_surface_mutex_lock(void)
221 {
222         pthread_mutex_lock(&tbm_surface_lock);
223 }
224
225 void
226 _tbm_surface_mutex_unlock(void)
227 {
228         pthread_mutex_unlock(&tbm_surface_lock);
229 }
230
231 static void
232 _init_surface_bufmgr(void)
233 {
234         g_surface_bufmgr = tbm_bufmgr_init(-1);
235 }
236
237 static void
238 _deinit_surface_bufmgr(void)
239 {
240         if (!g_surface_bufmgr)
241                 return;
242
243         tbm_bufmgr_deinit(g_surface_bufmgr);
244         g_surface_bufmgr = NULL;
245 }
246 /* LCOV_EXCL_STOP */
247
248 static int
249 _tbm_surface_internal_magic_check(tbm_surface_h surface)
250 {
251         if (surface->magic != TBM_SURFACE_MAGIC)
252                 return 0;
253
254         return 1;
255 }
256
257 static int
258 _tbm_surface_internal_is_valid(tbm_surface_h surface)
259 {
260         if (!surface) {
261                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
262                 TBM_ERR("error: No valid tbm_surface is NULL\n");
263                 return 0;
264         }
265
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);
269                 return 0;
270         }
271
272         return 1;
273 }
274
275 static int
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)
278 {
279         TBM_RETURN_VAL_IF_FAIL(surface, 0);
280         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
281
282         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
283         struct _tbm_bufmgr *bufmgr = surf->bufmgr;
284         int ret = 0;
285         tbm_error_e error;
286
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);
291
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);
298                         return 0;
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);
302                         return 0;
303                 }
304                 /* LCOV_EXCL_STOP */
305                 ret = 1;
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);
309                         return 0;
310                 }
311
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);
318                         return 0;
319                         /* LCOV_EXCL_STOP */
320                 }
321                 ret = 1;
322         } else {
323                 if (!bufmgr->backend->surface_get_plane_data) {
324                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
325                         return 0;
326                 }
327
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);
330                 if (!ret) {
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);
334                         return 0;
335                         /* LCOV_EXCL_STOP */
336                 }
337         }
338
339         return ret;
340 }
341
342 static void
343 _tbm_surface_internal_destroy(tbm_surface_h surface)
344 {
345         int i;
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;
350
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);
354                 }
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);
358                         free(func_info);
359                 }
360         }
361
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);
367                 }
368         }
369
370         for (i = 0; i < surface->num_bos; i++) {
371                 surface->bos[i]->surface = NULL;
372
373                 tbm_bo_unref(surface->bos[i]);
374                 surface->bos[i] = NULL;
375         }
376
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);
380         }
381
382         LIST_DEL(&surface->item_link);
383         surface->magic = 0;
384
385         free(surface);
386         surface = NULL;
387
388         if (bufmgr && LIST_IS_EMPTY(&bufmgr->surf_list)) {
389                 LIST_DELINIT(&bufmgr->surf_list);
390
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);
394                         }
395                 }
396
397                 _deinit_surface_bufmgr();
398         }
399 }
400
401 /* LCOV_EXCL_START */
402 static int
403 _tbm_surface_check_file_is_symbolic_link(const char* path)
404 {
405         struct stat sb;
406
407         if (!path)
408                 return 0;
409
410         if (stat(path, &sb) != 0)
411                 return 0;
412
413         if (S_ISLNK(sb.st_mode))
414                 return 1;
415
416         return 0;
417 }
418 /* LCOV_EXCL_STOP */
419
420 static int
421 _tbm_surface_internal_get_num_planes(tbm_format format)
422 {
423         int num_planes = 0;
424
425         switch (format) {
426         case TBM_FORMAT_C8:
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:
470                 num_planes = 1;
471                 break;
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:
477                 num_planes = 2;
478                 break;
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:
489                 num_planes = 3;
490                 break;
491
492         default:
493                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
494                 break;
495         }
496
497         return num_planes;
498 }
499
500 static int
501 _tbm_surface_internal_get_bpp(tbm_format format)
502 {
503
504         int bpp = 0;
505
506         switch (format) {
507         case TBM_FORMAT_C8:
508         case TBM_FORMAT_RGB332:
509         case TBM_FORMAT_BGR233:
510                 bpp = 8;
511                 break;
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:
530                 bpp = 16;
531                 break;
532         case TBM_FORMAT_RGB888:
533         case TBM_FORMAT_BGR888:
534                 bpp = 24;
535                 break;
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:
557                 bpp = 32;
558                 break;
559         case TBM_FORMAT_NV12:
560         case TBM_FORMAT_NV12MT:
561         case TBM_FORMAT_NV21:
562                 bpp = 12;
563                 break;
564         case TBM_FORMAT_NV16:
565         case TBM_FORMAT_NV61:
566                 bpp = 16;
567                 break;
568         case TBM_FORMAT_YUV410:
569         case TBM_FORMAT_YVU410:
570                 bpp = 9;
571                 break;
572         case TBM_FORMAT_YUV411:
573         case TBM_FORMAT_YVU411:
574         case TBM_FORMAT_YUV420:
575         case TBM_FORMAT_YVU420:
576                 bpp = 12;
577                 break;
578         case TBM_FORMAT_YUV422:
579         case TBM_FORMAT_YVU422:
580                 bpp = 16;
581                 break;
582         case TBM_FORMAT_YUV444:
583         case TBM_FORMAT_YVU444:
584                 bpp = 24;
585                 break;
586         default:
587                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
588                 break;
589         }
590
591         return bpp;
592 }
593
594 int
595 tbm_surface_internal_is_valid(tbm_surface_h surface)
596 {
597         int ret = 0;
598
599         _tbm_surface_mutex_lock();
600         _tbm_set_last_result(TBM_ERROR_NONE);
601
602         /* Return silently if surface is null. */
603         if (!surface) {
604                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
605                 _tbm_surface_mutex_unlock();
606                 return 0;
607         }
608
609         ret = _tbm_surface_internal_is_valid(surface);
610
611         _tbm_surface_mutex_unlock();
612
613         return ret;
614 }
615
616 int
617 tbm_surface_internal_query_supported_formats(uint32_t **formats,
618                 uint32_t *num)
619 {
620         struct _tbm_bufmgr *bufmgr;
621         int ret = 0;
622         bool bufmgr_initialized = false;
623         tbm_error_e error;
624
625         _tbm_surface_mutex_lock();
626         _tbm_set_last_result(TBM_ERROR_NONE);
627
628         TBM_SURFACE_RETURN_VAL_IF_FAIL(formats, 0);
629         TBM_SURFACE_RETURN_VAL_IF_FAIL(num, 0);
630
631         if (!g_surface_bufmgr) {
632                 _init_surface_bufmgr();
633                 if (!g_surface_bufmgr) {
634                         TBM_ERR("fail bufmgr initialization\n");
635                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
636                         goto fail;
637                 }
638                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
639                 bufmgr_initialized = true;
640         }
641
642         bufmgr = g_surface_bufmgr;
643
644         if (bufmgr->use_hal_tbm) {
645                 error = (tbm_error_e)hal_tbm_bufmgr_get_supported_formats(bufmgr->hal_bufmgr, formats, num);
646                 /* LCOV_EXCL_START */
647                 if (error == TBM_ERROR_NOT_SUPPORTED) {
648                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
649                         goto fail;
650                 } else if (error != TBM_ERROR_NONE) {
651                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
652                         goto fail;
653                 }
654                 /* LCOV_EXCL_STOP */
655                 ret = 1;
656         } else if (bufmgr->backend_module_data) {
657                 if (!bufmgr->bufmgr_func->bufmgr_get_supported_formats) {
658                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
659                         goto fail;
660                 }
661
662                 error = bufmgr->bufmgr_func->bufmgr_get_supported_formats(bufmgr->bufmgr_data, formats, num);
663                 if (error != TBM_ERROR_NONE) {
664                         /* LCOV_EXCL_START */
665                         TBM_ERR("Fail to surface_supported_format. error(%d)\n", error);
666                         goto fail;
667                         /* LCOV_EXCL_START */
668                 }
669                 ret = 1;
670         } else {
671                 if (!bufmgr->backend->surface_supported_format) {
672                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
673                         goto fail;
674                 }
675
676                 ret = bufmgr->backend->surface_supported_format(formats, num);
677                 if (!ret)  {
678                         /* LCOV_EXCL_START */
679                         TBM_ERR("Fail to surface_supported_format.\n");
680                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
681                         goto fail;
682                         /* LCOV_EXCL_START */
683                 }
684         }
685
686         TBM_TRACE_SURFACE_INTERNAL("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
687
688         if (bufmgr_initialized) {
689                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
690                 _deinit_surface_bufmgr();
691         }
692
693         _tbm_surface_mutex_unlock();
694
695         return ret;
696
697 /* LCOV_EXCL_START */
698 fail:
699         if (bufmgr_initialized) {
700                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
701                 _deinit_surface_bufmgr();
702         }
703         _tbm_surface_mutex_unlock();
704
705         TBM_ERR("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
706
707         return 0;
708 /* LCOV_EXCL_STOP */
709 }
710
711 int
712 tbm_surface_internal_get_num_planes(tbm_format format)
713 {
714         int num_planes = 0;
715
716         _tbm_surface_mutex_lock();
717         _tbm_set_last_result(TBM_ERROR_NONE);
718
719         num_planes = _tbm_surface_internal_get_num_planes(format);
720         if (!num_planes) {
721                 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
722                 _tbm_surface_mutex_unlock();
723                 return 0;
724         }
725
726         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
727
728         _tbm_surface_mutex_unlock();
729
730         return num_planes;
731 }
732
733 int
734 tbm_surface_internal_get_bpp(tbm_format format)
735 {
736         int bpp = 0;
737
738         _tbm_surface_mutex_lock();
739         _tbm_set_last_result(TBM_ERROR_NONE);
740
741         bpp = _tbm_surface_internal_get_bpp(format);
742         if (!bpp) {
743                 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
744                 _tbm_surface_mutex_unlock();
745                 return 0;
746         }
747
748         _tbm_surface_mutex_unlock();
749
750         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
751
752         return bpp;
753 }
754
755 tbm_surface_h
756 tbm_surface_internal_create_with_flags(int width, int height,
757                                        int format, int flags)
758 {
759         struct _tbm_bufmgr *bufmgr;
760         struct _tbm_surface *surf = NULL;
761         uint32_t size = 0;
762         uint32_t offset = 0;
763         uint32_t stride = 0;
764         uint32_t bo_size = 0;
765         int bo_idx;
766         int i, j;
767         bool bufmgr_initialized = false;
768         tbm_error_e error;
769
770         _tbm_surface_mutex_lock();
771         _tbm_set_last_result(TBM_ERROR_NONE);
772
773         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, NULL);
774         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, NULL);
775
776         if (!g_surface_bufmgr) {
777                 _init_surface_bufmgr();
778                 if (!g_surface_bufmgr) {
779                         TBM_ERR("fail bufmgr initialization\n");
780                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
781                         goto check_valid_fail;
782                 }
783                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
784                 bufmgr_initialized = true;
785         }
786
787         bufmgr = g_surface_bufmgr;
788         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
789                 TBM_ERR("The bufmgr is invalid\n");
790                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
791                 goto check_valid_fail;
792         }
793
794         surf = calloc(1, sizeof(struct _tbm_surface));
795         if (!surf) {
796                 /* LCOV_EXCL_START */
797                 TBM_ERR("fail to alloc surf\n");
798                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
799                 goto alloc_surf_fail;
800                 /* LCOV_EXCL_STOP */
801         }
802
803         surf->magic = TBM_SURFACE_MAGIC;
804         surf->bufmgr = bufmgr;
805         surf->info.width = width;
806         surf->info.height = height;
807         surf->info.format = format;
808         surf->info.bpp = _tbm_surface_internal_get_bpp(format);
809         if (!surf->info.bpp) {
810                 TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
811                 goto bpp_fail;
812         }
813         surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
814         if (!surf->info.num_planes) {
815                 TBM_ERR("fail to get num_planes. error(%s)\n", tbm_error_str(tbm_get_last_error()));
816                 goto num_planes_fail;
817         }
818         surf->refcnt = 1;
819
820         /* get size, stride and offset bo_idx */
821         for (i = 0; i < surf->info.num_planes; i++) {
822                 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
823                                                 &offset, &stride, &bo_idx)) {
824                         TBM_ERR("fail to query plane data\n");
825                         goto query_plane_data_fail;
826                 }
827
828                 surf->info.planes[i].size = size;
829                 surf->info.planes[i].offset = offset;
830                 surf->info.planes[i].stride = stride;
831                 surf->planes_bo_idx[i] = bo_idx;
832         }
833
834         surf->num_bos = 1;
835
836         for (i = 0; i < surf->info.num_planes; i++) {
837                 surf->info.size += surf->info.planes[i].size;
838
839                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
840                         surf->num_bos = surf->planes_bo_idx[i] + 1;
841         }
842
843         surf->flags = flags;
844
845         for (i = 0; i < surf->num_bos; i++) {
846                 bo_size = 0;
847                 for (j = 0; j < surf->info.num_planes; j++) {
848                         if (surf->planes_bo_idx[j] == i)
849                                 bo_size += surf->info.planes[j].size;
850                 }
851
852                 if (bufmgr->use_hal_tbm) {
853                         surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, flags, &error);
854                         if (error == TBM_ERROR_NOT_SUPPORTED) {
855                                 if (flags & TBM_BO_TILED) {
856                                         surf->bos[i] = tbm_bo_alloc_with_tiled_format(bufmgr, width, height, surf->info.bpp/8, format, flags, i, &error);
857                                         if (error == TBM_ERROR_NOT_SUPPORTED) {
858                                                 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
859                                         } else if (error != TBM_ERROR_NONE) {
860                                                 TBM_ERR("fail to alloc bo idx:%d\n", i);
861                                                 goto alloc_bo_fail;
862                                         }
863                                 } else {
864                                         surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
865                                 }
866
867                                 if (!surf->bos[i]) {
868                                         TBM_ERR("fail to alloc bo idx:%d\n", i);
869                                         goto alloc_bo_fail;
870                                 }
871                         } else if (error != TBM_ERROR_NONE) {
872                                 TBM_ERR("fail to alloc bo idx:%d\n", i);
873                                 goto alloc_bo_fail;
874                         }
875                 } else if (bufmgr->backend_module_data) {
876                         if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format) {
877                                 /* LCOV_EXCL_START */
878                                 surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, flags, &error);
879                                 if (!surf->bos[i]) {
880                                         TBM_ERR("fail to tbm_bo_alloc_with_format idx:%d\n", i);
881                                         goto alloc_bo_fail;
882                                 }
883                                 /* LCOV_EXCL_STOP */
884                         } else if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format && (flags & TBM_BO_TILED)) {
885                                 /* LCOV_EXCL_START */
886                                 surf->bos[i] = tbm_bo_alloc_with_tiled_format(bufmgr, width, height, surf->info.bpp/8, format, flags, i, &error);
887                                 if (!surf->bos[i]) {
888                                         TBM_ERR("fail to tbm_bo_alloc_with_tiled_format idx:%d\n", i);
889                                         goto alloc_bo_fail;
890                                 }
891                                 /* LCOV_EXCL_STOP */
892                         } else {
893                                 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
894                                 if (!surf->bos[i]) {
895                                         TBM_ERR("fail to alloc bo idx:%d\n", i);
896                                         goto alloc_bo_fail;
897                                 }
898                         }
899                 } else {
900                         if (bufmgr->backend->surface_bo_alloc) {
901                                 /* LCOV_EXCL_START */
902                                 surf->bos[i] = tbm_bo_alloc_with_surface(bufmgr, width, height, format, flags, i);
903                                 if (!surf->bos[i]) {
904                                         TBM_ERR("fail to tbm_bo_alloc_with_surface idx:%d\n", i);
905                                         goto alloc_bo_fail;
906                                 /* LCOV_EXCL_STOP */
907                                 }
908                         } else {
909                                 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
910                                 if (!surf->bos[i]) {
911                                         TBM_ERR("fail to alloc bo idx:%d\n", i);
912                                         goto alloc_bo_fail;
913                                 }
914                         }
915                 }
916
917                 _tbm_bo_set_surface(surf->bos[i], surf);
918         }
919
920         TBM_TRACE_SURFACE_INTERNAL("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
921                         _tbm_surface_internal_format_to_str(format), flags, surf);
922
923         LIST_INITHEAD(&surf->user_data_list);
924         LIST_INITHEAD(&surf->debug_data_list);
925         LIST_INITHEAD(&surf->destroy_funcs);
926
927         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
928
929         _tbm_surface_mutex_unlock();
930
931         return surf;
932
933 /* LCOV_EXCL_START */
934 alloc_bo_fail:
935         for (j = 0; j < i; j++) {
936                 if (surf->bos[j])
937                         tbm_bo_unref(surf->bos[j]);
938         }
939 query_plane_data_fail:
940 bpp_fail:
941 num_planes_fail:
942         free(surf);
943 alloc_surf_fail:
944 check_valid_fail:
945         if (bufmgr_initialized && bufmgr) {
946                 LIST_DELINIT(&bufmgr->surf_list);
947                 _deinit_surface_bufmgr();
948         }
949         _tbm_surface_mutex_unlock();
950
951         TBM_ERR("error: width(%d) height(%d) format(%s) flags(%d)\n",
952                         width, height,
953                         _tbm_surface_internal_format_to_str(format), flags);
954 /* LCOV_EXCL_STOP */
955
956         return NULL;
957 }
958
959 tbm_surface_h
960 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
961                                      tbm_bo *bos, int num)
962 {
963         struct _tbm_bufmgr *bufmgr;
964         struct _tbm_surface *surf = NULL;
965         int i;
966         bool bufmgr_initialized = false;
967
968         _tbm_surface_mutex_lock();
969         _tbm_set_last_result(TBM_ERROR_NONE);
970
971         TBM_SURFACE_RETURN_VAL_IF_FAIL(bos, NULL);
972         TBM_SURFACE_RETURN_VAL_IF_FAIL(info, NULL);
973         TBM_SURFACE_RETURN_VAL_IF_FAIL(info->num_planes > 0, NULL);
974         TBM_SURFACE_RETURN_VAL_IF_FAIL(num > 0, NULL);
975         TBM_SURFACE_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
976
977         if (!g_surface_bufmgr) {
978                 _init_surface_bufmgr();
979                 if (!g_surface_bufmgr) {
980                         TBM_ERR("fail bufmgr initialization\n");
981                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
982                         goto check_valid_fail;
983                 }
984                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
985                 bufmgr_initialized = true;
986         }
987
988         bufmgr = g_surface_bufmgr;
989         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
990                 TBM_ERR("fail to validate the Bufmgr.\n");
991                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
992                 goto check_valid_fail;
993         }
994
995         surf = calloc(1, sizeof(struct _tbm_surface));
996         if (!surf) {
997                 /* LCOV_EXCL_START */
998                 TBM_ERR("fail to allocate struct _tbm_surface.\n");
999                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1000                 goto alloc_surf_fail;
1001                 /* LCOV_EXCL_STOP */
1002         }
1003
1004         surf->magic = TBM_SURFACE_MAGIC;
1005         surf->bufmgr = bufmgr;
1006         surf->info.width = info->width;
1007         surf->info.height = info->height;
1008         surf->info.format = info->format;
1009         if (info->bpp > 0)
1010                 surf->info.bpp = info->bpp;
1011         else {
1012                 surf->info.bpp = _tbm_surface_internal_get_bpp(info->format);
1013                 if (!surf->info.bpp) {
1014                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1015                         goto bpp_fail;
1016                 }
1017         }
1018         surf->info.num_planes = info->num_planes;
1019         surf->refcnt = 1;
1020
1021         /* get size, stride and offset */
1022         for (i = 0; i < info->num_planes; i++) {
1023                 surf->info.planes[i].offset = info->planes[i].offset;
1024                 surf->info.planes[i].stride = info->planes[i].stride;
1025
1026                 if (info->planes[i].size > 0)
1027                         surf->info.planes[i].size = info->planes[i].size;
1028                 else {
1029                         uint32_t size = 0, offset = 0, stride = 0;
1030                         int32_t bo_idx = 0;
1031
1032                         if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
1033                                 TBM_ERR("fail to get plane_data. error(%s)\n", tbm_error_str(tbm_get_last_error()));
1034                                 goto plane_data_fail;
1035                         }
1036                         surf->info.planes[i].size = size;
1037                 }
1038
1039                 if (num == 1)
1040                         surf->planes_bo_idx[i] = 0;
1041                 else
1042                         surf->planes_bo_idx[i] = i;
1043         }
1044
1045         if (info->size > 0) {
1046                 surf->info.size = info->size;
1047         } else {
1048                 surf->info.size = 0;
1049                 for (i = 0; i < info->num_planes; i++)
1050                         surf->info.size += surf->info.planes[i].size;
1051         }
1052
1053         surf->flags = TBM_BO_DEFAULT;
1054
1055         /* create only one bo */
1056         surf->num_bos = num;
1057         for (i = 0; i < num; i++) {
1058                 if (bos[i] == NULL) {
1059                         TBM_ERR("bos[%d] is null.\n", i);
1060                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
1061                         goto check_bo_fail;
1062                 }
1063
1064                 surf->bos[i] = tbm_bo_ref(bos[i]);
1065                 _tbm_bo_set_surface(bos[i], surf);
1066         }
1067
1068         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
1069                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
1070
1071         LIST_INITHEAD(&surf->user_data_list);
1072         LIST_INITHEAD(&surf->debug_data_list);
1073         LIST_INITHEAD(&surf->destroy_funcs);
1074
1075         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
1076
1077         _tbm_surface_mutex_unlock();
1078
1079         return surf;
1080
1081 /* LCOV_EXCL_START */
1082 check_bo_fail:
1083 plane_data_fail:
1084 bpp_fail:
1085         for (i = 0; i < num; i++) {
1086                 if (surf->bos[i])
1087                         tbm_bo_unref(surf->bos[i]);
1088         }
1089         free(surf);
1090 alloc_surf_fail:
1091 check_valid_fail:
1092         if (bufmgr_initialized && bufmgr) {
1093                 LIST_DELINIT(&bufmgr->surf_list);
1094                 _deinit_surface_bufmgr();
1095         }
1096         _tbm_surface_mutex_unlock();
1097
1098         TBM_ERR("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
1099                         info->width, info->height,
1100                         _tbm_surface_internal_format_to_str(info->format), num);
1101 /* LCOV_EXCL_STOP */
1102
1103         return NULL;
1104 }
1105
1106 void
1107 tbm_surface_internal_destroy(tbm_surface_h surface)
1108 {
1109         _tbm_surface_mutex_lock();
1110         _tbm_set_last_result(TBM_ERROR_NONE);
1111
1112         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1113
1114         surface->refcnt--;
1115
1116         if (surface->refcnt > 0) {
1117                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1118                 _tbm_surface_mutex_unlock();
1119                 return;
1120         }
1121
1122         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1123
1124         if (surface->refcnt == 0)
1125                 _tbm_surface_internal_destroy(surface);
1126
1127         _tbm_surface_mutex_unlock();
1128 }
1129
1130 void
1131 tbm_surface_internal_ref(tbm_surface_h surface)
1132 {
1133         _tbm_surface_mutex_lock();
1134         _tbm_set_last_result(TBM_ERROR_NONE);
1135
1136         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1137
1138         surface->refcnt++;
1139
1140         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1141
1142         _tbm_surface_mutex_unlock();
1143 }
1144
1145 void
1146 tbm_surface_internal_unref(tbm_surface_h surface)
1147 {
1148         _tbm_surface_mutex_lock();
1149         _tbm_set_last_result(TBM_ERROR_NONE);
1150
1151         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1152
1153         surface->refcnt--;
1154
1155         if (surface->refcnt > 0) {
1156                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1157                 _tbm_surface_mutex_unlock();
1158                 return;
1159         }
1160
1161         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1162
1163         if (surface->refcnt == 0)
1164                 _tbm_surface_internal_destroy(surface);
1165
1166         _tbm_surface_mutex_unlock();
1167 }
1168
1169 int
1170 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
1171 {
1172         struct _tbm_surface *surf;
1173         int num;
1174
1175         _tbm_surface_mutex_lock();
1176         _tbm_set_last_result(TBM_ERROR_NONE);
1177
1178         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1179
1180         surf = (struct _tbm_surface *)surface;
1181         num = surf->num_bos;
1182
1183         if (!num)
1184                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1185
1186         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) num_bos(%d)\n", surface, num);
1187
1188         _tbm_surface_mutex_unlock();
1189
1190         return num;
1191 }
1192
1193 tbm_bo
1194 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
1195 {
1196         struct _tbm_surface *surf;
1197         tbm_bo bo;
1198
1199         _tbm_surface_mutex_lock();
1200         _tbm_set_last_result(TBM_ERROR_NONE);
1201
1202         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
1203         TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
1204
1205         surf = (struct _tbm_surface *)surface;
1206         bo = surf->bos[bo_idx];
1207
1208         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
1209
1210         _tbm_surface_mutex_unlock();
1211
1212         return bo;
1213 }
1214
1215 unsigned int
1216 tbm_surface_internal_get_size(tbm_surface_h surface)
1217 {
1218         struct _tbm_surface *surf;
1219         unsigned int size;
1220
1221         _tbm_surface_mutex_lock();
1222         _tbm_set_last_result(TBM_ERROR_NONE);
1223
1224         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1225
1226         surf = (struct _tbm_surface *)surface;
1227         size = surf->info.size;
1228
1229         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) size(%u)\n", surface, size);
1230
1231         _tbm_surface_mutex_unlock();
1232
1233         return size;
1234 }
1235
1236 int
1237 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1238                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
1239 {
1240         struct _tbm_surface *surf;
1241
1242         _tbm_surface_mutex_lock();
1243         _tbm_set_last_result(TBM_ERROR_NONE);
1244
1245         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1246         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1247
1248         surf = (struct _tbm_surface *)surface;
1249
1250         if (plane_idx >= surf->info.num_planes) {
1251                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1252                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1253                 _tbm_surface_mutex_unlock();
1254                 return 0;
1255         }
1256
1257         if (size)
1258                 *size = surf->info.planes[plane_idx].size;
1259
1260         if (offset)
1261                 *offset = surf->info.planes[plane_idx].offset;
1262
1263         if (pitch)
1264                 *pitch = surf->info.planes[plane_idx].stride;
1265
1266         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1267                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1268                                 surf->info.planes[plane_idx].stride);
1269
1270         _tbm_surface_mutex_unlock();
1271
1272         return 1;
1273 }
1274
1275 int
1276 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1277                               tbm_surface_info_s *info, int map)
1278 {
1279         struct _tbm_surface *surf;
1280         tbm_bo_handle bo_handles[4];
1281         int num_bos = 0;
1282         tbm_bo bos[4];
1283         int planes_bo_idx[TBM_SURF_PLANE_MAX];
1284         int i, j;
1285
1286         _tbm_surface_mutex_lock();
1287         _tbm_set_last_result(TBM_ERROR_NONE);
1288
1289         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1290
1291         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1292
1293         surf = (struct _tbm_surface *)surface;
1294
1295         memset(info, 0x00, sizeof(tbm_surface_info_s));
1296         info->width = surf->info.width;
1297         info->height = surf->info.height;
1298         info->format = surf->info.format;
1299         info->bpp = surf->info.bpp;
1300         info->size = surf->info.size;
1301         info->num_planes = surf->info.num_planes;
1302
1303         for (i = 0; i < surf->info.num_planes; i++) {
1304                 info->planes[i].size = surf->info.planes[i].size;
1305                 info->planes[i].offset = surf->info.planes[i].offset;
1306                 info->planes[i].stride = surf->info.planes[i].stride;
1307                 planes_bo_idx[i] = surf->planes_bo_idx[i];
1308         }
1309
1310         for (i = 0; i < surf->num_bos; i++)
1311                 bos[i] = surf->bos[i];
1312
1313         num_bos = surf->num_bos;
1314
1315         if (map == 1) {
1316                 _tbm_surface_mutex_unlock();
1317                 for (i = 0; i < num_bos; i++) {
1318                         bo_handles[i] = tbm_bo_map(bos[i], TBM_DEVICE_CPU, opt);
1319                         if (bo_handles[i].ptr == NULL) {
1320                                 for (j = 0; j < i; j++)
1321                                         tbm_bo_unmap(bos[j]);
1322
1323                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1324                                 return 0;
1325                         }
1326                 }
1327                 _tbm_surface_mutex_lock();
1328         } else {
1329                 for (i = 0; i < num_bos; i++) {
1330                         bo_handles[i] = tbm_bo_get_handle(bos[i], TBM_DEVICE_CPU);
1331                         if (bo_handles[i].ptr == NULL) {
1332                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1333                                 _tbm_surface_mutex_unlock();
1334                                 return 0;
1335                         }
1336                 }
1337         }
1338
1339         for (i = 0; i < info->num_planes; i++) {
1340                 if (bo_handles[planes_bo_idx[i]].ptr)
1341                         info->planes[i].ptr = bo_handles[planes_bo_idx[i]].ptr + info->planes[i].offset;
1342         }
1343
1344         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1345
1346         _tbm_surface_mutex_unlock();
1347
1348         return 1;
1349 }
1350
1351 void
1352 tbm_surface_internal_unmap(tbm_surface_h surface)
1353 {
1354         struct _tbm_surface *surf;
1355         int i;
1356
1357         _tbm_surface_mutex_lock();
1358         _tbm_set_last_result(TBM_ERROR_NONE);
1359
1360         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1361
1362         surf = (struct _tbm_surface *)surface;
1363
1364         for (i = 0; i < surf->num_bos; i++)
1365                 tbm_bo_unmap(surf->bos[i]);
1366
1367         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)\n", surface);
1368
1369         _tbm_surface_mutex_unlock();
1370 }
1371
1372 unsigned int
1373 tbm_surface_internal_get_width(tbm_surface_h surface)
1374 {
1375         struct _tbm_surface *surf;
1376         unsigned int width;
1377
1378         _tbm_surface_mutex_lock();
1379         _tbm_set_last_result(TBM_ERROR_NONE);
1380
1381         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1382
1383         surf = (struct _tbm_surface *)surface;
1384         width = surf->info.width;
1385
1386         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u)\n", surface, width);
1387
1388         _tbm_surface_mutex_unlock();
1389
1390         return width;
1391 }
1392
1393 unsigned int
1394 tbm_surface_internal_get_height(tbm_surface_h surface)
1395 {
1396         struct _tbm_surface *surf;
1397         unsigned int height;
1398
1399         _tbm_surface_mutex_lock();
1400         _tbm_set_last_result(TBM_ERROR_NONE);
1401
1402         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1403
1404         surf = (struct _tbm_surface *)surface;
1405         height = surf->info.height;
1406
1407         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) height(%u)\n", surface, height);
1408
1409         _tbm_surface_mutex_unlock();
1410
1411         return height;
1412
1413 }
1414
1415 tbm_format
1416 tbm_surface_internal_get_format(tbm_surface_h surface)
1417 {
1418         struct _tbm_surface *surf;
1419         tbm_format format;
1420
1421         _tbm_surface_mutex_lock();
1422         _tbm_set_last_result(TBM_ERROR_NONE);
1423
1424         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1425
1426         surf = (struct _tbm_surface *)surface;
1427         format = surf->info.format;
1428
1429         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1430
1431         _tbm_surface_mutex_unlock();
1432
1433         return format;
1434 }
1435
1436 int
1437 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1438 {
1439         struct _tbm_surface *surf;
1440         int bo_idx;
1441
1442         _tbm_surface_mutex_lock();
1443         _tbm_set_last_result(TBM_ERROR_NONE);
1444
1445         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1446         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1447
1448         surf = (struct _tbm_surface *)surface;
1449         bo_idx = surf->planes_bo_idx[plane_idx];
1450
1451         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1452
1453         _tbm_surface_mutex_unlock();
1454
1455         return bo_idx;
1456 }
1457
1458 int
1459 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1460                                    tbm_data_free data_free_func)
1461 {
1462         tbm_user_data *data;
1463
1464         _tbm_surface_mutex_lock();
1465         _tbm_set_last_result(TBM_ERROR_NONE);
1466
1467         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1468
1469         /* check if the data according to the key exist if so, return false. */
1470         data = user_data_lookup(&surface->user_data_list, key);
1471         if (data) {
1472                 TBM_TRACE_SURFACE_INTERNAL("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1473                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1474                 _tbm_surface_mutex_unlock();
1475                 return 0;
1476         }
1477
1478         data = user_data_create(key, data_free_func);
1479         if (!data) {
1480                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1481                 _tbm_surface_mutex_unlock();
1482                 return 0;
1483         }
1484
1485         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1486
1487         LIST_ADD(&data->item_link, &surface->user_data_list);
1488
1489         _tbm_surface_mutex_unlock();
1490
1491         return 1;
1492 }
1493
1494 int
1495 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1496                                    void *data)
1497 {
1498         tbm_user_data *old_data;
1499
1500         _tbm_surface_mutex_lock();
1501         _tbm_set_last_result(TBM_ERROR_NONE);
1502
1503         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1504
1505         old_data = user_data_lookup(&surface->user_data_list, key);
1506         if (!old_data) {
1507                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1508                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1509                 _tbm_surface_mutex_unlock();
1510                 return 0;
1511         }
1512
1513         if (old_data->data && old_data->free_func)
1514                 old_data->free_func(old_data->data);
1515
1516         old_data->data = data;
1517
1518         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1519
1520         _tbm_surface_mutex_unlock();
1521
1522         return 1;
1523 }
1524
1525 int
1526 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1527                                    void **data)
1528 {
1529         tbm_user_data *old_data;
1530
1531         _tbm_surface_mutex_lock();
1532         _tbm_set_last_result(TBM_ERROR_NONE);
1533
1534         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1535
1536         if (!data) {
1537                 TBM_ERR("error: tbm_surface(%p) key(%lu)\n", surface, key);
1538                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1539                 _tbm_surface_mutex_unlock();
1540                 return 0;
1541         }
1542         *data = NULL;
1543
1544         old_data = user_data_lookup(&surface->user_data_list, key);
1545         if (!old_data) {
1546                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1547                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1548                 _tbm_surface_mutex_unlock();
1549                 return 0;
1550         }
1551
1552         *data = old_data->data;
1553
1554         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1555
1556         _tbm_surface_mutex_unlock();
1557
1558         return 1;
1559 }
1560
1561 int
1562 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1563                                       unsigned long key)
1564 {
1565         tbm_user_data *old_data = (void *)0;
1566
1567         _tbm_surface_mutex_lock();
1568         _tbm_set_last_result(TBM_ERROR_NONE);
1569
1570         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1571
1572         old_data = user_data_lookup(&surface->user_data_list, key);
1573         if (!old_data) {
1574                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1575                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1576                 _tbm_surface_mutex_unlock();
1577                 return 0;
1578         }
1579
1580         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1581
1582         user_data_delete(old_data);
1583
1584         _tbm_surface_mutex_unlock();
1585
1586         return 1;
1587 }
1588
1589 /* LCOV_EXCL_START */
1590 unsigned int
1591 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1592 {
1593         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1594
1595         return surface->debug_pid;
1596 }
1597
1598 void
1599 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1600 {
1601         _tbm_surface_mutex_lock();
1602         _tbm_set_last_result(TBM_ERROR_NONE);
1603
1604         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1605
1606         surface->debug_pid = pid;
1607
1608         _tbm_surface_mutex_unlock();
1609 }
1610
1611 static tbm_surface_debug_data *
1612 _tbm_surface_internal_debug_data_create(char *key, char *value)
1613 {
1614         tbm_surface_debug_data *debug_data = NULL;
1615
1616         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1617         if (!debug_data) {
1618                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1619                 TBM_ERR("fail to allocate the debug_data.");
1620                 return NULL;
1621         }
1622
1623         if (key) debug_data->key = strdup(key);
1624         if (value) debug_data->value = strdup(value);
1625
1626         return debug_data;
1627 }
1628
1629 static void
1630 _tbm_surface_internal_debug_data_value_update(tbm_surface_debug_data *debug_data, char *value)
1631 {
1632         if (!debug_data->value && !value)
1633                 return;
1634
1635         if (debug_data->value && value && !strncmp(debug_data->value, value, strlen(debug_data->value)))
1636                 return;
1637
1638         if (debug_data->value)
1639                 free(debug_data->value);
1640
1641         if (value)
1642                 debug_data->value = strdup(value);
1643         else
1644                 debug_data->value = NULL;
1645 }
1646
1647 static tbm_surface_debug_data *
1648 _tbm_surface_internal_debug_data_find(struct list_head *list, char *key)
1649 {
1650         tbm_surface_debug_data *debug_data = NULL;
1651
1652         if (LIST_IS_EMPTY(list))
1653                 return NULL;
1654
1655         LIST_FOR_EACH_ENTRY(debug_data, list, item_link) {
1656                 if (!strncmp(debug_data->key, key, strlen(debug_data->key)))
1657                         return debug_data;
1658         }
1659
1660         return NULL;
1661 }
1662
1663 int
1664 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1665 {
1666         tbm_surface_debug_data *debug_data = NULL;
1667         tbm_bufmgr bufmgr = NULL;
1668
1669         _tbm_surface_mutex_lock();
1670         _tbm_set_last_result(TBM_ERROR_NONE);
1671
1672         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1673         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1674
1675         bufmgr = surface->bufmgr;
1676
1677         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1678
1679         debug_data = _tbm_surface_internal_debug_data_find(&surface->debug_data_list, key);
1680         if (debug_data) {
1681                 _tbm_surface_internal_debug_data_value_update(debug_data, value);
1682         } else {
1683                 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1684                 if (!debug_data) {
1685                         TBM_ERR("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1686                         _tbm_surface_mutex_unlock();
1687                         return 0;
1688                 }
1689
1690                 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1691         }
1692
1693         /* add new debug key to list */
1694         debug_data = _tbm_surface_internal_debug_data_find(&bufmgr->debug_key_list, key);
1695         if (!debug_data) {
1696                 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1697                 if (debug_data)
1698                         LIST_ADDTAIL(&debug_data->item_link, &bufmgr->debug_key_list);
1699         }
1700
1701         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1702
1703         _tbm_surface_mutex_unlock();
1704
1705         return 1;
1706 }
1707
1708 char *
1709 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1710 {
1711         tbm_surface_debug_data *old_data = NULL;
1712
1713         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1714
1715         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1716                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1717                         if (!strcmp(old_data->key, key))
1718                                 return old_data->value;
1719                 }
1720         }
1721
1722         return NULL;
1723 }
1724
1725 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1726 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1727
1728 struct _tbm_surface_dump_buf_info {
1729         int index;
1730         tbm_bo bo;
1731         int size;
1732         int dirty;
1733         int dirty_shm;
1734         int shm_stride;
1735         int shm_h;
1736         char name[1024];
1737
1738         tbm_surface_info_s info;
1739
1740         struct list_head link;
1741 };
1742
1743 struct _tbm_surface_dump_info {
1744         char *path;  // copy???
1745         int dump_max;
1746         int count;
1747         struct list_head *link;
1748         struct list_head surface_list; /* link of surface */
1749 };
1750
1751 static tbm_surface_dump_info *g_dump_info = NULL;
1752 static const char *dump_postfix[2] = {"png", "yuv"};
1753 static double scale_factor;
1754
1755 static void
1756 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1757                                 void *data2, int size2, void *data3, int size3)
1758 {
1759         FILE *fp;
1760         unsigned int *blocks;
1761
1762         if (_tbm_surface_check_file_is_symbolic_link(file))
1763                 TBM_ERR("%s is symbolic link\n", file);
1764
1765         fp = fopen(file, "w+");
1766         TBM_RETURN_IF_FAIL(fp != NULL);
1767
1768         blocks = (unsigned int *)data1;
1769         fwrite(blocks, 1, size1, fp);
1770
1771         if (size2 > 0) {
1772                 blocks = (unsigned int *)data2;
1773                 fwrite(blocks, 1, size2, fp);
1774         }
1775
1776         if (size3 > 0) {
1777                 blocks = (unsigned int *)data3;
1778                 fwrite(blocks, 1, size3, fp);
1779         }
1780
1781         fclose(fp);
1782 }
1783
1784 static void
1785 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height, int stride, int format)
1786 {
1787         unsigned int *blocks = (unsigned int *)data;
1788         FILE *fp;
1789         int pixel_size;
1790         png_bytep *row_pointers;
1791         int depth = 8, y;
1792
1793         if (_tbm_surface_check_file_is_symbolic_link(file))
1794                 TBM_ERR("%s is symbolic link\n", file);
1795
1796         fp = fopen(file, "wb");
1797         TBM_RETURN_IF_FAIL(fp != NULL);
1798
1799         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1800                                                         NULL, NULL, NULL);
1801         if (!pPngStruct) {
1802                 TBM_ERR("fail to create a png write structure.\n");
1803                 fclose(fp);
1804                 return;
1805         }
1806
1807         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1808         if (!pPngInfo) {
1809                 TBM_ERR("fail to create a png info structure.\n");
1810                 png_destroy_write_struct(&pPngStruct, NULL);
1811                 fclose(fp);
1812                 return;
1813         }
1814
1815         if (setjmp(png_jmpbuf(pPngStruct))) {
1816                 /* if png has problem of writing the file, we get here */
1817                 TBM_ERR("fail to write png file.\n");
1818                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1819                 fclose(fp);
1820                 return;
1821         }
1822
1823         png_init_io(pPngStruct, fp);
1824         if (format == TBM_FORMAT_XRGB8888) {
1825                 pixel_size = 3;
1826                 png_set_IHDR(pPngStruct,
1827                                 pPngInfo,
1828                                 width,
1829                                 height,
1830                                 depth,
1831                                 PNG_COLOR_TYPE_RGB,
1832                                 PNG_INTERLACE_NONE,
1833                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1834         } else {
1835                 pixel_size = 4;
1836                 png_set_IHDR(pPngStruct,
1837                                 pPngInfo,
1838                                 width,
1839                                 height,
1840                                 depth,
1841                                 PNG_COLOR_TYPE_RGBA,
1842                                 PNG_INTERLACE_NONE,
1843                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1844         }
1845
1846         png_set_bgr(pPngStruct);
1847         png_write_info(pPngStruct, pPngInfo);
1848
1849         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1850         if (!row_pointers) {
1851                 TBM_ERR("fail to allocate the png row_pointers.\n");
1852                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1853                 fclose(fp);
1854                 return;
1855         }
1856
1857         for (y = 0; y < height; ++y) {
1858                 png_bytep row;
1859                 int x = 0;
1860
1861                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1862                 if (!row) {
1863                         TBM_ERR("fail to allocate the png row.\n");
1864                         for (x = 0; x < y; x++)
1865                                 png_free(pPngStruct, row_pointers[x]);
1866                         png_free(pPngStruct, row_pointers);
1867                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1868                         fclose(fp);
1869                         return;
1870                 }
1871                 row_pointers[y] = (png_bytep)row;
1872
1873                 for (x = 0; x < width; ++x) {
1874                         unsigned int curBlock = blocks[(y * (stride >> 2)) + x];
1875
1876                         if (pixel_size == 3) { // XRGB8888
1877                                 row[x * pixel_size] = (curBlock & 0xFF);
1878                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1879                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1880                         } else { // ARGB8888
1881                                 row[x * pixel_size] = (curBlock & 0xFF);
1882                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1883                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1884                                 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1885                         }
1886                 }
1887         }
1888
1889         png_write_image(pPngStruct, row_pointers);
1890         png_write_end(pPngStruct, pPngInfo);
1891
1892         for (y = 0; y < height; y++)
1893                 png_free(pPngStruct, row_pointers[y]);
1894         png_free(pPngStruct, row_pointers);
1895
1896         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1897
1898         fclose(fp);
1899 }
1900
1901 void
1902 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1903 {
1904         TBM_RETURN_IF_FAIL(path != NULL);
1905         TBM_RETURN_IF_FAIL(w > 0);
1906         TBM_RETURN_IF_FAIL(h > 0);
1907         TBM_RETURN_IF_FAIL(count > 0);
1908
1909         tbm_surface_dump_buf_info *buf_info = NULL;
1910         tbm_surface_h tbm_surface;
1911         tbm_surface_info_s info;
1912         int buffer_size, i;
1913
1914         /* check running */
1915         if (g_dump_info) {
1916                 TBM_WRN("waring already running the tbm_surface_internal_dump.\n");
1917                 return;
1918         }
1919
1920         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1921         TBM_RETURN_IF_FAIL(g_dump_info);
1922
1923         LIST_INITHEAD(&g_dump_info->surface_list);
1924         g_dump_info->count = 0;
1925         g_dump_info->dump_max = count;
1926
1927         /* get buffer size */
1928         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1929         if (tbm_surface == NULL) {
1930                 TBM_ERR("tbm_surface_create fail\n");
1931                 free(g_dump_info);
1932                 g_dump_info = NULL;
1933                 return;
1934         }
1935
1936         if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
1937                 TBM_ERR("tbm_surface_get_info fail\n");
1938                 tbm_surface_destroy(tbm_surface);
1939                 free(g_dump_info);
1940                 g_dump_info = NULL;
1941                 return;
1942         }
1943         buffer_size = info.size;
1944         tbm_surface_destroy(tbm_surface);
1945
1946         /* create dump lists */
1947         for (i = 0; i < count; i++) {
1948                 tbm_bo bo = NULL;
1949
1950                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1951                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1952
1953                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1954                 if (bo == NULL) {
1955                         TBM_ERR("fail to allocate the tbm_bo[%d]\n", i);
1956                         free(buf_info);
1957                         goto fail;
1958                 }
1959
1960                 buf_info->index = i;
1961                 buf_info->bo = bo;
1962                 buf_info->size = buffer_size;
1963
1964                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1965         }
1966
1967         g_dump_info->path = path;
1968         g_dump_info->link = &g_dump_info->surface_list;
1969
1970         scale_factor = 0.0;
1971
1972         TBM_INFO("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1973
1974         return;
1975
1976 fail:
1977         /* free resources */
1978         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1979                 tbm_surface_dump_buf_info *tmp;
1980
1981                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1982                         tbm_bo_unref(buf_info->bo);
1983                         LIST_DEL(&buf_info->link);
1984                         free(buf_info);
1985                 }
1986         }
1987
1988         TBM_ERR("Dump Start fail.. path:%s\n", g_dump_info->path);
1989
1990         free(g_dump_info);
1991         g_dump_info = NULL;
1992
1993         return;
1994 }
1995
1996 void
1997 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
1998 {
1999         if (scale > 0.0) {
2000                 w *= scale;
2001                 h *= scale;
2002         }
2003
2004         tbm_surface_internal_dump_start(path, w, h, count);
2005         scale_factor = scale;
2006 }
2007
2008 void
2009 tbm_surface_internal_dump_end(void)
2010 {
2011         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
2012         tbm_bo_handle bo_handle;
2013
2014         if (!g_dump_info)
2015                 return;
2016
2017         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
2018                 free(g_dump_info);
2019                 g_dump_info = NULL;
2020                 return;
2021         }
2022
2023         /* make files */
2024         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
2025                 char file[2048];
2026
2027                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
2028                 if (bo_handle.ptr == NULL) {
2029                         tbm_bo_unref(buf_info->bo);
2030                         LIST_DEL(&buf_info->link);
2031                         free(buf_info);
2032                         continue;
2033                 }
2034
2035                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
2036                 TBM_INFO("Dump File.. %s generated.\n", file);
2037
2038                 if (buf_info->dirty) {
2039                         void *ptr1 = NULL, *ptr2 = NULL;
2040
2041                         switch (buf_info->info.format) {
2042                         case TBM_FORMAT_ARGB8888:
2043                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2044                                                         buf_info->info.planes[0].stride >> 2,
2045                                                         buf_info->info.height,
2046                                                         buf_info->info.planes[0].stride,
2047                                                         TBM_FORMAT_ARGB8888);
2048                                 break;
2049                         case TBM_FORMAT_XRGB8888:
2050                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2051                                                         buf_info->info.planes[0].stride >> 2,
2052                                                         buf_info->info.height,
2053                                                         buf_info->info.planes[0].stride,
2054                                                         TBM_FORMAT_XRGB8888);
2055                                 break;
2056                         case TBM_FORMAT_YVU420:
2057                         case TBM_FORMAT_YUV420:
2058                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2059                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
2060                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2061                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2062                                                         ptr1,
2063                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2064                                                         ptr2,
2065                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
2066                                 break;
2067                         case TBM_FORMAT_NV12:
2068                         case TBM_FORMAT_NV21:
2069                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
2070                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2071                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2072                                                         ptr1,
2073                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
2074                                                         NULL, 0);
2075                                 break;
2076                         case TBM_FORMAT_YUYV:
2077                         case TBM_FORMAT_UYVY:
2078                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2079                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2080                                                         NULL, 0, NULL, 0);
2081                                 break;
2082                         default:
2083                                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
2084                                 break;
2085                         }
2086                 } else if (buf_info->dirty_shm)
2087                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2088                                                         buf_info->shm_stride >> 2,
2089                                                         buf_info->shm_h,
2090                                                         buf_info->shm_stride, 0);
2091
2092                 tbm_bo_unmap(buf_info->bo);
2093                 tbm_bo_unref(buf_info->bo);
2094                 LIST_DEL(&buf_info->link);
2095                 free(buf_info);
2096         }
2097
2098         free(g_dump_info);
2099         g_dump_info = NULL;
2100
2101         TBM_INFO("Dump End..\n");
2102 }
2103
2104 static pixman_format_code_t
2105 _tbm_surface_internal_pixman_format_get(tbm_format format)
2106 {
2107         switch (format) {
2108         case TBM_FORMAT_ARGB8888:
2109                 return PIXMAN_a8r8g8b8;
2110         case TBM_FORMAT_XRGB8888:
2111                 return PIXMAN_x8r8g8b8;
2112         default:
2113                 return 0;
2114         }
2115
2116         return 0;
2117 }
2118
2119 /**
2120  * This function supports only if a buffer has below formats.
2121  * - TBM_FORMAT_ARGB8888
2122  * - TBM_FORMAT_XRGB8888
2123  */
2124 static tbm_surface_error_e
2125 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
2126                                                                    int format, int src_stride, int src_w, int src_h,
2127                                                                    int dst_stride, int dst_w, int dst_h)
2128 {
2129         pixman_image_t *src_img = NULL, *dst_img = NULL;
2130         pixman_format_code_t pixman_format;
2131         pixman_transform_t t;
2132         struct pixman_f_transform ft;
2133         double scale_x, scale_y;
2134
2135         TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2136         TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2137
2138         pixman_format = _tbm_surface_internal_pixman_format_get(format);
2139         TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2140
2141         /* src */
2142         src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2143                                                                            (uint32_t*)src_ptr, src_stride);
2144         TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2145
2146         /* dst */
2147         dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2148                                                                            (uint32_t*)dst_ptr, dst_stride);
2149         TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2150
2151         pixman_f_transform_init_identity(&ft);
2152
2153         scale_x = (double)src_w / dst_w;
2154         scale_y = (double)src_h / dst_h;
2155
2156         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2157         pixman_f_transform_translate(&ft, NULL, 0, 0);
2158         pixman_transform_from_pixman_f_transform(&t, &ft);
2159         pixman_image_set_transform(src_img, &t);
2160
2161         pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2162                                                    0, 0, 0, 0, 0, 0, dst_w, dst_h);
2163
2164         pixman_image_unref(src_img);
2165         pixman_image_unref(dst_img);
2166
2167         return TBM_SURFACE_ERROR_NONE;
2168
2169 cant_convert:
2170         if (src_img)
2171                 pixman_image_unref(src_img);
2172
2173         return TBM_SURFACE_ERROR_INVALID_OPERATION;
2174 }
2175
2176 #define MAX_BOS         4       // This value is came from bos[4] in struct _tbm_surface
2177 #define KEY_LEN         5       // "_XXXX"
2178 #define KEYS_LEN        KEY_LEN * MAX_BOS
2179
2180 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2181 {
2182         char *keys, temp_key[KEY_LEN + 1];
2183         struct _tbm_surface *surf;
2184         int i, num_bos;
2185         tbm_bo bo;
2186
2187         _tbm_surface_mutex_lock();
2188
2189         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2190
2191         surf = (struct _tbm_surface *)surface;
2192
2193         num_bos = surf->num_bos;
2194         if (num_bos > MAX_BOS)
2195                 num_bos = MAX_BOS;
2196
2197         keys = calloc(KEYS_LEN + 1, sizeof(char));
2198         if (!keys) {
2199                 TBM_ERR("Failed to alloc memory");
2200                 _tbm_surface_mutex_unlock();
2201                 return NULL;
2202         }
2203
2204         for (i = 0; i < num_bos; i++) {
2205                 memset(temp_key, 0x00, KEY_LEN + 1);
2206                 bo = surf->bos[i];
2207                 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2208                 strncat(keys, temp_key, KEY_LEN + 1);
2209         }
2210
2211         _tbm_surface_mutex_unlock();
2212
2213         return keys;
2214 }
2215
2216 static void _tbm_surface_internal_put_keys(char *keys)
2217 {
2218         if (keys)
2219                 free(keys);
2220 }
2221
2222 void
2223 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2224 {
2225         TBM_RETURN_IF_FAIL(surface != NULL);
2226         TBM_RETURN_IF_FAIL(type != NULL);
2227
2228         tbm_surface_dump_buf_info *buf_info;
2229         struct list_head *next_link;
2230         tbm_surface_info_s info;
2231         tbm_bo_handle bo_handle;
2232         const char *postfix;
2233         const char *format = NULL;
2234         char *keys;
2235         int ret;
2236
2237         if (!g_dump_info)
2238                 return;
2239
2240         next_link = g_dump_info->link->next;
2241         TBM_RETURN_IF_FAIL(next_link != NULL);
2242
2243         if (next_link == &g_dump_info->surface_list) {
2244                 next_link = next_link->next;
2245                 TBM_RETURN_IF_FAIL(next_link != NULL);
2246         }
2247
2248         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2249         TBM_RETURN_IF_FAIL(buf_info != NULL);
2250
2251         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2252         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2253
2254         if (scale_factor > 0.0) {
2255                 const int bpp = 4;
2256
2257                 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
2258                         TBM_WRN("Dump with scale skip. unsupported format(%s)\n",
2259                                           _tbm_surface_internal_format_to_str(info.format));
2260                         tbm_surface_unmap(surface);
2261                         return;
2262                 }
2263
2264                 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2265
2266                 buf_info->info.width = info.width * scale_factor;
2267                 buf_info->info.height = info.height * scale_factor;
2268                 buf_info->info.format = info.format;
2269                 buf_info->info.bpp = _tbm_surface_internal_get_bpp(buf_info->info.format);
2270                 if (!buf_info->info.bpp) {
2271                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
2272                         tbm_surface_unmap(surface);
2273                         return;
2274                 }
2275                 buf_info->info.num_planes = 1;
2276                 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2277                 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2278
2279                 if (buf_info->info.size > buf_info->size) {
2280                         TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)\n",
2281                                         buf_info->info.size, buf_info->size);
2282                         tbm_surface_unmap(surface);
2283                         return;
2284                 }
2285         } else {
2286                 if (info.size > buf_info->size) {
2287                         TBM_WRN("Dump skip. surface over created buffer size(%u, %d)\n",
2288                                         info.size, buf_info->size);
2289                         tbm_surface_unmap(surface);
2290                         return;
2291                 }
2292
2293                 /* make the file information */
2294                 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2295         }
2296
2297         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888) {
2298                 postfix = dump_postfix[0];
2299                 format = _tbm_surface_internal_format_to_str(info.format);
2300         } else
2301                 postfix = dump_postfix[1];
2302
2303         keys = _tbm_surface_internal_get_keys(surface);
2304         if (!keys) {
2305                 TBM_ERR("fail to get keys");
2306                 tbm_surface_unmap(surface);
2307                 return;
2308         }
2309
2310         /* dump */
2311         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2312         if (!bo_handle.ptr) {
2313                 TBM_ERR("fail to map bo");
2314                 _tbm_surface_internal_put_keys(keys);
2315                 tbm_surface_unmap(surface);
2316                 return;
2317         }
2318         memset(bo_handle.ptr, 0x00, buf_info->size);
2319
2320         switch (info.format) {
2321         case TBM_FORMAT_ARGB8888:
2322         case TBM_FORMAT_XRGB8888:
2323                 snprintf(buf_info->name, sizeof(buf_info->name),
2324                                 "%10.3f_%03d%s_%p_%s-%s.%s",
2325                                  _tbm_surface_internal_get_time(),
2326                                  g_dump_info->count++, keys, surface, format, type, postfix);
2327
2328                 if (scale_factor > 0.0) {
2329                         ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2330                                                                                                          bo_handle.ptr,
2331                                                                                                          buf_info->info.format,
2332                                                                                                          info.planes[0].stride,
2333                                                                                                          info.width, info.height,
2334                                                                                                          buf_info->info.planes[0].stride,
2335                                                                                                          buf_info->info.width,
2336                                                                                                          buf_info->info.height);
2337                         if (ret != TBM_SURFACE_ERROR_NONE) {
2338                                 TBM_ERR("fail to scale buffer");
2339                                 tbm_bo_unmap(buf_info->bo);
2340                                 _tbm_surface_internal_put_keys(keys);
2341                                 tbm_surface_unmap(surface);
2342                                 return;
2343                         }
2344                 } else
2345                         memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2346                 break;
2347         case TBM_FORMAT_YVU420:
2348         case TBM_FORMAT_YUV420:
2349                 snprintf(buf_info->name, sizeof(buf_info->name),
2350                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2351                                  _tbm_surface_internal_get_time(),
2352                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2353                                 info.height, FOURCC_STR(info.format), postfix);
2354                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2355                 bo_handle.ptr += info.planes[0].stride * info.height;
2356                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2357                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2358                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2359                 break;
2360         case TBM_FORMAT_NV12:
2361         case TBM_FORMAT_NV21:
2362                 snprintf(buf_info->name, sizeof(buf_info->name),
2363                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2364                                  _tbm_surface_internal_get_time(),
2365                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2366                                 info.height, FOURCC_STR(info.format), postfix);
2367                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2368                 bo_handle.ptr += info.planes[0].stride * info.height;
2369                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2370                 break;
2371         case TBM_FORMAT_YUYV:
2372         case TBM_FORMAT_UYVY:
2373                 snprintf(buf_info->name, sizeof(buf_info->name),
2374                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2375                                  _tbm_surface_internal_get_time(),
2376                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2377                                 info.height, FOURCC_STR(info.format), postfix);
2378                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2379                 break;
2380         default:
2381                 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2382                 tbm_bo_unmap(buf_info->bo);
2383                 _tbm_surface_internal_put_keys(keys);
2384                 tbm_surface_unmap(surface);
2385                 return;
2386         }
2387
2388         tbm_bo_unmap(buf_info->bo);
2389
2390         _tbm_surface_internal_put_keys(keys);
2391
2392         tbm_surface_unmap(surface);
2393
2394         buf_info->dirty = 1;
2395         buf_info->dirty_shm = 0;
2396
2397         if (g_dump_info->count == 1000)
2398                 g_dump_info->count = 0;
2399
2400         g_dump_info->link = next_link;
2401
2402         TBM_INFO("Dump %s \n", buf_info->name);
2403 }
2404
2405 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2406                                                 const char *type)
2407 {
2408         TBM_RETURN_IF_FAIL(ptr != NULL);
2409         TBM_RETURN_IF_FAIL(w > 0);
2410         TBM_RETURN_IF_FAIL(h > 0);
2411         TBM_RETURN_IF_FAIL(stride > 0);
2412         TBM_RETURN_IF_FAIL(type != NULL);
2413
2414         tbm_surface_dump_buf_info *buf_info;
2415         struct list_head *next_link;
2416         tbm_bo_handle bo_handle;
2417         int ret, size, dw = 0, dh = 0, dstride = 0;
2418
2419         if (!g_dump_info)
2420                 return;
2421
2422         next_link = g_dump_info->link->next;
2423         TBM_RETURN_IF_FAIL(next_link != NULL);
2424
2425         if (next_link == &g_dump_info->surface_list) {
2426                 next_link = next_link->next;
2427                 TBM_RETURN_IF_FAIL(next_link != NULL);
2428         }
2429
2430         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2431         TBM_RETURN_IF_FAIL(buf_info != NULL);
2432
2433         if (scale_factor > 0.0) {
2434                 const int bpp = 4;
2435
2436                 dw = w * scale_factor;
2437                 dh = h * scale_factor;
2438                 dstride = dw * bpp;
2439                 size = dstride * dh;
2440         } else
2441                 size = stride * h;
2442
2443         if (size > buf_info->size) {
2444                 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2445                                 size, buf_info->size);
2446                 return;
2447         }
2448
2449         /* dump */
2450         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2451         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2452
2453         memset(bo_handle.ptr, 0x00, buf_info->size);
2454         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2455
2456         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2457                          _tbm_surface_internal_get_time(),
2458                          g_dump_info->count++, type, dump_postfix[0]);
2459         if (scale_factor > 0.0) {
2460                 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2461                                                                                                  TBM_FORMAT_ARGB8888, stride,
2462                                                                                                  w, h, dstride, dw, dh);
2463                 if (ret != TBM_SURFACE_ERROR_NONE) {
2464                         TBM_ERR("fail to scale buffer");
2465                         tbm_bo_unmap(buf_info->bo);
2466                         return;
2467                 }
2468                 buf_info->shm_stride = dstride;
2469                 buf_info->shm_h = dh;
2470         } else {
2471                 memcpy(bo_handle.ptr, ptr, size);
2472                 buf_info->shm_stride = stride;
2473                 buf_info->shm_h = h;
2474         }
2475
2476         tbm_bo_unmap(buf_info->bo);
2477
2478         buf_info->dirty = 0;
2479         buf_info->dirty_shm = 1;
2480
2481         if (g_dump_info->count == 1000)
2482                 g_dump_info->count = 0;
2483
2484         g_dump_info->link = next_link;
2485
2486         TBM_INFO("Dump %s \n", buf_info->name);
2487 }
2488
2489 int
2490 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2491 {
2492         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2493         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2494         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2495
2496         tbm_surface_info_s info;
2497         const char *postfix;
2498         int ret;
2499         char file[1024];
2500
2501         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2502         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2503
2504         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2505                 postfix = dump_postfix[0];
2506         else
2507                 postfix = dump_postfix[1];
2508
2509         if (strcmp(postfix, type)) {
2510                 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2511                 tbm_surface_unmap(surface);
2512                 return 0;
2513         }
2514
2515         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2516
2517         if (!access(file, 0)) {
2518                 TBM_ERR("can't capture  buffer, exist file %s", file);
2519                 tbm_surface_unmap(surface);
2520                 return 0;
2521         }
2522
2523         switch (info.format) {
2524         case TBM_FORMAT_ARGB8888:
2525                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2526                                                         info.width,
2527                                                         info.height,
2528                                                         info.planes[0].stride,
2529                                                         TBM_FORMAT_ARGB8888);
2530                 break;
2531         case TBM_FORMAT_XRGB8888:
2532                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2533                                                         info.width,
2534                                                         info.height,
2535                                                         info.planes[0].stride,
2536                                                         TBM_FORMAT_XRGB8888);
2537                 break;
2538         case TBM_FORMAT_YVU420:
2539         case TBM_FORMAT_YUV420:
2540                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2541                                 info.planes[0].stride * info.height,
2542                                 info.planes[1].ptr,
2543                                 info.planes[1].stride * (info.height >> 1),
2544                                 info.planes[2].ptr,
2545                                 info.planes[2].stride * (info.height >> 1));
2546                 break;
2547         case TBM_FORMAT_NV12:
2548         case TBM_FORMAT_NV21:
2549                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2550                                         info.planes[0].stride * info.height,
2551                                         info.planes[1].ptr,
2552                                         info.planes[1].stride * (info.height >> 1),
2553                                         NULL, 0);
2554                 break;
2555         case TBM_FORMAT_YUYV:
2556         case TBM_FORMAT_UYVY:
2557                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2558                                         info.planes[0].stride * info.height,
2559                                         NULL, 0, NULL, 0);
2560                 break;
2561         default:
2562                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2563                 tbm_surface_unmap(surface);
2564                 return 0;
2565         }
2566
2567         tbm_surface_unmap(surface);
2568
2569         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2570
2571         return 1;
2572 }
2573
2574 int
2575 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2576                                                 const char *path, const char *name, const char *type)
2577 {
2578         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2579         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2580         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2581         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2582         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2583         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2584
2585         char file[1024];
2586
2587         if (strcmp(dump_postfix[0], type)) {
2588                 TBM_ERR("Not supported type:%s'", type);
2589                 return 0;
2590         }
2591
2592         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2593
2594         if (!access(file, 0)) {
2595                 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2596                 return 0;
2597         }
2598
2599         _tbm_surface_internal_dump_file_png(file, ptr, w, h, stride, 0);
2600
2601         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2602
2603         return 1;
2604 }
2605
2606 int
2607 tbm_surface_internal_set_damage(tbm_surface_h surface, int x, int y, int width, int height)
2608 {
2609         struct _tbm_surface *surf;
2610
2611         _tbm_surface_mutex_lock();
2612         _tbm_set_last_result(TBM_ERROR_NONE);
2613
2614         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, 0);
2615         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, 0);
2616         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2617
2618         surf = (struct _tbm_surface *)surface;
2619
2620         surf->damage.x = x;
2621         surf->damage.y = y;
2622         surf->damage.width = width;
2623         surf->damage.height = height;
2624
2625         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2626                                                         surface, x, y, width, height);
2627
2628         _tbm_surface_mutex_unlock();
2629
2630         return 1;
2631 }
2632
2633 int
2634 tbm_surface_internal_get_damage(tbm_surface_h surface, int *x, int *y, int *width, int *height)
2635 {
2636         struct _tbm_surface *surf;
2637
2638         _tbm_surface_mutex_lock();
2639         _tbm_set_last_result(TBM_ERROR_NONE);
2640
2641         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2642
2643         surf = (struct _tbm_surface *)surface;
2644
2645         if (x) *x = surf->damage.x;
2646         if (y) *y = surf->damage.y;
2647         if (width) *width = surf->damage.width;
2648         if (height) *height = surf->damage.height;
2649
2650         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2651                                                         surface, surf->damage.x, surf->damage.y, surf->damage.width, surf->damage.height);
2652
2653         _tbm_surface_mutex_unlock();
2654
2655         return 1;
2656 }
2657
2658 int
2659 tbm_surface_internal_add_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2660 {
2661         struct _tbm_surface *surf;
2662         tbm_surface_destroy_func_info *func_info = NULL;
2663
2664         _tbm_surface_mutex_lock();
2665         _tbm_set_last_result(TBM_ERROR_NONE);
2666
2667         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2668         TBM_SURFACE_RETURN_VAL_IF_FAIL(func != NULL, 0);
2669
2670         surf = (struct _tbm_surface *)surface;
2671         LIST_FOR_EACH_ENTRY(func_info, &surf->destroy_funcs, item_link) {
2672                 if (func_info->destroy_func == func && func_info->user_data == user_data) {
2673                         TBM_ERR("can't add twice");
2674                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
2675                         _tbm_surface_mutex_unlock();
2676                         return 0;
2677                 }
2678         }
2679
2680         func_info = calloc(1, sizeof(tbm_surface_destroy_func_info));
2681         if (func_info == NULL) {
2682                 TBM_ERR("alloc failed");
2683                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
2684                 _tbm_surface_mutex_unlock();
2685                 return 0;
2686         }
2687
2688         func_info->destroy_func = func;
2689         func_info->user_data = user_data;
2690
2691         LIST_ADDTAIL(&func_info->item_link, &surf->destroy_funcs);
2692
2693         _tbm_surface_mutex_unlock();
2694
2695         return 1;
2696 }
2697
2698 void
2699 tbm_surface_internal_remove_destroy_handler(tbm_surface_h surface, tbm_surface_internal_destroy_handler func, void *user_data)
2700 {
2701         struct _tbm_surface *surf;
2702         tbm_surface_destroy_func_info *func_info = NULL, *next = NULL;
2703
2704         _tbm_surface_mutex_lock();
2705         _tbm_set_last_result(TBM_ERROR_NONE);
2706
2707         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
2708         TBM_SURFACE_RETURN_IF_FAIL(func != NULL);
2709
2710         surf = (struct _tbm_surface *)surface;
2711         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &surf->destroy_funcs, item_link) {
2712                 if (func_info->destroy_func != func || func_info->user_data != user_data)
2713                         continue;
2714
2715                 LIST_DEL(&func_info->item_link);
2716                 free(func_info);
2717
2718                 _tbm_surface_mutex_unlock();
2719
2720                 return;
2721         }
2722
2723         _tbm_surface_mutex_unlock();
2724 }
2725 /*LCOV_EXCL_STOP*/