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