surface: clean up tbm_surface_internal_set_debug_data
[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->backend_module_data) {
293                 if (!bufmgr->bufmgr_func->bufmgr_get_plane_data) {
294                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
295                         return 0;
296                 }
297
298                 error = bufmgr->bufmgr_func->bufmgr_get_plane_data(bufmgr->bufmgr_data, surf->info.format, plane_idx,
299                                                 surf->info.width, surf->info.height, size, offset, pitch, bo_idx);
300                 if (error != TBM_ERROR_NONE) {
301                         /* LCOV_EXCL_START */
302                         TBM_ERR("Fail to surface_get_plane_data. surface(%p) error(%d)\n", surface, error);
303                         _tbm_set_last_result(error);
304                         return 0;
305                         /* LCOV_EXCL_STOP */
306                 }
307                 ret = 1;
308         } else {
309                 if (!bufmgr->backend->surface_get_plane_data) {
310                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
311                         return 0;
312                 }
313
314                 ret = bufmgr->backend->surface_get_plane_data(surf->info.width,
315                                 surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
316                 if (!ret) {
317                         /* LCOV_EXCL_START */
318                         TBM_ERR("Fail to surface_get_plane_data. surface(%p)\n", surface);
319                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
320                         return 0;
321                         /* LCOV_EXCL_STOP */
322                 }
323         }
324
325         return ret;
326 }
327
328 static void
329 _tbm_surface_internal_destroy(tbm_surface_h surface)
330 {
331         int i;
332         tbm_bufmgr bufmgr = surface->bufmgr;
333         tbm_user_data *old_data = NULL, *tmp = NULL;
334         tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
335
336         /* destory the user_data_list */
337         if (!LIST_IS_EMPTY(&surface->user_data_list)) {
338                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
339                         TBM_DBG("free user_data\n");
340                         user_data_delete(old_data);
341                 }
342         }
343
344         for (i = 0; i < surface->num_bos; i++) {
345                 surface->bos[i]->surface = NULL;
346
347                 tbm_bo_unref(surface->bos[i]);
348                 surface->bos[i] = NULL;
349         }
350
351         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
352                 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
353                         _tbm_surface_internal_debug_data_delete(debug_old_data);
354         }
355
356         LIST_DEL(&surface->item_link);
357         surface->magic = 0;
358
359         free(surface);
360         surface = NULL;
361
362         if (bufmgr && LIST_IS_EMPTY(&bufmgr->surf_list)) {
363                 LIST_DELINIT(&bufmgr->surf_list);
364
365                 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
366                         LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
367                                 _tbm_surface_internal_debug_data_delete(debug_old_data);
368                         }
369                 }
370
371                 _deinit_surface_bufmgr();
372         }
373 }
374
375 /* LCOV_EXCL_START */
376 static int
377 _tbm_surface_check_file_is_symbolic_link(const char* path)
378 {
379         struct stat sb;
380
381         if (!path)
382                 return 0;
383
384         if (stat(path, &sb) != 0)
385                 return 0;
386
387         if (S_ISLNK(sb.st_mode))
388                 return 1;
389
390         return 0;
391 }
392 /* LCOV_EXCL_STOP */
393
394 static int
395 _tbm_surface_internal_get_num_planes(tbm_format format)
396 {
397         int num_planes = 0;
398
399         switch (format) {
400         case TBM_FORMAT_C8:
401         case TBM_FORMAT_RGB332:
402         case TBM_FORMAT_BGR233:
403         case TBM_FORMAT_XRGB4444:
404         case TBM_FORMAT_XBGR4444:
405         case TBM_FORMAT_RGBX4444:
406         case TBM_FORMAT_BGRX4444:
407         case TBM_FORMAT_ARGB4444:
408         case TBM_FORMAT_ABGR4444:
409         case TBM_FORMAT_RGBA4444:
410         case TBM_FORMAT_BGRA4444:
411         case TBM_FORMAT_XRGB1555:
412         case TBM_FORMAT_XBGR1555:
413         case TBM_FORMAT_RGBX5551:
414         case TBM_FORMAT_BGRX5551:
415         case TBM_FORMAT_ARGB1555:
416         case TBM_FORMAT_ABGR1555:
417         case TBM_FORMAT_RGBA5551:
418         case TBM_FORMAT_BGRA5551:
419         case TBM_FORMAT_RGB565:
420         case TBM_FORMAT_BGR565:
421         case TBM_FORMAT_RGB888:
422         case TBM_FORMAT_BGR888:
423         case TBM_FORMAT_XRGB8888:
424         case TBM_FORMAT_XBGR8888:
425         case TBM_FORMAT_RGBX8888:
426         case TBM_FORMAT_BGRX8888:
427         case TBM_FORMAT_ARGB8888:
428         case TBM_FORMAT_ABGR8888:
429         case TBM_FORMAT_RGBA8888:
430         case TBM_FORMAT_BGRA8888:
431         case TBM_FORMAT_XRGB2101010:
432         case TBM_FORMAT_XBGR2101010:
433         case TBM_FORMAT_RGBX1010102:
434         case TBM_FORMAT_BGRX1010102:
435         case TBM_FORMAT_ARGB2101010:
436         case TBM_FORMAT_ABGR2101010:
437         case TBM_FORMAT_RGBA1010102:
438         case TBM_FORMAT_BGRA1010102:
439         case TBM_FORMAT_YUYV:
440         case TBM_FORMAT_YVYU:
441         case TBM_FORMAT_UYVY:
442         case TBM_FORMAT_VYUY:
443         case TBM_FORMAT_AYUV:
444                 num_planes = 1;
445                 break;
446         case TBM_FORMAT_NV12:
447         case TBM_FORMAT_NV12MT:
448         case TBM_FORMAT_NV21:
449         case TBM_FORMAT_NV16:
450         case TBM_FORMAT_NV61:
451                 num_planes = 2;
452                 break;
453         case TBM_FORMAT_YUV410:
454         case TBM_FORMAT_YVU410:
455         case TBM_FORMAT_YUV411:
456         case TBM_FORMAT_YVU411:
457         case TBM_FORMAT_YUV420:
458         case TBM_FORMAT_YVU420:
459         case TBM_FORMAT_YUV422:
460         case TBM_FORMAT_YVU422:
461         case TBM_FORMAT_YUV444:
462         case TBM_FORMAT_YVU444:
463                 num_planes = 3;
464                 break;
465
466         default:
467                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
468                 break;
469         }
470
471         return num_planes;
472 }
473
474 static int
475 _tbm_surface_internal_get_bpp(tbm_format format)
476 {
477
478         int bpp = 0;
479
480         switch (format) {
481         case TBM_FORMAT_C8:
482         case TBM_FORMAT_RGB332:
483         case TBM_FORMAT_BGR233:
484                 bpp = 8;
485                 break;
486         case TBM_FORMAT_XRGB4444:
487         case TBM_FORMAT_XBGR4444:
488         case TBM_FORMAT_RGBX4444:
489         case TBM_FORMAT_BGRX4444:
490         case TBM_FORMAT_ARGB4444:
491         case TBM_FORMAT_ABGR4444:
492         case TBM_FORMAT_RGBA4444:
493         case TBM_FORMAT_BGRA4444:
494         case TBM_FORMAT_XRGB1555:
495         case TBM_FORMAT_XBGR1555:
496         case TBM_FORMAT_RGBX5551:
497         case TBM_FORMAT_BGRX5551:
498         case TBM_FORMAT_ARGB1555:
499         case TBM_FORMAT_ABGR1555:
500         case TBM_FORMAT_RGBA5551:
501         case TBM_FORMAT_BGRA5551:
502         case TBM_FORMAT_RGB565:
503         case TBM_FORMAT_BGR565:
504                 bpp = 16;
505                 break;
506         case TBM_FORMAT_RGB888:
507         case TBM_FORMAT_BGR888:
508                 bpp = 24;
509                 break;
510         case TBM_FORMAT_XRGB8888:
511         case TBM_FORMAT_XBGR8888:
512         case TBM_FORMAT_RGBX8888:
513         case TBM_FORMAT_BGRX8888:
514         case TBM_FORMAT_ARGB8888:
515         case TBM_FORMAT_ABGR8888:
516         case TBM_FORMAT_RGBA8888:
517         case TBM_FORMAT_BGRA8888:
518         case TBM_FORMAT_XRGB2101010:
519         case TBM_FORMAT_XBGR2101010:
520         case TBM_FORMAT_RGBX1010102:
521         case TBM_FORMAT_BGRX1010102:
522         case TBM_FORMAT_ARGB2101010:
523         case TBM_FORMAT_ABGR2101010:
524         case TBM_FORMAT_RGBA1010102:
525         case TBM_FORMAT_BGRA1010102:
526         case TBM_FORMAT_YUYV:
527         case TBM_FORMAT_YVYU:
528         case TBM_FORMAT_UYVY:
529         case TBM_FORMAT_VYUY:
530         case TBM_FORMAT_AYUV:
531                 bpp = 32;
532                 break;
533         case TBM_FORMAT_NV12:
534         case TBM_FORMAT_NV12MT:
535         case TBM_FORMAT_NV21:
536                 bpp = 12;
537                 break;
538         case TBM_FORMAT_NV16:
539         case TBM_FORMAT_NV61:
540                 bpp = 16;
541                 break;
542         case TBM_FORMAT_YUV410:
543         case TBM_FORMAT_YVU410:
544                 bpp = 9;
545                 break;
546         case TBM_FORMAT_YUV411:
547         case TBM_FORMAT_YVU411:
548         case TBM_FORMAT_YUV420:
549         case TBM_FORMAT_YVU420:
550                 bpp = 12;
551                 break;
552         case TBM_FORMAT_YUV422:
553         case TBM_FORMAT_YVU422:
554                 bpp = 16;
555                 break;
556         case TBM_FORMAT_YUV444:
557         case TBM_FORMAT_YVU444:
558                 bpp = 24;
559                 break;
560         default:
561                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
562                 break;
563         }
564
565         return bpp;
566 }
567
568 int
569 tbm_surface_internal_is_valid(tbm_surface_h surface)
570 {
571         int ret = 0;
572
573         _tbm_surface_mutex_lock();
574         _tbm_set_last_result(TBM_ERROR_NONE);
575
576         /* Return silently if surface is null. */
577         if (!surface) {
578                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
579                 _tbm_surface_mutex_unlock();
580                 return 0;
581         }
582
583         ret = _tbm_surface_internal_is_valid(surface);
584
585         _tbm_surface_mutex_unlock();
586
587         return ret;
588 }
589
590 int
591 tbm_surface_internal_query_supported_formats(uint32_t **formats,
592                 uint32_t *num)
593 {
594         struct _tbm_bufmgr *bufmgr;
595         int ret = 0;
596         bool bufmgr_initialized = false;
597         tbm_error_e error;
598
599         _tbm_surface_mutex_lock();
600         _tbm_set_last_result(TBM_ERROR_NONE);
601
602         TBM_SURFACE_RETURN_VAL_IF_FAIL(formats, 0);
603         TBM_SURFACE_RETURN_VAL_IF_FAIL(num, 0);
604
605         if (!g_surface_bufmgr) {
606                 _init_surface_bufmgr();
607                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
608                 bufmgr_initialized = true;
609         }
610
611         bufmgr = g_surface_bufmgr;
612
613         if (bufmgr->backend_module_data) {
614                 if (!bufmgr->bufmgr_func->bufmgr_get_supported_formats) {
615                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
616                         goto fail;
617                 }
618
619                 error = bufmgr->bufmgr_func->bufmgr_get_supported_formats(bufmgr->bufmgr_data, formats, num);
620                 if (error != TBM_ERROR_NONE) {
621                         /* LCOV_EXCL_START */
622                         TBM_ERR("Fail to surface_supported_format. error(%d)\n", error);
623                         goto fail;
624                         /* LCOV_EXCL_START */
625                 }
626                 ret = 1;
627         } else {
628                 if (!bufmgr->backend->surface_supported_format) {
629                         _tbm_set_last_result(TBM_ERROR_NOT_SUPPORTED);
630                         goto fail;
631                 }
632
633                 ret = bufmgr->backend->surface_supported_format(formats, num);
634                 if (!ret)  {
635                         /* LCOV_EXCL_START */
636                         TBM_ERR("Fail to surface_supported_format.\n");
637                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
638                         goto fail;
639                         /* LCOV_EXCL_START */
640                 }
641         }
642
643         TBM_TRACE_SURFACE_INTERNAL("tbm_bufmgr(%p) format num(%u)\n", g_surface_bufmgr, *num);
644
645         if (bufmgr_initialized) {
646                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
647                 _deinit_surface_bufmgr();
648         }
649
650         _tbm_surface_mutex_unlock();
651
652         return ret;
653
654 /* LCOV_EXCL_START */
655 fail:
656         if (bufmgr_initialized) {
657                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
658                 _deinit_surface_bufmgr();
659         }
660         _tbm_surface_mutex_unlock();
661
662         TBM_ERR("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
663
664         return 0;
665 /* LCOV_EXCL_STOP */
666 }
667
668 int
669 tbm_surface_internal_get_num_planes(tbm_format format)
670 {
671         int num_planes = 0;
672
673         _tbm_surface_mutex_lock();
674         _tbm_set_last_result(TBM_ERROR_NONE);
675
676         num_planes = _tbm_surface_internal_get_num_planes(format);
677         if (!num_planes) {
678                 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
679                 _tbm_surface_mutex_unlock();
680                 return 0;
681         }
682
683         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
684
685         _tbm_surface_mutex_unlock();
686
687         return num_planes;
688 }
689
690 int
691 tbm_surface_internal_get_bpp(tbm_format format)
692 {
693         int bpp = 0;
694
695         _tbm_surface_mutex_lock();
696         _tbm_set_last_result(TBM_ERROR_NONE);
697
698         bpp = _tbm_surface_internal_get_bpp(format);
699         if (!bpp) {
700                 TBM_ERR("error: tbm_error(%s)\n", tbm_error_str(tbm_get_last_error()));
701                 _tbm_surface_mutex_unlock();
702                 return 0;
703         }
704
705         _tbm_surface_mutex_unlock();
706
707         TBM_TRACE_SURFACE_INTERNAL("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
708
709         return bpp;
710 }
711
712 tbm_surface_h
713 tbm_surface_internal_create_with_flags(int width, int height,
714                                        int format, int flags)
715 {
716         struct _tbm_bufmgr *bufmgr;
717         struct _tbm_surface *surf = NULL;
718         uint32_t size = 0;
719         uint32_t offset = 0;
720         uint32_t stride = 0;
721         uint32_t bo_size = 0;
722         int bo_idx;
723         int i, j;
724         bool bufmgr_initialized = false;
725         tbm_error_e error;
726
727         _tbm_surface_mutex_lock();
728         _tbm_set_last_result(TBM_ERROR_NONE);
729
730         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, NULL);
731         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, NULL);
732
733         if (!g_surface_bufmgr) {
734                 _init_surface_bufmgr();
735                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
736                 bufmgr_initialized = true;
737         }
738
739         bufmgr = g_surface_bufmgr;
740         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
741                 TBM_ERR("The bufmgr is invalid\n");
742                 goto check_valid_fail;
743         }
744
745         surf = calloc(1, sizeof(struct _tbm_surface));
746         if (!surf) {
747                 /* LCOV_EXCL_START */
748                 TBM_ERR("fail to alloc surf\n");
749                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
750                 goto alloc_surf_fail;
751                 /* LCOV_EXCL_STOP */
752         }
753
754         surf->magic = TBM_SURFACE_MAGIC;
755         surf->bufmgr = bufmgr;
756         surf->info.width = width;
757         surf->info.height = height;
758         surf->info.format = format;
759         surf->info.bpp = _tbm_surface_internal_get_bpp(format);
760         if (!surf->info.bpp) {
761                 TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
762                 goto bpp_fail;
763         }
764         surf->info.num_planes = _tbm_surface_internal_get_num_planes(format);
765         if (!surf->info.num_planes) {
766                 TBM_ERR("fail to get num_planes. error(%s)\n", tbm_error_str(tbm_get_last_error()));
767                 goto num_planes_fail;
768         }
769         surf->refcnt = 1;
770
771         /* get size, stride and offset bo_idx */
772         for (i = 0; i < surf->info.num_planes; i++) {
773                 if (!_tbm_surface_internal_query_plane_data(surf, i, &size,
774                                                 &offset, &stride, &bo_idx)) {
775                         TBM_ERR("fail to query plane data\n");
776                         goto query_plane_data_fail;
777                 }
778
779                 surf->info.planes[i].size = size;
780                 surf->info.planes[i].offset = offset;
781                 surf->info.planes[i].stride = stride;
782                 surf->planes_bo_idx[i] = bo_idx;
783         }
784
785         surf->num_bos = 1;
786
787         for (i = 0; i < surf->info.num_planes; i++) {
788                 surf->info.size += surf->info.planes[i].size;
789
790                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
791                         surf->num_bos = surf->planes_bo_idx[i] + 1;
792         }
793
794         surf->flags = flags;
795
796         for (i = 0; i < surf->num_bos; i++) {
797                 bo_size = 0;
798                 for (j = 0; j < surf->info.num_planes; j++) {
799                         if (surf->planes_bo_idx[j] == i)
800                                 bo_size += surf->info.planes[j].size;
801                 }
802
803                 if (bufmgr->backend_module_data) {
804                         if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_format) {
805                                 /* LCOV_EXCL_START */
806                                 surf->bos[i] = tbm_bo_alloc_with_format(bufmgr, format, i, width, height, flags, &error);
807                                 if (!surf->bos[i]) {
808                                         TBM_ERR("fail to tbm_bo_alloc_with_format idx:%d\n", i);
809                                         goto alloc_bo_fail;
810                                 }
811                                 /* LCOV_EXCL_STOP */
812                         } else if (bufmgr->bufmgr_func->bufmgr_alloc_bo_with_tiled_format && (flags & TBM_BO_TILED)) {
813                                 /* LCOV_EXCL_START */
814                                 surf->bos[i] = tbm_bo_alloc_with_tiled_format(bufmgr, width, height, surf->info.bpp/8, format, flags, i, &error);
815                                 if (!surf->bos[i]) {
816                                         TBM_ERR("fail to tbm_bo_alloc_with_tiled_format idx:%d\n", i);
817                                         goto alloc_bo_fail;
818                                 }
819                                 /* LCOV_EXCL_STOP */
820                         } else {
821                                 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
822                                 if (!surf->bos[i]) {
823                                         TBM_ERR("fail to alloc bo idx:%d\n", i);
824                                         goto alloc_bo_fail;
825                                 }
826                         }
827                 } else {
828                         if (bufmgr->backend->surface_bo_alloc) {
829                                 /* LCOV_EXCL_START */
830                                 surf->bos[i] = tbm_bo_alloc_with_surface(bufmgr, width, height, format, flags, i);
831                                 if (!surf->bos[i]) {
832                                         TBM_ERR("fail to tbm_bo_alloc_with_surface idx:%d\n", i);
833                                         goto alloc_bo_fail;
834                                 /* LCOV_EXCL_STOP */
835                                 }
836                         } else {
837                                 surf->bos[i] = tbm_bo_alloc(bufmgr, bo_size, flags);
838                                 if (!surf->bos[i]) {
839                                         TBM_ERR("fail to alloc bo idx:%d\n", i);
840                                         goto alloc_bo_fail;
841                                 }
842                         }
843                 }
844
845                 _tbm_bo_set_surface(surf->bos[i], surf);
846         }
847
848         TBM_TRACE_SURFACE_INTERNAL("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
849                         _tbm_surface_internal_format_to_str(format), flags, surf);
850
851         LIST_INITHEAD(&surf->user_data_list);
852         LIST_INITHEAD(&surf->debug_data_list);
853
854         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
855
856         _tbm_surface_mutex_unlock();
857
858         return surf;
859
860 /* LCOV_EXCL_START */
861 alloc_bo_fail:
862         for (j = 0; j < i; j++) {
863                 if (surf->bos[j])
864                         tbm_bo_unref(surf->bos[j]);
865         }
866 query_plane_data_fail:
867 bpp_fail:
868 num_planes_fail:
869         free(surf);
870 alloc_surf_fail:
871 check_valid_fail:
872         if (bufmgr_initialized && bufmgr) {
873                 LIST_DELINIT(&bufmgr->surf_list);
874                 _deinit_surface_bufmgr();
875         }
876         _tbm_surface_mutex_unlock();
877
878         TBM_ERR("error: width(%d) height(%d) format(%s) flags(%d)\n",
879                         width, height,
880                         _tbm_surface_internal_format_to_str(format), flags);
881 /* LCOV_EXCL_STOP */
882
883         return NULL;
884 }
885
886 tbm_surface_h
887 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
888                                      tbm_bo *bos, int num)
889 {
890         struct _tbm_bufmgr *bufmgr;
891         struct _tbm_surface *surf = NULL;
892         int i;
893         bool bufmgr_initialized = false;
894
895         _tbm_surface_mutex_lock();
896         _tbm_set_last_result(TBM_ERROR_NONE);
897
898         TBM_SURFACE_RETURN_VAL_IF_FAIL(bos, NULL);
899         TBM_SURFACE_RETURN_VAL_IF_FAIL(info, NULL);
900         TBM_SURFACE_RETURN_VAL_IF_FAIL(info->num_planes > 0, NULL);
901         TBM_SURFACE_RETURN_VAL_IF_FAIL(num > 0, NULL);
902         TBM_SURFACE_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
903
904         if (!g_surface_bufmgr) {
905                 _init_surface_bufmgr();
906                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
907                 bufmgr_initialized = true;
908         }
909
910         bufmgr = g_surface_bufmgr;
911         if (!TBM_BUFMGR_IS_VALID(bufmgr)) {
912                 TBM_ERR("fail to validate the Bufmgr.\n");
913                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
914                 goto check_valid_fail;
915         }
916
917         surf = calloc(1, sizeof(struct _tbm_surface));
918         if (!surf) {
919                 /* LCOV_EXCL_START */
920                 TBM_ERR("fail to allocate struct _tbm_surface.\n");
921                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
922                 goto alloc_surf_fail;
923                 /* LCOV_EXCL_STOP */
924         }
925
926         surf->magic = TBM_SURFACE_MAGIC;
927         surf->bufmgr = bufmgr;
928         surf->info.width = info->width;
929         surf->info.height = info->height;
930         surf->info.format = info->format;
931         if (info->bpp > 0)
932                 surf->info.bpp = info->bpp;
933         else {
934                 surf->info.bpp = _tbm_surface_internal_get_bpp(info->format);
935                 if (!surf->info.bpp) {
936                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
937                         goto bpp_fail;
938                 }
939         }
940         surf->info.num_planes = info->num_planes;
941         surf->refcnt = 1;
942
943         /* get size, stride and offset */
944         for (i = 0; i < info->num_planes; i++) {
945                 surf->info.planes[i].offset = info->planes[i].offset;
946                 surf->info.planes[i].stride = info->planes[i].stride;
947
948                 if (info->planes[i].size > 0)
949                         surf->info.planes[i].size = info->planes[i].size;
950                 else {
951                         uint32_t size = 0, offset = 0, stride = 0;
952                         int32_t bo_idx = 0;
953
954                         if (!_tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride, &bo_idx)) {
955                                 TBM_ERR("fail to get plane_data. error(%s)\n", tbm_error_str(tbm_get_last_error()));
956                                 goto plane_data_fail;
957                         }
958                         surf->info.planes[i].size = size;
959                 }
960
961                 if (num == 1)
962                         surf->planes_bo_idx[i] = 0;
963                 else
964                         surf->planes_bo_idx[i] = i;
965         }
966
967         if (info->size > 0) {
968                 surf->info.size = info->size;
969         } else {
970                 surf->info.size = 0;
971                 for (i = 0; i < info->num_planes; i++)
972                         surf->info.size += surf->info.planes[i].size;
973         }
974
975         surf->flags = TBM_BO_DEFAULT;
976
977         /* create only one bo */
978         surf->num_bos = num;
979         for (i = 0; i < num; i++) {
980                 if (bos[i] == NULL) {
981                         TBM_ERR("bos[%d] is null.\n", i);
982                         _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
983                         goto check_bo_fail;
984                 }
985
986                 surf->bos[i] = tbm_bo_ref(bos[i]);
987                 _tbm_bo_set_surface(bos[i], surf);
988         }
989
990         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u) height(%u) format(%s) bo_num(%d)\n", surf,
991                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
992
993         LIST_INITHEAD(&surf->user_data_list);
994         LIST_INITHEAD(&surf->debug_data_list);
995
996         LIST_ADD(&surf->item_link, &bufmgr->surf_list);
997
998         _tbm_surface_mutex_unlock();
999
1000         return surf;
1001
1002 /* LCOV_EXCL_START */
1003 check_bo_fail:
1004 plane_data_fail:
1005 bpp_fail:
1006         for (i = 0; i < num; i++) {
1007                 if (surf->bos[i])
1008                         tbm_bo_unref(surf->bos[i]);
1009         }
1010         free(surf);
1011 alloc_surf_fail:
1012 check_valid_fail:
1013         if (bufmgr_initialized && bufmgr) {
1014                 LIST_DELINIT(&bufmgr->surf_list);
1015                 _deinit_surface_bufmgr();
1016         }
1017         _tbm_surface_mutex_unlock();
1018
1019         TBM_ERR("error: width(%u) height(%u) format(%s) bo_num(%d)\n",
1020                         info->width, info->height,
1021                         _tbm_surface_internal_format_to_str(info->format), num);
1022 /* LCOV_EXCL_STOP */
1023
1024         return NULL;
1025 }
1026
1027 void
1028 tbm_surface_internal_destroy(tbm_surface_h surface)
1029 {
1030         _tbm_surface_mutex_lock();
1031         _tbm_set_last_result(TBM_ERROR_NONE);
1032
1033         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1034
1035         surface->refcnt--;
1036
1037         if (surface->refcnt > 0) {
1038                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1039                 _tbm_surface_mutex_unlock();
1040                 return;
1041         }
1042
1043         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1044
1045         if (surface->refcnt == 0)
1046                 _tbm_surface_internal_destroy(surface);
1047
1048         _tbm_surface_mutex_unlock();
1049 }
1050
1051 void
1052 tbm_surface_internal_ref(tbm_surface_h surface)
1053 {
1054         _tbm_surface_mutex_lock();
1055         _tbm_set_last_result(TBM_ERROR_NONE);
1056
1057         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1058
1059         surface->refcnt++;
1060
1061         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1062
1063         _tbm_surface_mutex_unlock();
1064 }
1065
1066 void
1067 tbm_surface_internal_unref(tbm_surface_h surface)
1068 {
1069         _tbm_surface_mutex_lock();
1070         _tbm_set_last_result(TBM_ERROR_NONE);
1071
1072         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1073
1074         surface->refcnt--;
1075
1076         if (surface->refcnt > 0) {
1077                 TBM_TRACE_SURFACE_INTERNAL("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
1078                 _tbm_surface_mutex_unlock();
1079                 return;
1080         }
1081
1082         TBM_TRACE_SURFACE_INTERNAL("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
1083
1084         if (surface->refcnt == 0)
1085                 _tbm_surface_internal_destroy(surface);
1086
1087         _tbm_surface_mutex_unlock();
1088 }
1089
1090 int
1091 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
1092 {
1093         struct _tbm_surface *surf;
1094         int num;
1095
1096         _tbm_surface_mutex_lock();
1097         _tbm_set_last_result(TBM_ERROR_NONE);
1098
1099         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1100
1101         surf = (struct _tbm_surface *)surface;
1102         num = surf->num_bos;
1103
1104         if (!num)
1105                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1106
1107         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) num_bos(%d)\n", surface, num);
1108
1109         _tbm_surface_mutex_unlock();
1110
1111         return num;
1112 }
1113
1114 tbm_bo
1115 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
1116 {
1117         struct _tbm_surface *surf;
1118         tbm_bo bo;
1119
1120         _tbm_surface_mutex_lock();
1121         _tbm_set_last_result(TBM_ERROR_NONE);
1122
1123         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
1124         TBM_SURFACE_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
1125
1126         surf = (struct _tbm_surface *)surface;
1127         bo = surf->bos[bo_idx];
1128
1129         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
1130
1131         _tbm_surface_mutex_unlock();
1132
1133         return bo;
1134 }
1135
1136 unsigned int
1137 tbm_surface_internal_get_size(tbm_surface_h surface)
1138 {
1139         struct _tbm_surface *surf;
1140         unsigned int size;
1141
1142         _tbm_surface_mutex_lock();
1143         _tbm_set_last_result(TBM_ERROR_NONE);
1144
1145         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1146
1147         surf = (struct _tbm_surface *)surface;
1148         size = surf->info.size;
1149
1150         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) size(%u)\n", surface, size);
1151
1152         _tbm_surface_mutex_unlock();
1153
1154         return size;
1155 }
1156
1157 int
1158 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
1159                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
1160 {
1161         struct _tbm_surface *surf;
1162
1163         _tbm_surface_mutex_lock();
1164         _tbm_set_last_result(TBM_ERROR_NONE);
1165
1166         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1167         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1168
1169         surf = (struct _tbm_surface *)surface;
1170
1171         if (plane_idx >= surf->info.num_planes) {
1172                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
1173                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1174                 _tbm_surface_mutex_unlock();
1175                 return 0;
1176         }
1177
1178         if (size)
1179                 *size = surf->info.planes[plane_idx].size;
1180
1181         if (offset)
1182                 *offset = surf->info.planes[plane_idx].offset;
1183
1184         if (pitch)
1185                 *pitch = surf->info.planes[plane_idx].stride;
1186
1187         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) size(%u) offset(%u) pitch(%u)\n", surface, plane_idx,
1188                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1189                                 surf->info.planes[plane_idx].stride);
1190
1191         _tbm_surface_mutex_unlock();
1192
1193         return 1;
1194 }
1195
1196 int
1197 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1198                               tbm_surface_info_s *info, int map)
1199 {
1200         struct _tbm_surface *surf;
1201         tbm_bo_handle bo_handles[4];
1202         int num_bos = 0;
1203         tbm_bo bos[4];
1204         int planes_bo_idx[TBM_SURF_PLANE_MAX];
1205         int i, j;
1206
1207         _tbm_surface_mutex_lock();
1208         _tbm_set_last_result(TBM_ERROR_NONE);
1209
1210         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1211
1212         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1213
1214         surf = (struct _tbm_surface *)surface;
1215
1216         memset(info, 0x00, sizeof(tbm_surface_info_s));
1217         info->width = surf->info.width;
1218         info->height = surf->info.height;
1219         info->format = surf->info.format;
1220         info->bpp = surf->info.bpp;
1221         info->size = surf->info.size;
1222         info->num_planes = surf->info.num_planes;
1223
1224         for (i = 0; i < surf->info.num_planes; i++) {
1225                 info->planes[i].size = surf->info.planes[i].size;
1226                 info->planes[i].offset = surf->info.planes[i].offset;
1227                 info->planes[i].stride = surf->info.planes[i].stride;
1228                 planes_bo_idx[i] = surf->planes_bo_idx[i];
1229         }
1230
1231         for (i = 0; i < surf->num_bos; i++)
1232                 bos[i] = surf->bos[i];
1233
1234         num_bos = surf->num_bos;
1235
1236         if (map == 1) {
1237                 _tbm_surface_mutex_unlock();
1238                 for (i = 0; i < num_bos; i++) {
1239                         bo_handles[i] = tbm_bo_map(bos[i], TBM_DEVICE_CPU, opt);
1240                         if (bo_handles[i].ptr == NULL) {
1241                                 for (j = 0; j < i; j++)
1242                                         tbm_bo_unmap(bos[j]);
1243
1244                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1245                                 return 0;
1246                         }
1247                 }
1248                 _tbm_surface_mutex_lock();
1249         } else {
1250                 for (i = 0; i < num_bos; i++) {
1251                         bo_handles[i] = tbm_bo_get_handle(bos[i], TBM_DEVICE_CPU);
1252                         if (bo_handles[i].ptr == NULL) {
1253                                 TBM_ERR("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1254                                 _tbm_surface_mutex_unlock();
1255                                 return 0;
1256                         }
1257                 }
1258         }
1259
1260         for (i = 0; i < info->num_planes; i++) {
1261                 if (bo_handles[planes_bo_idx[i]].ptr)
1262                         info->planes[i].ptr = bo_handles[planes_bo_idx[i]].ptr + info->planes[i].offset;
1263         }
1264
1265         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1266
1267         _tbm_surface_mutex_unlock();
1268
1269         return 1;
1270 }
1271
1272 void
1273 tbm_surface_internal_unmap(tbm_surface_h surface)
1274 {
1275         struct _tbm_surface *surf;
1276         int i;
1277
1278         _tbm_surface_mutex_lock();
1279         _tbm_set_last_result(TBM_ERROR_NONE);
1280
1281         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1282
1283         surf = (struct _tbm_surface *)surface;
1284
1285         for (i = 0; i < surf->num_bos; i++)
1286                 tbm_bo_unmap(surf->bos[i]);
1287
1288         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p)\n", surface);
1289
1290         _tbm_surface_mutex_unlock();
1291 }
1292
1293 unsigned int
1294 tbm_surface_internal_get_width(tbm_surface_h surface)
1295 {
1296         struct _tbm_surface *surf;
1297         unsigned int width;
1298
1299         _tbm_surface_mutex_lock();
1300         _tbm_set_last_result(TBM_ERROR_NONE);
1301
1302         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1303
1304         surf = (struct _tbm_surface *)surface;
1305         width = surf->info.width;
1306
1307         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) width(%u)\n", surface, width);
1308
1309         _tbm_surface_mutex_unlock();
1310
1311         return width;
1312 }
1313
1314 unsigned int
1315 tbm_surface_internal_get_height(tbm_surface_h surface)
1316 {
1317         struct _tbm_surface *surf;
1318         unsigned int height;
1319
1320         _tbm_surface_mutex_lock();
1321         _tbm_set_last_result(TBM_ERROR_NONE);
1322
1323         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1324
1325         surf = (struct _tbm_surface *)surface;
1326         height = surf->info.height;
1327
1328         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) height(%u)\n", surface, height);
1329
1330         _tbm_surface_mutex_unlock();
1331
1332         return height;
1333
1334 }
1335
1336 tbm_format
1337 tbm_surface_internal_get_format(tbm_surface_h surface)
1338 {
1339         struct _tbm_surface *surf;
1340         tbm_format format;
1341
1342         _tbm_surface_mutex_lock();
1343         _tbm_set_last_result(TBM_ERROR_NONE);
1344
1345         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1346
1347         surf = (struct _tbm_surface *)surface;
1348         format = surf->info.format;
1349
1350         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1351
1352         _tbm_surface_mutex_unlock();
1353
1354         return format;
1355 }
1356
1357 int
1358 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1359 {
1360         struct _tbm_surface *surf;
1361         int bo_idx;
1362
1363         _tbm_surface_mutex_lock();
1364         _tbm_set_last_result(TBM_ERROR_NONE);
1365
1366         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1367         TBM_SURFACE_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1368
1369         surf = (struct _tbm_surface *)surface;
1370         bo_idx = surf->planes_bo_idx[plane_idx];
1371
1372         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1373
1374         _tbm_surface_mutex_unlock();
1375
1376         return bo_idx;
1377 }
1378
1379 int
1380 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1381                                    tbm_data_free data_free_func)
1382 {
1383         tbm_user_data *data;
1384
1385         _tbm_surface_mutex_lock();
1386         _tbm_set_last_result(TBM_ERROR_NONE);
1387
1388         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1389
1390         /* check if the data according to the key exist if so, return false. */
1391         data = user_data_lookup(&surface->user_data_list, key);
1392         if (data) {
1393                 TBM_TRACE_SURFACE_INTERNAL("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1394                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1395                 _tbm_surface_mutex_unlock();
1396                 return 0;
1397         }
1398
1399         data = user_data_create(key, data_free_func);
1400         if (!data) {
1401                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1402                 _tbm_surface_mutex_unlock();
1403                 return 0;
1404         }
1405
1406         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1407
1408         LIST_ADD(&data->item_link, &surface->user_data_list);
1409
1410         _tbm_surface_mutex_unlock();
1411
1412         return 1;
1413 }
1414
1415 int
1416 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1417                                    void *data)
1418 {
1419         tbm_user_data *old_data;
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         old_data = user_data_lookup(&surface->user_data_list, key);
1427         if (!old_data) {
1428                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1429                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1430                 _tbm_surface_mutex_unlock();
1431                 return 0;
1432         }
1433
1434         if (old_data->data && old_data->free_func)
1435                 old_data->free_func(old_data->data);
1436
1437         old_data->data = data;
1438
1439         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1440
1441         _tbm_surface_mutex_unlock();
1442
1443         return 1;
1444 }
1445
1446 int
1447 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1448                                    void **data)
1449 {
1450         tbm_user_data *old_data;
1451
1452         _tbm_surface_mutex_lock();
1453         _tbm_set_last_result(TBM_ERROR_NONE);
1454
1455         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1456
1457         if (!data) {
1458                 TBM_ERR("error: tbm_surface(%p) key(%lu)\n", surface, key);
1459                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1460                 _tbm_surface_mutex_unlock();
1461                 return 0;
1462         }
1463         *data = NULL;
1464
1465         old_data = user_data_lookup(&surface->user_data_list, key);
1466         if (!old_data) {
1467                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1468                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1469                 _tbm_surface_mutex_unlock();
1470                 return 0;
1471         }
1472
1473         *data = old_data->data;
1474
1475         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1476
1477         _tbm_surface_mutex_unlock();
1478
1479         return 1;
1480 }
1481
1482 int
1483 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1484                                       unsigned long key)
1485 {
1486         tbm_user_data *old_data = (void *)0;
1487
1488         _tbm_surface_mutex_lock();
1489         _tbm_set_last_result(TBM_ERROR_NONE);
1490
1491         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1492
1493         old_data = user_data_lookup(&surface->user_data_list, key);
1494         if (!old_data) {
1495                 TBM_TRACE_SURFACE_INTERNAL("error: tbm_surface(%p) key(%lu)\n", surface, key);
1496                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
1497                 _tbm_surface_mutex_unlock();
1498                 return 0;
1499         }
1500
1501         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1502
1503         user_data_delete(old_data);
1504
1505         _tbm_surface_mutex_unlock();
1506
1507         return 1;
1508 }
1509
1510 /* LCOV_EXCL_START */
1511 unsigned int
1512 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1513 {
1514         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1515
1516         return surface->debug_pid;
1517 }
1518
1519 void
1520 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1521 {
1522         _tbm_surface_mutex_lock();
1523         _tbm_set_last_result(TBM_ERROR_NONE);
1524
1525         TBM_SURFACE_RETURN_IF_FAIL(_tbm_surface_internal_is_valid(surface));
1526
1527         surface->debug_pid = pid;
1528
1529         _tbm_surface_mutex_unlock();
1530 }
1531
1532 static tbm_surface_debug_data *
1533 _tbm_surface_internal_debug_data_create(char *key, char *value)
1534 {
1535         tbm_surface_debug_data *debug_data = NULL;
1536
1537         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1538         if (!debug_data) {
1539                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
1540                 TBM_ERR("fail to allocate the debug_data.");
1541                 return NULL;
1542         }
1543
1544         if (key) debug_data->key = strdup(key);
1545         if (value) debug_data->value = strdup(value);
1546
1547         return debug_data;
1548 }
1549
1550 static void
1551 _tbm_surface_internal_debug_data_value_update(tbm_surface_debug_data *debug_data, char *value)
1552 {
1553         if (!debug_data->value && !value)
1554                 return;
1555
1556         if (debug_data->value && value && !strncmp(debug_data->value, value, strlen(debug_data->value)))
1557                 return;
1558
1559         if (debug_data->value)
1560                 free(debug_data->value);
1561
1562         if (value)
1563                 debug_data->value = strdup(value);
1564         else
1565                 debug_data->value = NULL;
1566 }
1567
1568 static tbm_surface_debug_data *
1569 _tbm_surface_internal_debug_data_find(struct list_head *list, char *key)
1570 {
1571         tbm_surface_debug_data *debug_data = NULL;
1572
1573         if (LIST_IS_EMPTY(list))
1574                 return NULL;
1575
1576         LIST_FOR_EACH_ENTRY(debug_data, list, item_link) {
1577                 if (!strncmp(debug_data->key, key, strlen(debug_data->key)))
1578                         return debug_data;
1579         }
1580
1581         return NULL;
1582 }
1583
1584 int
1585 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1586 {
1587         tbm_surface_debug_data *debug_data = NULL;
1588         tbm_bufmgr bufmgr = NULL;
1589
1590         _tbm_surface_mutex_lock();
1591         _tbm_set_last_result(TBM_ERROR_NONE);
1592
1593         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
1594         TBM_SURFACE_RETURN_VAL_IF_FAIL(key, 0);
1595
1596         bufmgr = surface->bufmgr;
1597
1598         TBM_SURFACE_RETURN_VAL_IF_FAIL(bufmgr, 0);
1599
1600         debug_data = _tbm_surface_internal_debug_data_find(&surface->debug_data_list, key);
1601         if (debug_data) {
1602                 _tbm_surface_internal_debug_data_value_update(debug_data, value);
1603         } else {
1604                 debug_data = _tbm_surface_internal_debug_data_create(key, value);
1605                 if (!debug_data) {
1606                         TBM_ERR("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1607                         _tbm_surface_mutex_unlock();
1608                         return 0;
1609                 }
1610
1611                 LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1612         }
1613
1614         /* add new debug key to list */
1615         debug_data = _tbm_surface_internal_debug_data_find(&bufmgr->debug_key_list, key);
1616         if (!debug_data) {
1617                 debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1618                 if (debug_data)
1619                         LIST_ADDTAIL(&debug_data->item_link, &bufmgr->debug_key_list);
1620         }
1621
1622         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1623
1624         _tbm_surface_mutex_unlock();
1625
1626         return 1;
1627 }
1628
1629 char *
1630 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1631 {
1632         tbm_surface_debug_data *old_data = NULL;
1633
1634         TBM_SURFACE_RETURN_VAL_IF_FAIL(surface, NULL);
1635
1636         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1637                 LIST_FOR_EACH_ENTRY(old_data, &surface->debug_data_list, item_link) {
1638                         if (!strcmp(old_data->key, key))
1639                                 return old_data->value;
1640                 }
1641         }
1642
1643         return NULL;
1644 }
1645
1646 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1647 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1648
1649 struct _tbm_surface_dump_buf_info {
1650         int index;
1651         tbm_bo bo;
1652         int size;
1653         int dirty;
1654         int dirty_shm;
1655         int shm_stride;
1656         int shm_h;
1657         char name[1024];
1658
1659         tbm_surface_info_s info;
1660
1661         struct list_head link;
1662 };
1663
1664 struct _tbm_surface_dump_info {
1665         char *path;  // copy???
1666         int dump_max;
1667         int count;
1668         struct list_head *link;
1669         struct list_head surface_list; /* link of surface */
1670 };
1671
1672 static tbm_surface_dump_info *g_dump_info = NULL;
1673 static const char *dump_postfix[2] = {"png", "yuv"};
1674 static double scale_factor;
1675
1676 static void
1677 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1,
1678                                 void *data2, int size2, void *data3, int size3)
1679 {
1680         FILE *fp;
1681         unsigned int *blocks;
1682
1683         if (_tbm_surface_check_file_is_symbolic_link(file))
1684                 TBM_ERR("%s is symbolic link\n", file);
1685
1686         fp = fopen(file, "w+");
1687         TBM_RETURN_IF_FAIL(fp != NULL);
1688
1689         blocks = (unsigned int *)data1;
1690         fwrite(blocks, 1, size1, fp);
1691
1692         if (size2 > 0) {
1693                 blocks = (unsigned int *)data2;
1694                 fwrite(blocks, 1, size2, fp);
1695         }
1696
1697         if (size3 > 0) {
1698                 blocks = (unsigned int *)data3;
1699                 fwrite(blocks, 1, size3, fp);
1700         }
1701
1702         fclose(fp);
1703 }
1704
1705 static void
1706 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width, int height, int stride, int format)
1707 {
1708         unsigned int *blocks = (unsigned int *)data;
1709         FILE *fp;
1710         int pixel_size;
1711         png_bytep *row_pointers;
1712         int depth = 8, y;
1713
1714         if (_tbm_surface_check_file_is_symbolic_link(file))
1715                 TBM_ERR("%s is symbolic link\n", file);
1716
1717         fp = fopen(file, "wb");
1718         TBM_RETURN_IF_FAIL(fp != NULL);
1719
1720         png_structp pPngStruct = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1721                                                         NULL, NULL, NULL);
1722         if (!pPngStruct) {
1723                 TBM_ERR("fail to create a png write structure.\n");
1724                 fclose(fp);
1725                 return;
1726         }
1727
1728         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1729         if (!pPngInfo) {
1730                 TBM_ERR("fail to create a png info structure.\n");
1731                 png_destroy_write_struct(&pPngStruct, NULL);
1732                 fclose(fp);
1733                 return;
1734         }
1735
1736         if (setjmp(png_jmpbuf(pPngStruct))) {
1737                 /* if png has problem of writing the file, we get here */
1738                 TBM_ERR("fail to write png file.\n");
1739                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1740                 fclose(fp);
1741                 return;
1742         }
1743
1744         png_init_io(pPngStruct, fp);
1745         if (format == TBM_FORMAT_XRGB8888) {
1746                 pixel_size = 3;
1747                 png_set_IHDR(pPngStruct,
1748                                 pPngInfo,
1749                                 width,
1750                                 height,
1751                                 depth,
1752                                 PNG_COLOR_TYPE_RGB,
1753                                 PNG_INTERLACE_NONE,
1754                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1755         } else {
1756                 pixel_size = 4;
1757                 png_set_IHDR(pPngStruct,
1758                                 pPngInfo,
1759                                 width,
1760                                 height,
1761                                 depth,
1762                                 PNG_COLOR_TYPE_RGBA,
1763                                 PNG_INTERLACE_NONE,
1764                                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1765         }
1766
1767         png_set_bgr(pPngStruct);
1768         png_write_info(pPngStruct, pPngInfo);
1769
1770         row_pointers = png_malloc(pPngStruct, height * sizeof(png_byte *));
1771         if (!row_pointers) {
1772                 TBM_ERR("fail to allocate the png row_pointers.\n");
1773                 png_destroy_write_struct(&pPngStruct, &pPngInfo);
1774                 fclose(fp);
1775                 return;
1776         }
1777
1778         for (y = 0; y < height; ++y) {
1779                 png_bytep row;
1780                 int x = 0;
1781
1782                 row = png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1783                 if (!row) {
1784                         TBM_ERR("fail to allocate the png row.\n");
1785                         for (x = 0; x < y; x++)
1786                                 png_free(pPngStruct, row_pointers[x]);
1787                         png_free(pPngStruct, row_pointers);
1788                         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1789                         fclose(fp);
1790                         return;
1791                 }
1792                 row_pointers[y] = (png_bytep)row;
1793
1794                 for (x = 0; x < width; ++x) {
1795                         unsigned int curBlock = blocks[(y * (stride >> 2)) + x];
1796
1797                         if (pixel_size == 3) { // XRGB8888
1798                                 row[x * pixel_size] = (curBlock & 0xFF);
1799                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1800                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1801                         } else { // ARGB8888
1802                                 row[x * pixel_size] = (curBlock & 0xFF);
1803                                 row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1804                                 row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1805                                 row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1806                         }
1807                 }
1808         }
1809
1810         png_write_image(pPngStruct, row_pointers);
1811         png_write_end(pPngStruct, pPngInfo);
1812
1813         for (y = 0; y < height; y++)
1814                 png_free(pPngStruct, row_pointers[y]);
1815         png_free(pPngStruct, row_pointers);
1816
1817         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1818
1819         fclose(fp);
1820 }
1821
1822 void
1823 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1824 {
1825         TBM_RETURN_IF_FAIL(path != NULL);
1826         TBM_RETURN_IF_FAIL(w > 0);
1827         TBM_RETURN_IF_FAIL(h > 0);
1828         TBM_RETURN_IF_FAIL(count > 0);
1829
1830         tbm_surface_dump_buf_info *buf_info = NULL;
1831         tbm_surface_h tbm_surface;
1832         tbm_surface_info_s info;
1833         int buffer_size, i;
1834
1835         /* check running */
1836         if (g_dump_info) {
1837                 TBM_WRN("waring already running the tbm_surface_internal_dump.\n");
1838                 return;
1839         }
1840
1841         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1842         TBM_RETURN_IF_FAIL(g_dump_info);
1843
1844         LIST_INITHEAD(&g_dump_info->surface_list);
1845         g_dump_info->count = 0;
1846         g_dump_info->dump_max = count;
1847
1848         /* get buffer size */
1849         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1850         if (tbm_surface == NULL) {
1851                 TBM_ERR("tbm_surface_create fail\n");
1852                 free(g_dump_info);
1853                 g_dump_info = NULL;
1854                 return;
1855         }
1856
1857         if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &info)) {
1858                 TBM_ERR("tbm_surface_get_info fail\n");
1859                 tbm_surface_destroy(tbm_surface);
1860                 free(g_dump_info);
1861                 g_dump_info = NULL;
1862                 return;
1863         }
1864         buffer_size = info.size;
1865         tbm_surface_destroy(tbm_surface);
1866
1867         /* create dump lists */
1868         for (i = 0; i < count; i++) {
1869                 tbm_bo bo = NULL;
1870
1871                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1872                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1873
1874                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1875                 if (bo == NULL) {
1876                         TBM_ERR("fail to allocate the tbm_bo[%d]\n", i);
1877                         free(buf_info);
1878                         goto fail;
1879                 }
1880
1881                 buf_info->index = i;
1882                 buf_info->bo = bo;
1883                 buf_info->size = buffer_size;
1884
1885                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1886         }
1887
1888         g_dump_info->path = path;
1889         g_dump_info->link = &g_dump_info->surface_list;
1890
1891         scale_factor = 0.0;
1892
1893         TBM_INFO("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1894
1895         return;
1896
1897 fail:
1898         /* free resources */
1899         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1900                 tbm_surface_dump_buf_info *tmp;
1901
1902                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1903                         tbm_bo_unref(buf_info->bo);
1904                         LIST_DEL(&buf_info->link);
1905                         free(buf_info);
1906                 }
1907         }
1908
1909         TBM_ERR("Dump Start fail.. path:%s\n", g_dump_info->path);
1910
1911         free(g_dump_info);
1912         g_dump_info = NULL;
1913
1914         return;
1915 }
1916
1917 void
1918 tbm_surface_internal_dump_with_scale_start(char *path, int w, int h, int count, double scale)
1919 {
1920         if (scale > 0.0) {
1921                 w *= scale;
1922                 h *= scale;
1923         }
1924
1925         tbm_surface_internal_dump_start(path, w, h, count);
1926         scale_factor = scale;
1927 }
1928
1929 void
1930 tbm_surface_internal_dump_end(void)
1931 {
1932         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1933         tbm_bo_handle bo_handle;
1934
1935         if (!g_dump_info)
1936                 return;
1937
1938         if (LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1939                 free(g_dump_info);
1940                 g_dump_info = NULL;
1941                 return;
1942         }
1943
1944         /* make files */
1945         LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1946                 char file[2048];
1947
1948                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1949                 if (bo_handle.ptr == NULL) {
1950                         tbm_bo_unref(buf_info->bo);
1951                         LIST_DEL(&buf_info->link);
1952                         free(buf_info);
1953                         continue;
1954                 }
1955
1956                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1957                 TBM_INFO("Dump File.. %s generated.\n", file);
1958
1959                 if (buf_info->dirty) {
1960                         void *ptr1 = NULL, *ptr2 = NULL;
1961
1962                         switch (buf_info->info.format) {
1963                         case TBM_FORMAT_ARGB8888:
1964                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1965                                                         buf_info->info.planes[0].stride >> 2,
1966                                                         buf_info->info.height,
1967                                                         buf_info->info.planes[0].stride,
1968                                                         TBM_FORMAT_ARGB8888);
1969                                 break;
1970                         case TBM_FORMAT_XRGB8888:
1971                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1972                                                         buf_info->info.planes[0].stride >> 2,
1973                                                         buf_info->info.height,
1974                                                         buf_info->info.planes[0].stride,
1975                                                         TBM_FORMAT_XRGB8888);
1976                                 break;
1977                         case TBM_FORMAT_YVU420:
1978                         case TBM_FORMAT_YUV420:
1979                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1980                                 ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1981                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1982                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1983                                                         ptr1,
1984                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1985                                                         ptr2,
1986                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1987                                 break;
1988                         case TBM_FORMAT_NV12:
1989                         case TBM_FORMAT_NV21:
1990                                 ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1991                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1992                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1993                                                         ptr1,
1994                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1995                                                         NULL, 0);
1996                                 break;
1997                         case TBM_FORMAT_YUYV:
1998                         case TBM_FORMAT_UYVY:
1999                                 _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
2000                                                         buf_info->info.planes[0].stride * buf_info->info.height,
2001                                                         NULL, 0, NULL, 0);
2002                                 break;
2003                         default:
2004                                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
2005                                 break;
2006                         }
2007                 } else if (buf_info->dirty_shm)
2008                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
2009                                                         buf_info->shm_stride >> 2,
2010                                                         buf_info->shm_h,
2011                                                         buf_info->shm_stride, 0);
2012
2013                 tbm_bo_unmap(buf_info->bo);
2014                 tbm_bo_unref(buf_info->bo);
2015                 LIST_DEL(&buf_info->link);
2016                 free(buf_info);
2017         }
2018
2019         free(g_dump_info);
2020         g_dump_info = NULL;
2021
2022         TBM_INFO("Dump End..\n");
2023 }
2024
2025 static pixman_format_code_t
2026 _tbm_surface_internal_pixman_format_get(tbm_format format)
2027 {
2028         switch (format) {
2029         case TBM_FORMAT_ARGB8888:
2030                 return PIXMAN_a8r8g8b8;
2031         case TBM_FORMAT_XRGB8888:
2032                 return PIXMAN_x8r8g8b8;
2033         default:
2034                 return 0;
2035         }
2036
2037         return 0;
2038 }
2039
2040 /**
2041  * This function supports only if a buffer has below formats.
2042  * - TBM_FORMAT_ARGB8888
2043  * - TBM_FORMAT_XRGB8888
2044  */
2045 static tbm_surface_error_e
2046 _tbm_surface_internal_buffer_scale(void *src_ptr, void *dst_ptr,
2047                                                                    int format, int src_stride, int src_w, int src_h,
2048                                                                    int dst_stride, int dst_w, int dst_h)
2049 {
2050         pixman_image_t *src_img = NULL, *dst_img = NULL;
2051         pixman_format_code_t pixman_format;
2052         pixman_transform_t t;
2053         struct pixman_f_transform ft;
2054         double scale_x, scale_y;
2055
2056         TBM_RETURN_VAL_IF_FAIL(src_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2057         TBM_RETURN_VAL_IF_FAIL(dst_ptr != NULL, TBM_SURFACE_ERROR_INVALID_OPERATION);
2058
2059         pixman_format = _tbm_surface_internal_pixman_format_get(format);
2060         TBM_RETURN_VAL_IF_FAIL(pixman_format > 0, TBM_SURFACE_ERROR_INVALID_OPERATION);
2061
2062         /* src */
2063         src_img = pixman_image_create_bits(pixman_format, src_w, src_h,
2064                                                                            (uint32_t*)src_ptr, src_stride);
2065         TBM_GOTO_VAL_IF_FAIL(src_img != NULL, cant_convert);
2066
2067         /* dst */
2068         dst_img = pixman_image_create_bits(pixman_format, dst_w, dst_h,
2069                                                                            (uint32_t*)dst_ptr, dst_stride);
2070         TBM_GOTO_VAL_IF_FAIL(dst_img != NULL, cant_convert);
2071
2072         pixman_f_transform_init_identity(&ft);
2073
2074         scale_x = (double)src_w / dst_w;
2075         scale_y = (double)src_h / dst_h;
2076
2077         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2078         pixman_f_transform_translate(&ft, NULL, 0, 0);
2079         pixman_transform_from_pixman_f_transform(&t, &ft);
2080         pixman_image_set_transform(src_img, &t);
2081
2082         pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img,
2083                                                    0, 0, 0, 0, 0, 0, dst_w, dst_h);
2084
2085         pixman_image_unref(src_img);
2086         pixman_image_unref(dst_img);
2087
2088         return TBM_SURFACE_ERROR_NONE;
2089
2090 cant_convert:
2091         if (src_img)
2092                 pixman_image_unref(src_img);
2093
2094         return TBM_SURFACE_ERROR_INVALID_OPERATION;
2095 }
2096
2097 #define MAX_BOS         4       // This value is came from bos[4] in struct _tbm_surface
2098 #define KEY_LEN         5       // "_XXXX"
2099 #define KEYS_LEN        KEY_LEN * MAX_BOS
2100
2101 static char *_tbm_surface_internal_get_keys(tbm_surface_h surface)
2102 {
2103         char *keys, temp_key[KEY_LEN + 1];
2104         struct _tbm_surface *surf;
2105         int i, num_bos;
2106         tbm_bo bo;
2107
2108         _tbm_surface_mutex_lock();
2109
2110         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), NULL);
2111
2112         surf = (struct _tbm_surface *)surface;
2113
2114         num_bos = surf->num_bos;
2115         if (num_bos > MAX_BOS)
2116                 num_bos = MAX_BOS;
2117
2118         keys = calloc(KEYS_LEN + 1, sizeof(char));
2119         if (!keys) {
2120                 TBM_ERR("Failed to alloc memory");
2121                 _tbm_surface_mutex_unlock();
2122                 return NULL;
2123         }
2124
2125         for (i = 0; i < num_bos; i++) {
2126                 memset(temp_key, 0x00, KEY_LEN + 1);
2127                 bo = surf->bos[i];
2128                 snprintf(temp_key, KEY_LEN, "_%d", tbm_bo_export(bo));
2129                 strncat(keys, temp_key, KEY_LEN + 1);
2130         }
2131
2132         _tbm_surface_mutex_unlock();
2133
2134         return keys;
2135 }
2136
2137 static void _tbm_surface_internal_put_keys(char *keys)
2138 {
2139         if (keys)
2140                 free(keys);
2141 }
2142
2143 void
2144 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
2145 {
2146         TBM_RETURN_IF_FAIL(surface != NULL);
2147         TBM_RETURN_IF_FAIL(type != NULL);
2148
2149         tbm_surface_dump_buf_info *buf_info;
2150         struct list_head *next_link;
2151         tbm_surface_info_s info;
2152         tbm_bo_handle bo_handle;
2153         const char *postfix;
2154         const char *format = NULL;
2155         char *keys;
2156         int ret;
2157
2158         if (!g_dump_info)
2159                 return;
2160
2161         next_link = g_dump_info->link->next;
2162         TBM_RETURN_IF_FAIL(next_link != NULL);
2163
2164         if (next_link == &g_dump_info->surface_list) {
2165                 next_link = next_link->next;
2166                 TBM_RETURN_IF_FAIL(next_link != NULL);
2167         }
2168
2169         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2170         TBM_RETURN_IF_FAIL(buf_info != NULL);
2171
2172         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2173         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
2174
2175         if (scale_factor > 0.0) {
2176                 const int bpp = 4;
2177
2178                 if (info.format != TBM_FORMAT_ARGB8888 && info.format != TBM_FORMAT_XRGB8888) {
2179                         TBM_WRN("Dump with scale skip. unsupported format(%s)\n",
2180                                           _tbm_surface_internal_format_to_str(info.format));
2181                         tbm_surface_unmap(surface);
2182                         return;
2183                 }
2184
2185                 memset(&buf_info->info, 0, sizeof(tbm_surface_info_s));
2186
2187                 buf_info->info.width = info.width * scale_factor;
2188                 buf_info->info.height = info.height * scale_factor;
2189                 buf_info->info.format = info.format;
2190                 buf_info->info.bpp = _tbm_surface_internal_get_bpp(buf_info->info.format);
2191                 if (!buf_info->info.bpp) {
2192                         TBM_ERR("fail to get bpp. error(%s)\n", tbm_error_str(tbm_get_last_error()));
2193                         tbm_surface_unmap(surface);
2194                         return;
2195                 }
2196                 buf_info->info.num_planes = 1;
2197                 buf_info->info.planes[0].stride = buf_info->info.width * bpp;
2198                 buf_info->info.size = buf_info->info.width * buf_info->info.height * bpp;
2199
2200                 if (buf_info->info.size > buf_info->size) {
2201                         TBM_WRN("Dump with scale skip. surface over created buffer size(%u, %d)\n",
2202                                         buf_info->info.size, buf_info->size);
2203                         tbm_surface_unmap(surface);
2204                         return;
2205                 }
2206         } else {
2207                 if (info.size > buf_info->size) {
2208                         TBM_WRN("Dump skip. surface over created buffer size(%u, %d)\n",
2209                                         info.size, buf_info->size);
2210                         tbm_surface_unmap(surface);
2211                         return;
2212                 }
2213
2214                 /* make the file information */
2215                 memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
2216         }
2217
2218         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888) {
2219                 postfix = dump_postfix[0];
2220                 format = _tbm_surface_internal_format_to_str(info.format);
2221         } else
2222                 postfix = dump_postfix[1];
2223
2224         keys = _tbm_surface_internal_get_keys(surface);
2225         if (!keys) {
2226                 TBM_ERR("fail to get keys");
2227                 tbm_surface_unmap(surface);
2228                 return;
2229         }
2230
2231         /* dump */
2232         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2233         if (!bo_handle.ptr) {
2234                 TBM_ERR("fail to map bo");
2235                 _tbm_surface_internal_put_keys(keys);
2236                 tbm_surface_unmap(surface);
2237                 return;
2238         }
2239         memset(bo_handle.ptr, 0x00, buf_info->size);
2240
2241         switch (info.format) {
2242         case TBM_FORMAT_ARGB8888:
2243         case TBM_FORMAT_XRGB8888:
2244                 snprintf(buf_info->name, sizeof(buf_info->name),
2245                                 "%10.3f_%03d%s_%p_%s-%s.%s",
2246                                  _tbm_surface_internal_get_time(),
2247                                  g_dump_info->count++, keys, surface, format, type, postfix);
2248
2249                 if (scale_factor > 0.0) {
2250                         ret = _tbm_surface_internal_buffer_scale(info.planes[0].ptr,
2251                                                                                                          bo_handle.ptr,
2252                                                                                                          buf_info->info.format,
2253                                                                                                          info.planes[0].stride,
2254                                                                                                          info.width, info.height,
2255                                                                                                          buf_info->info.planes[0].stride,
2256                                                                                                          buf_info->info.width,
2257                                                                                                          buf_info->info.height);
2258                         if (ret != TBM_SURFACE_ERROR_NONE) {
2259                                 TBM_ERR("fail to scale buffer");
2260                                 tbm_bo_unmap(buf_info->bo);
2261                                 _tbm_surface_internal_put_keys(keys);
2262                                 tbm_surface_unmap(surface);
2263                                 return;
2264                         }
2265                 } else
2266                         memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
2267                 break;
2268         case TBM_FORMAT_YVU420:
2269         case TBM_FORMAT_YUV420:
2270                 snprintf(buf_info->name, sizeof(buf_info->name),
2271                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2272                                  _tbm_surface_internal_get_time(),
2273                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2274                                 info.height, FOURCC_STR(info.format), postfix);
2275                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2276                 bo_handle.ptr += info.planes[0].stride * info.height;
2277                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2278                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
2279                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
2280                 break;
2281         case TBM_FORMAT_NV12:
2282         case TBM_FORMAT_NV21:
2283                 snprintf(buf_info->name, sizeof(buf_info->name),
2284                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2285                                  _tbm_surface_internal_get_time(),
2286                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2287                                 info.height, FOURCC_STR(info.format), postfix);
2288                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2289                 bo_handle.ptr += info.planes[0].stride * info.height;
2290                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
2291                 break;
2292         case TBM_FORMAT_YUYV:
2293         case TBM_FORMAT_UYVY:
2294                 snprintf(buf_info->name, sizeof(buf_info->name),
2295                                 "%10.3f_%03d%s-%s_%dx%d_%c%c%c%c.%s",
2296                                  _tbm_surface_internal_get_time(),
2297                                  g_dump_info->count++, keys, type, info.planes[0].stride,
2298                                 info.height, FOURCC_STR(info.format), postfix);
2299                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
2300                 break;
2301         default:
2302                 TBM_ERR("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
2303                 tbm_bo_unmap(buf_info->bo);
2304                 _tbm_surface_internal_put_keys(keys);
2305                 tbm_surface_unmap(surface);
2306                 return;
2307         }
2308
2309         tbm_bo_unmap(buf_info->bo);
2310
2311         _tbm_surface_internal_put_keys(keys);
2312
2313         tbm_surface_unmap(surface);
2314
2315         buf_info->dirty = 1;
2316         buf_info->dirty_shm = 0;
2317
2318         if (g_dump_info->count == 1000)
2319                 g_dump_info->count = 0;
2320
2321         g_dump_info->link = next_link;
2322
2323         TBM_INFO("Dump %s \n", buf_info->name);
2324 }
2325
2326 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int stride,
2327                                                 const char *type)
2328 {
2329         TBM_RETURN_IF_FAIL(ptr != NULL);
2330         TBM_RETURN_IF_FAIL(w > 0);
2331         TBM_RETURN_IF_FAIL(h > 0);
2332         TBM_RETURN_IF_FAIL(stride > 0);
2333         TBM_RETURN_IF_FAIL(type != NULL);
2334
2335         tbm_surface_dump_buf_info *buf_info;
2336         struct list_head *next_link;
2337         tbm_bo_handle bo_handle;
2338         int ret, size, dw = 0, dh = 0, dstride = 0;
2339
2340         if (!g_dump_info)
2341                 return;
2342
2343         next_link = g_dump_info->link->next;
2344         TBM_RETURN_IF_FAIL(next_link != NULL);
2345
2346         if (next_link == &g_dump_info->surface_list) {
2347                 next_link = next_link->next;
2348                 TBM_RETURN_IF_FAIL(next_link != NULL);
2349         }
2350
2351         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
2352         TBM_RETURN_IF_FAIL(buf_info != NULL);
2353
2354         if (scale_factor > 0.0) {
2355                 const int bpp = 4;
2356
2357                 dw = w * scale_factor;
2358                 dh = h * scale_factor;
2359                 dstride = dw * bpp;
2360                 size = dstride * dh;
2361         } else
2362                 size = stride * h;
2363
2364         if (size > buf_info->size) {
2365                 TBM_WRN("Dump skip. shm buffer over created buffer size(%d, %d)\n",
2366                                 size, buf_info->size);
2367                 return;
2368         }
2369
2370         /* dump */
2371         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
2372         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
2373
2374         memset(bo_handle.ptr, 0x00, buf_info->size);
2375         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
2376
2377         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
2378                          _tbm_surface_internal_get_time(),
2379                          g_dump_info->count++, type, dump_postfix[0]);
2380         if (scale_factor > 0.0) {
2381                 ret = _tbm_surface_internal_buffer_scale(ptr, bo_handle.ptr,
2382                                                                                                  TBM_FORMAT_ARGB8888, stride,
2383                                                                                                  w, h, dstride, dw, dh);
2384                 if (ret != TBM_SURFACE_ERROR_NONE) {
2385                         TBM_ERR("fail to scale buffer");
2386                         tbm_bo_unmap(buf_info->bo);
2387                         return;
2388                 }
2389                 buf_info->shm_stride = dstride;
2390                 buf_info->shm_h = dh;
2391         } else {
2392                 memcpy(bo_handle.ptr, ptr, size);
2393                 buf_info->shm_stride = stride;
2394                 buf_info->shm_h = h;
2395         }
2396
2397         tbm_bo_unmap(buf_info->bo);
2398
2399         buf_info->dirty = 0;
2400         buf_info->dirty_shm = 1;
2401
2402         if (g_dump_info->count == 1000)
2403                 g_dump_info->count = 0;
2404
2405         g_dump_info->link = next_link;
2406
2407         TBM_INFO("Dump %s \n", buf_info->name);
2408 }
2409
2410 int
2411 tbm_surface_internal_capture_buffer(tbm_surface_h surface, const char *path, const char *name, const char *type)
2412 {
2413         TBM_RETURN_VAL_IF_FAIL(surface != NULL, 0);
2414         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2415         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2416
2417         tbm_surface_info_s info;
2418         const char *postfix;
2419         int ret;
2420         char file[1024];
2421
2422         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
2423         TBM_RETURN_VAL_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE, 0);
2424
2425         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
2426                 postfix = dump_postfix[0];
2427         else
2428                 postfix = dump_postfix[1];
2429
2430         if (strcmp(postfix, type)) {
2431                 TBM_ERR("not support type(%s) %c%c%c%c buffer", type, FOURCC_STR(info.format));
2432                 tbm_surface_unmap(surface);
2433                 return 0;
2434         }
2435
2436         snprintf(file, sizeof(file), "%s/%s.%s", path , name, postfix);
2437
2438         if (!access(file, 0)) {
2439                 TBM_ERR("can't capture  buffer, exist file %s", file);
2440                 tbm_surface_unmap(surface);
2441                 return 0;
2442         }
2443
2444         switch (info.format) {
2445         case TBM_FORMAT_ARGB8888:
2446                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2447                                                         info.width,
2448                                                         info.height,
2449                                                         info.planes[0].stride,
2450                                                         TBM_FORMAT_ARGB8888);
2451                 break;
2452         case TBM_FORMAT_XRGB8888:
2453                 _tbm_surface_internal_dump_file_png(file, info.planes[0].ptr,
2454                                                         info.width,
2455                                                         info.height,
2456                                                         info.planes[0].stride,
2457                                                         TBM_FORMAT_XRGB8888);
2458                 break;
2459         case TBM_FORMAT_YVU420:
2460         case TBM_FORMAT_YUV420:
2461                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2462                                 info.planes[0].stride * info.height,
2463                                 info.planes[1].ptr,
2464                                 info.planes[1].stride * (info.height >> 1),
2465                                 info.planes[2].ptr,
2466                                 info.planes[2].stride * (info.height >> 1));
2467                 break;
2468         case TBM_FORMAT_NV12:
2469         case TBM_FORMAT_NV21:
2470                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2471                                         info.planes[0].stride * info.height,
2472                                         info.planes[1].ptr,
2473                                         info.planes[1].stride * (info.height >> 1),
2474                                         NULL, 0);
2475                 break;
2476         case TBM_FORMAT_YUYV:
2477         case TBM_FORMAT_UYVY:
2478                 _tbm_surface_internal_dump_file_raw(file, info.planes[0].ptr,
2479                                         info.planes[0].stride * info.height,
2480                                         NULL, 0, NULL, 0);
2481                 break;
2482         default:
2483                 TBM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR(info.format));
2484                 tbm_surface_unmap(surface);
2485                 return 0;
2486         }
2487
2488         tbm_surface_unmap(surface);
2489
2490         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2491
2492         return 1;
2493 }
2494
2495 int
2496 tbm_surface_internal_capture_shm_buffer(void *ptr, int w, int h, int stride,
2497                                                 const char *path, const char *name, const char *type)
2498 {
2499         TBM_RETURN_VAL_IF_FAIL(ptr != NULL, 0);
2500         TBM_RETURN_VAL_IF_FAIL(w > 0, 0);
2501         TBM_RETURN_VAL_IF_FAIL(h > 0, 0);
2502         TBM_RETURN_VAL_IF_FAIL(stride > 0, 0);
2503         TBM_RETURN_VAL_IF_FAIL(path != NULL, 0);
2504         TBM_RETURN_VAL_IF_FAIL(name != NULL, 0);
2505
2506         char file[1024];
2507
2508         if (strcmp(dump_postfix[0], type)) {
2509                 TBM_ERR("Not supported type:%s'", type);
2510                 return 0;
2511         }
2512
2513         snprintf(file, sizeof(file), "%s/%s.%s", path , name, dump_postfix[0]);
2514
2515         if (!access(file, 0)) {
2516                 TBM_ERR("can't capture buffer, exist file %sTBM_FORMAT_XRGB8888", file);
2517                 return 0;
2518         }
2519
2520         _tbm_surface_internal_dump_file_png(file, ptr, w, h, stride, 0);
2521
2522         TBM_TRACE_SURFACE_INTERNAL("Capture %s \n", file);
2523
2524         return 1;
2525 }
2526
2527 int
2528 tbm_surface_internal_set_damage(tbm_surface_h surface, int x, int y, int width, int height)
2529 {
2530         struct _tbm_surface *surf;
2531
2532         _tbm_surface_mutex_lock();
2533         _tbm_set_last_result(TBM_ERROR_NONE);
2534
2535         TBM_SURFACE_RETURN_VAL_IF_FAIL(width > 0, 0);
2536         TBM_SURFACE_RETURN_VAL_IF_FAIL(height > 0, 0);
2537         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2538
2539         surf = (struct _tbm_surface *)surface;
2540
2541         surf->damage.x = x;
2542         surf->damage.y = y;
2543         surf->damage.width = width;
2544         surf->damage.height = height;
2545
2546         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2547                                                         surface, x, y, width, height);
2548
2549         _tbm_surface_mutex_unlock();
2550
2551         return 1;
2552 }
2553
2554 int
2555 tbm_surface_internal_get_damage(tbm_surface_h surface, int *x, int *y, int *width, int *height)
2556 {
2557         struct _tbm_surface *surf;
2558
2559         _tbm_surface_mutex_lock();
2560         _tbm_set_last_result(TBM_ERROR_NONE);
2561
2562         TBM_SURFACE_RETURN_VAL_IF_FAIL(_tbm_surface_internal_is_valid(surface), 0);
2563
2564         surf = (struct _tbm_surface *)surface;
2565
2566         if (x) *x = surf->damage.x;
2567         if (y) *y = surf->damage.y;
2568         if (width) *width = surf->damage.width;
2569         if (height) *height = surf->damage.height;
2570
2571         TBM_TRACE_SURFACE_INTERNAL("tbm_surface(%p) x(%d) y(%d) width(%d) height(%d)\n",
2572                                                         surface, surf->damage.x, surf->damage.y, surf->damage.width, surf->damage.height);
2573
2574         _tbm_surface_mutex_unlock();
2575
2576         return 1;
2577 }
2578 /*LCOV_EXCL_STOP*/