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