Apply tizen coding rule
[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 #include <stdio.h>
34 #include <time.h>
35 #include <sys/time.h>
36 #include "tbm_bufmgr.h"
37 #include "tbm_bufmgr_int.h"
38 #include "tbm_surface_internal.h"
39 #include "list.h"
40 #include <png.h>
41
42 #define C(b, m)              (((b) >> (m)) & 0xFF)
43 #define B(c, s)              ((((unsigned int)(c)) & 0xff) << (s))
44 #define FOURCC(a, b, c, d)     (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0))
45 #define FOURCC_STR(id)      C(id, 0), C(id, 8), C(id, 16), C(id, 24)
46 #define FOURCC_ID(str)      FOURCC(((char*)str)[0], ((char*)str)[1], ((char*)str)[2], ((char*)str)[3])
47
48 static tbm_bufmgr g_surface_bufmgr;
49 static pthread_mutex_t tbm_surface_lock;
50
51 /* LCOV_EXCL_START */
52 #define USE_REALTIME 1
53
54 static double
55 _tbm_surface_internal_get_time(void)
56 {
57         struct timespec tp;
58         unsigned int time;
59
60 #if USE_REALTIME
61         clock_gettime(CLOCK_REALTIME, &tp);
62 #else /* USE_MONOTONIC */
63         clock_gettime(CLOCK_MONOTONIC, &tp);
64 #endif
65         time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
66
67         return time / 1000.0;
68 }
69
70 static void
71 _tbm_surface_internal_debug_data_delete(tbm_surface_debug_data *debug_data)
72 {
73         LIST_DEL(&debug_data->item_link);
74
75         if (debug_data->key) free(debug_data->key);
76         if (debug_data->value) free(debug_data->value);
77         free(debug_data);
78 }
79
80 char *
81 _tbm_surface_internal_format_to_str(tbm_format format)
82 {
83         switch (format) {
84         case TBM_FORMAT_C8:
85                 return "TBM_FORMAT_C8";
86         case TBM_FORMAT_RGB332:
87                 return "TBM_FORMAT_RGB332";
88         case TBM_FORMAT_BGR233:
89                 return "TBM_FORMAT_BGR233";
90         case TBM_FORMAT_XRGB4444:
91                 return "TBM_FORMAT_XRGB4444";
92         case TBM_FORMAT_XBGR4444:
93                 return "TBM_FORMAT_XBGR4444";
94         case TBM_FORMAT_RGBX4444:
95                 return "TBM_FORMAT_RGBX4444";
96         case TBM_FORMAT_BGRX4444:
97                 return "TBM_FORMAT_BGRX4444";
98         case TBM_FORMAT_ARGB4444:
99                 return "TBM_FORMAT_ARGB4444";
100         case TBM_FORMAT_ABGR4444:
101                 return "TBM_FORMAT_ABGR4444";
102         case TBM_FORMAT_RGBA4444:
103                 return "TBM_FORMAT_RGBA4444";
104         case TBM_FORMAT_BGRA4444:
105                 return "TBM_FORMAT_BGRA4444";
106         case TBM_FORMAT_XRGB1555:
107                 return "TBM_FORMAT_XRGB1555";
108         case TBM_FORMAT_XBGR1555:
109                 return "TBM_FORMAT_XBGR1555";
110         case TBM_FORMAT_RGBX5551:
111                 return "TBM_FORMAT_RGBX5551";
112         case TBM_FORMAT_BGRX5551:
113                 return "TBM_FORMAT_BGRX5551";
114         case TBM_FORMAT_ARGB1555:
115                 return "TBM_FORMAT_ARGB1555";
116         case TBM_FORMAT_ABGR1555:
117                 return "TBM_FORMAT_ABGR1555";
118         case TBM_FORMAT_RGBA5551:
119                 return "TBM_FORMAT_RGBA5551";
120         case TBM_FORMAT_BGRA5551:
121                 return "TBM_FORMAT_BGRA5551";
122         case TBM_FORMAT_RGB565:
123                 return "TBM_FORMAT_RGB565";
124         case TBM_FORMAT_BGR565:
125                 return "TBM_FORMAT_BGR565";
126         case TBM_FORMAT_RGB888:
127                 return "TBM_FORMAT_RGB888";
128         case TBM_FORMAT_BGR888:
129                 return "TBM_FORMAT_BGR888";
130         case TBM_FORMAT_XRGB8888:
131                 return "TBM_FORMAT_XRGB8888";
132         case TBM_FORMAT_XBGR8888:
133                 return "TBM_FORMAT_XBGR8888";
134         case TBM_FORMAT_RGBX8888:
135                 return "TBM_FORMAT_RGBX8888";
136         case TBM_FORMAT_BGRX8888:
137                 return "TBM_FORMAT_BGRX8888";
138         case TBM_FORMAT_ARGB8888:
139                 return "TBM_FORMAT_ARGB8888";
140         case TBM_FORMAT_ABGR8888:
141                 return "TBM_FORMAT_ABGR8888";
142         case TBM_FORMAT_RGBA8888:
143                 return "TBM_FORMAT_RGBA8888";
144         case TBM_FORMAT_BGRA8888:
145                 return "TBM_FORMAT_BGRA8888";
146         case TBM_FORMAT_XRGB2101010:
147                 return "TBM_FORMAT_XRGB2101010";
148         case TBM_FORMAT_XBGR2101010:
149                 return "TBM_FORMAT_XBGR2101010";
150         case TBM_FORMAT_RGBX1010102:
151                 return "TBM_FORMAT_RGBX1010102";
152         case TBM_FORMAT_BGRX1010102:
153                 return "TBM_FORMAT_BGRX1010102";
154         case TBM_FORMAT_ARGB2101010:
155                 return "TBM_FORMAT_ARGB2101010";
156         case TBM_FORMAT_ABGR2101010:
157                 return "TBM_FORMAT_ABGR2101010";
158         case TBM_FORMAT_RGBA1010102:
159                 return "TBM_FORMAT_RGBA1010102";
160         case TBM_FORMAT_BGRA1010102:
161                 return "TBM_FORMAT_BGRA1010102";
162         case TBM_FORMAT_YUYV:
163                 return "TBM_FORMAT_YUYV";
164         case TBM_FORMAT_YVYU:
165                 return "TBM_FORMAT_YVYU";
166         case TBM_FORMAT_UYVY:
167                 return "TBM_FORMAT_UYVY";
168         case TBM_FORMAT_VYUY:
169                 return "TBM_FORMAT_VYUY";
170         case TBM_FORMAT_AYUV:
171                 return "TBM_FORMAT_AYUV";
172         case TBM_FORMAT_NV12:
173                 return "TBM_FORMAT_NV12";
174         case TBM_FORMAT_NV21:
175                 return "TBM_FORMAT_NV21";
176         case TBM_FORMAT_NV16:
177                 return "TBM_FORMAT_NV16";
178         case TBM_FORMAT_NV61:
179                 return "TBM_FORMAT_NV61";
180         case TBM_FORMAT_YUV410:
181                 return "TBM_FORMAT_YUV410";
182         case TBM_FORMAT_YVU410:
183                 return "TBM_FORMAT_YVU410";
184         case TBM_FORMAT_YUV411:
185                 return "TBM_FORMAT_YUV411";
186         case TBM_FORMAT_YVU411:
187                 return "TBM_FORMAT_YVU411";
188         case TBM_FORMAT_YUV420:
189                 return "TBM_FORMAT_YUV420";
190         case TBM_FORMAT_YVU420:
191                 return "TBM_FORMAT_YVU420";
192         case TBM_FORMAT_YUV422:
193                 return "TBM_FORMAT_YUV422";
194         case TBM_FORMAT_YVU422:
195                 return "TBM_FORMAT_YVU422";
196         case TBM_FORMAT_YUV444:
197                 return "TBM_FORMAT_YUV444";
198         case TBM_FORMAT_YVU444:
199                 return "TBM_FORMAT_YVU444";
200         case TBM_FORMAT_NV12MT:
201                 return "TBM_FORMAT_NV12MT";
202         default:
203                 return "unknwon";
204         }
205 }
206 /* LCOV_EXCL_STOP */
207
208 static bool
209 _tbm_surface_mutex_init(void)
210 {
211         static bool tbm_surface_mutex_init = false;
212
213         if (tbm_surface_mutex_init)
214                 return true;
215
216         if (pthread_mutex_init(&tbm_surface_lock, NULL)) {
217                 TBM_LOG_E("fail: tbm_surface mutex init\n");
218                 return false;
219         }
220
221         tbm_surface_mutex_init = true;
222
223         return true;
224 }
225
226 void
227 _tbm_surface_mutex_lock(void)
228 {
229         if (!_tbm_surface_mutex_init())
230                 return;
231
232         pthread_mutex_lock(&tbm_surface_lock);
233 }
234
235 void
236 _tbm_surface_mutex_unlock(void)
237 {
238         pthread_mutex_unlock(&tbm_surface_lock);
239 }
240
241 static void
242 _init_surface_bufmgr(void)
243 {
244         g_surface_bufmgr = tbm_bufmgr_init(-1);
245 }
246
247 static void
248 _deinit_surface_bufmgr(void)
249 {
250         if (!g_surface_bufmgr)
251                 return;
252
253         tbm_bufmgr_deinit(g_surface_bufmgr);
254         g_surface_bufmgr = NULL;
255 }
256
257 static int
258 _tbm_surface_internal_query_plane_data(tbm_surface_h surface,
259                                        int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch, int *bo_idx)
260 {
261         TBM_RETURN_VAL_IF_FAIL(surface, 0);
262         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
263
264         struct _tbm_surface *surf = (struct _tbm_surface *)surface;
265         struct _tbm_bufmgr *mgr = surf->bufmgr;
266         int ret = 0;
267
268         TBM_RETURN_VAL_IF_FAIL(mgr != NULL, 0);
269         TBM_RETURN_VAL_IF_FAIL(surf->info.width > 0, 0);
270         TBM_RETURN_VAL_IF_FAIL(surf->info.height > 0, 0);
271         TBM_RETURN_VAL_IF_FAIL(surf->info.format > 0, 0);
272
273         if (!mgr->backend->surface_get_plane_data)
274                 return 0;
275
276         ret = mgr->backend->surface_get_plane_data(surf->info.width,
277                         surf->info.height, surf->info.format, plane_idx, size, offset, pitch, bo_idx);
278         if (!ret)
279                 return 0;
280
281         return 1;
282 }
283
284 static void
285 _tbm_surface_internal_destroy(tbm_surface_h surface)
286 {
287         int i;
288         tbm_bufmgr bufmgr = surface->bufmgr;
289         tbm_user_data *old_data = NULL, *tmp = NULL;
290         tbm_surface_debug_data *debug_old_data = NULL, *debug_tmp = NULL;
291
292         /* destory the user_data_list */
293         if (!LIST_IS_EMPTY(&surface->user_data_list)) {
294                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->user_data_list, item_link) {
295                         DBG("free user_data\n");
296                         user_data_delete(old_data);
297                 }
298         }
299
300         for (i = 0; i < surface->num_bos; i++) {
301                 surface->bos[i]->surface = NULL;
302
303                 tbm_bo_unref(surface->bos[i]);
304                 surface->bos[i] = NULL;
305         }
306
307         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
308                 LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &surface->debug_data_list, item_link)
309                         _tbm_surface_internal_debug_data_delete(debug_old_data);
310         }
311
312         LIST_DEL(&surface->item_link);
313
314         free(surface);
315         surface = NULL;
316
317         if (LIST_IS_EMPTY(&bufmgr->surf_list)) {
318                 LIST_DELINIT(&bufmgr->surf_list);
319
320                 if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
321                         LIST_FOR_EACH_ENTRY_SAFE(debug_old_data, debug_tmp, &bufmgr->debug_key_list, item_link) {
322                                 _tbm_surface_internal_debug_data_delete(debug_old_data);
323                         }
324                 }
325
326                 _deinit_surface_bufmgr();
327         }
328 }
329
330 static int
331 _tbm_surface_get_max_size(int * w, int * h)
332 {
333         int count = 0;
334         tbm_surface_h surface = NULL, tmp = NULL;
335         tbm_surface_info_s info;
336
337         *w = 0;
338         *h = 0;
339
340         if (g_surface_bufmgr == NULL)
341                 return count;
342
343         if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
344                 LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &g_surface_bufmgr->surf_list, item_link) {
345                         if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
346                                 count++;
347                                 if (*w < info.width) *w = info.width;
348                                 if (*h < info.height) *h = info.height;
349                         }
350                 }
351         }
352
353         return count;
354 }
355
356 int
357 tbm_surface_internal_is_valid(tbm_surface_h surface)
358 {
359         tbm_surface_h old_data = NULL, tmp = NULL;
360
361         if (surface == NULL || g_surface_bufmgr == NULL) {
362                 TBM_TRACE("error: tbm_surface(%p)\n", surface);
363                 return 0;
364         }
365
366         if (!LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
367                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &g_surface_bufmgr->surf_list, item_link) {
368                         if (old_data == surface) {
369                                 TBM_TRACE("tbm_surface(%p)\n", surface);
370                                 return 1;
371                         }
372                 }
373         }
374         TBM_TRACE("error: tbm_surface(%p)\n", surface);
375         return 0;
376 }
377
378 int
379 tbm_surface_internal_query_supported_formats(uint32_t **formats,
380                 uint32_t *num)
381 {
382         struct _tbm_bufmgr *mgr;
383         int ret = 0;
384
385         _tbm_surface_mutex_lock();
386
387         if (!g_surface_bufmgr) {
388                 _init_surface_bufmgr();
389                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
390         }
391
392         mgr = g_surface_bufmgr;
393
394         if (!mgr->backend->surface_supported_format) {
395                 TBM_TRACE("error: tbm_bufmgr(%p)\n", g_surface_bufmgr);
396                 _tbm_surface_mutex_unlock();
397                 return 0;
398         }
399
400         ret = mgr->backend->surface_supported_format(formats, num);
401
402         TBM_TRACE("tbm_bufmgr(%p) format num(%d)\n", g_surface_bufmgr, *num);
403
404         _tbm_surface_mutex_unlock();
405
406         return ret;
407 }
408
409 int
410 tbm_surface_internal_get_num_planes(tbm_format format)
411 {
412         int num_planes = 0;
413
414         switch (format) {
415         case TBM_FORMAT_C8:
416         case TBM_FORMAT_RGB332:
417         case TBM_FORMAT_BGR233:
418         case TBM_FORMAT_XRGB4444:
419         case TBM_FORMAT_XBGR4444:
420         case TBM_FORMAT_RGBX4444:
421         case TBM_FORMAT_BGRX4444:
422         case TBM_FORMAT_ARGB4444:
423         case TBM_FORMAT_ABGR4444:
424         case TBM_FORMAT_RGBA4444:
425         case TBM_FORMAT_BGRA4444:
426         case TBM_FORMAT_XRGB1555:
427         case TBM_FORMAT_XBGR1555:
428         case TBM_FORMAT_RGBX5551:
429         case TBM_FORMAT_BGRX5551:
430         case TBM_FORMAT_ARGB1555:
431         case TBM_FORMAT_ABGR1555:
432         case TBM_FORMAT_RGBA5551:
433         case TBM_FORMAT_BGRA5551:
434         case TBM_FORMAT_RGB565:
435         case TBM_FORMAT_BGR565:
436         case TBM_FORMAT_RGB888:
437         case TBM_FORMAT_BGR888:
438         case TBM_FORMAT_XRGB8888:
439         case TBM_FORMAT_XBGR8888:
440         case TBM_FORMAT_RGBX8888:
441         case TBM_FORMAT_BGRX8888:
442         case TBM_FORMAT_ARGB8888:
443         case TBM_FORMAT_ABGR8888:
444         case TBM_FORMAT_RGBA8888:
445         case TBM_FORMAT_BGRA8888:
446         case TBM_FORMAT_XRGB2101010:
447         case TBM_FORMAT_XBGR2101010:
448         case TBM_FORMAT_RGBX1010102:
449         case TBM_FORMAT_BGRX1010102:
450         case TBM_FORMAT_ARGB2101010:
451         case TBM_FORMAT_ABGR2101010:
452         case TBM_FORMAT_RGBA1010102:
453         case TBM_FORMAT_BGRA1010102:
454         case TBM_FORMAT_YUYV:
455         case TBM_FORMAT_YVYU:
456         case TBM_FORMAT_UYVY:
457         case TBM_FORMAT_VYUY:
458         case TBM_FORMAT_AYUV:
459                 num_planes = 1;
460                 break;
461         case TBM_FORMAT_NV12:
462         case TBM_FORMAT_NV12MT:
463         case TBM_FORMAT_NV21:
464         case TBM_FORMAT_NV16:
465         case TBM_FORMAT_NV61:
466                 num_planes = 2;
467                 break;
468         case TBM_FORMAT_YUV410:
469         case TBM_FORMAT_YVU410:
470         case TBM_FORMAT_YUV411:
471         case TBM_FORMAT_YVU411:
472         case TBM_FORMAT_YUV420:
473         case TBM_FORMAT_YVU420:
474         case TBM_FORMAT_YUV422:
475         case TBM_FORMAT_YVU422:
476         case TBM_FORMAT_YUV444:
477         case TBM_FORMAT_YVU444:
478                 num_planes = 3;
479                 break;
480
481         default:
482                 break;
483         }
484
485         TBM_TRACE("tbm_format(%s) num_planes(%d)\n", _tbm_surface_internal_format_to_str(format), num_planes);
486
487         return num_planes;
488 }
489
490 int
491 tbm_surface_internal_get_bpp(tbm_format format)
492 {
493
494         int bpp = 0;
495
496         switch (format) {
497         case TBM_FORMAT_C8:
498         case TBM_FORMAT_RGB332:
499         case TBM_FORMAT_BGR233:
500                 bpp = 8;
501                 break;
502         case TBM_FORMAT_XRGB4444:
503         case TBM_FORMAT_XBGR4444:
504         case TBM_FORMAT_RGBX4444:
505         case TBM_FORMAT_BGRX4444:
506         case TBM_FORMAT_ARGB4444:
507         case TBM_FORMAT_ABGR4444:
508         case TBM_FORMAT_RGBA4444:
509         case TBM_FORMAT_BGRA4444:
510         case TBM_FORMAT_XRGB1555:
511         case TBM_FORMAT_XBGR1555:
512         case TBM_FORMAT_RGBX5551:
513         case TBM_FORMAT_BGRX5551:
514         case TBM_FORMAT_ARGB1555:
515         case TBM_FORMAT_ABGR1555:
516         case TBM_FORMAT_RGBA5551:
517         case TBM_FORMAT_BGRA5551:
518         case TBM_FORMAT_RGB565:
519         case TBM_FORMAT_BGR565:
520                 bpp = 16;
521                 break;
522         case TBM_FORMAT_RGB888:
523         case TBM_FORMAT_BGR888:
524                 bpp = 24;
525                 break;
526         case TBM_FORMAT_XRGB8888:
527         case TBM_FORMAT_XBGR8888:
528         case TBM_FORMAT_RGBX8888:
529         case TBM_FORMAT_BGRX8888:
530         case TBM_FORMAT_ARGB8888:
531         case TBM_FORMAT_ABGR8888:
532         case TBM_FORMAT_RGBA8888:
533         case TBM_FORMAT_BGRA8888:
534         case TBM_FORMAT_XRGB2101010:
535         case TBM_FORMAT_XBGR2101010:
536         case TBM_FORMAT_RGBX1010102:
537         case TBM_FORMAT_BGRX1010102:
538         case TBM_FORMAT_ARGB2101010:
539         case TBM_FORMAT_ABGR2101010:
540         case TBM_FORMAT_RGBA1010102:
541         case TBM_FORMAT_BGRA1010102:
542         case TBM_FORMAT_YUYV:
543         case TBM_FORMAT_YVYU:
544         case TBM_FORMAT_UYVY:
545         case TBM_FORMAT_VYUY:
546         case TBM_FORMAT_AYUV:
547                 bpp = 32;
548                 break;
549         case TBM_FORMAT_NV12:
550         case TBM_FORMAT_NV12MT:
551         case TBM_FORMAT_NV21:
552                 bpp = 12;
553                 break;
554         case TBM_FORMAT_NV16:
555         case TBM_FORMAT_NV61:
556                 bpp = 16;
557                 break;
558         case TBM_FORMAT_YUV410:
559         case TBM_FORMAT_YVU410:
560                 bpp = 9;
561                 break;
562         case TBM_FORMAT_YUV411:
563         case TBM_FORMAT_YVU411:
564         case TBM_FORMAT_YUV420:
565         case TBM_FORMAT_YVU420:
566                 bpp = 12;
567                 break;
568         case TBM_FORMAT_YUV422:
569         case TBM_FORMAT_YVU422:
570                 bpp = 16;
571                 break;
572         case TBM_FORMAT_YUV444:
573         case TBM_FORMAT_YVU444:
574                 bpp = 24;
575                 break;
576         default:
577                 break;
578         }
579
580         TBM_TRACE("tbm_format(%s) bpp(%d)\n", _tbm_surface_internal_format_to_str(format), bpp);
581
582         return bpp;
583 }
584
585 tbm_surface_h
586 tbm_surface_internal_create_with_flags(int width, int height,
587                                        int format, int flags)
588 {
589         TBM_RETURN_VAL_IF_FAIL(width > 0, NULL);
590         TBM_RETURN_VAL_IF_FAIL(height > 0, NULL);
591
592         struct _tbm_bufmgr *mgr;
593         struct _tbm_surface *surf = NULL;
594         uint32_t size = 0;
595         uint32_t offset = 0;
596         uint32_t stride = 0;
597         uint32_t bo_size = 0;
598         int bo_idx;
599         int i, j;
600
601         _tbm_surface_mutex_lock();
602
603         if (!g_surface_bufmgr) {
604                 _init_surface_bufmgr();
605                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
606         }
607
608         mgr = g_surface_bufmgr;
609         if (!TBM_BUFMGR_IS_VALID(mgr)) {
610                 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
611                                 width, height, _tbm_surface_internal_format_to_str(format), flags);
612                 _tbm_surface_mutex_unlock();
613                 return NULL;
614         }
615         surf = calloc(1, sizeof(struct _tbm_surface));
616         if (!surf) {
617                 TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
618                                 width, height, _tbm_surface_internal_format_to_str(format), flags);
619                 _tbm_surface_mutex_unlock();
620                 return NULL;
621         }
622
623         surf->bufmgr = mgr;
624         surf->info.width = width;
625         surf->info.height = height;
626         surf->info.format = format;
627         surf->info.bpp = tbm_surface_internal_get_bpp(format);
628         surf->info.num_planes = tbm_surface_internal_get_num_planes(format);
629         surf->refcnt = 1;
630
631         /* get size, stride and offset bo_idx */
632         for (i = 0; i < surf->info.num_planes; i++) {
633                 _tbm_surface_internal_query_plane_data(surf, i, &size, &offset, &stride,
634                                                        &bo_idx);
635                 surf->info.planes[i].size = size;
636                 surf->info.planes[i].offset = offset;
637                 surf->info.planes[i].stride = stride;
638                 surf->planes_bo_idx[i] = bo_idx;
639         }
640
641         surf->num_bos = 1;
642
643         for (i = 0; i < surf->info.num_planes; i++) {
644                 surf->info.size += surf->info.planes[i].size;
645
646                 if (surf->num_bos < surf->planes_bo_idx[i] + 1)
647                         surf->num_bos = surf->planes_bo_idx[i] + 1;
648         }
649
650         surf->flags = flags;
651
652         for (i = 0; i < surf->num_bos; i++) {
653                 bo_size = 0;
654                 for (j = 0; j < surf->info.num_planes; j++) {
655                         if (surf->planes_bo_idx[j] == i)
656                                 bo_size += surf->info.planes[j].size;
657                 }
658
659                 if (mgr->backend->surface_bo_alloc) {
660                         /* LCOV_EXCL_START */
661                         tbm_bo bo = NULL;
662                         void *bo_priv = NULL;
663
664                         bo = calloc(1, sizeof(struct _tbm_bo));
665                         if (!bo) {
666                                 TBM_LOG_E("fail to alloc bo struct\n");
667                                 goto alloc_fail;
668                         }
669
670                         bo->bufmgr = surf->bufmgr;
671
672                         pthread_mutex_lock(&surf->bufmgr->lock);
673
674                         bo_priv = mgr->backend->surface_bo_alloc(bo, width, height, format, flags, i);
675                         if (!bo_priv) {
676                                 TBM_LOG_E("fail to alloc bo priv\n");
677                                 free(bo);
678                                 pthread_mutex_unlock(&surf->bufmgr->lock);
679                                 goto alloc_fail;
680                         }
681
682                         bo->ref_cnt = 1;
683                         bo->flags = flags;
684                         bo->priv = bo_priv;
685
686                         LIST_INITHEAD(&bo->user_data_list);
687
688                         LIST_ADD(&bo->item_link, &surf->bufmgr->bo_list);
689
690                         pthread_mutex_unlock(&surf->bufmgr->lock);
691
692                         surf->bos[i] = bo;
693                         /* LCOV_EXCL_STOP */
694                 } else {
695                         surf->bos[i] = tbm_bo_alloc(mgr, bo_size, flags);
696                 }
697
698                 if (!surf->bos[i]) {
699                         TBM_LOG_E("fail to alloc bo idx:%d\n", i);
700                         goto alloc_fail;
701                 }
702
703                 _tbm_bo_set_surface(surf->bos[i], surf);
704
705         }
706
707         TBM_TRACE("width(%d) height(%d) format(%s) flags(%d) tbm_surface(%p)\n", width, height,
708                         _tbm_surface_internal_format_to_str(format), flags, surf);
709
710         LIST_INITHEAD(&surf->user_data_list);
711         LIST_INITHEAD(&surf->debug_data_list);
712
713         LIST_ADD(&surf->item_link, &mgr->surf_list);
714
715         _tbm_surface_mutex_unlock();
716
717         return surf;
718
719 alloc_fail:
720
721         TBM_TRACE("error: width(%d) height(%d) format(%s) flags(%d)\n",
722                         width, height, _tbm_surface_internal_format_to_str(format), flags);
723
724         for (j = 0; j < i; j++) {
725                 if (surf->bos[j])
726                         tbm_bo_unref(surf->bos[j]);
727         }
728
729         free(surf);
730         surf = NULL;
731
732         if (LIST_IS_EMPTY(&mgr->surf_list)) {
733                 LIST_DELINIT(&mgr->surf_list);
734                 _deinit_surface_bufmgr();
735         }
736
737         _tbm_surface_mutex_unlock();
738         return NULL;
739 }
740
741 tbm_surface_h
742 tbm_surface_internal_create_with_bos(tbm_surface_info_s *info,
743                                      tbm_bo *bos, int num)
744 {
745         TBM_RETURN_VAL_IF_FAIL(bos, NULL);
746         TBM_RETURN_VAL_IF_FAIL(info, NULL);
747         TBM_RETURN_VAL_IF_FAIL(num == 1 || info->num_planes == num, NULL);
748
749         struct _tbm_bufmgr *mgr;
750         struct _tbm_surface *surf = NULL;
751         int i;
752
753         _tbm_surface_mutex_lock();
754
755         if (!g_surface_bufmgr) {
756                 _init_surface_bufmgr();
757                 LIST_INITHEAD(&g_surface_bufmgr->surf_list);
758         }
759
760         mgr = g_surface_bufmgr;
761         if (!TBM_BUFMGR_IS_VALID(mgr)) {
762                 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
763                                 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
764                 _tbm_surface_mutex_unlock();
765                 return NULL;
766         }
767
768         surf = calloc(1, sizeof(struct _tbm_surface));
769         if (!surf) {
770                 TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
771                                 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
772                 _tbm_surface_mutex_unlock();
773                 return NULL;
774         }
775
776         surf->bufmgr = mgr;
777         surf->info.width = info->width;
778         surf->info.height = info->height;
779         surf->info.format = info->format;
780         surf->info.bpp = info->bpp;
781         surf->info.num_planes = info->num_planes;
782         surf->refcnt = 1;
783
784         /* get size, stride and offset */
785         for (i = 0; i < info->num_planes; i++) {
786                 surf->info.planes[i].offset = info->planes[i].offset;
787                 surf->info.planes[i].stride = info->planes[i].stride;
788
789                 if (info->planes[i].size > 0)
790                         surf->info.planes[i].size = info->planes[i].size;
791                 else
792                         surf->info.planes[i].size += surf->info.planes[i].stride * info->height;
793
794                 if (num == 1)
795                         surf->planes_bo_idx[i] = 0;
796                 else
797                         surf->planes_bo_idx[i] = i;
798         }
799
800         if (info->size > 0) {
801                 surf->info.size = info->size;
802         } else {
803                 surf->info.size = 0;
804                 for (i = 0; i < info->num_planes; i++)
805                         surf->info.size += surf->info.planes[i].size;
806         }
807
808         surf->flags = TBM_BO_DEFAULT;
809
810         /* create only one bo */
811         surf->num_bos = num;
812         for (i = 0; i < num; i++) {
813                 if (bos[i] == NULL)
814                         goto bail1;
815
816                 surf->bos[i] = tbm_bo_ref(bos[i]);
817                 _tbm_bo_set_surface(bos[i], surf);
818         }
819
820         TBM_TRACE("tbm_surface(%p) width(%d) height(%d) format(%s) bo_num(%d)\n", surf,
821                         info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
822
823         LIST_INITHEAD(&surf->user_data_list);
824         LIST_INITHEAD(&surf->debug_data_list);
825
826         LIST_ADD(&surf->item_link, &mgr->surf_list);
827
828         _tbm_surface_mutex_unlock();
829
830         return surf;
831 bail1:
832         TBM_TRACE("error: width(%d) height(%d) format(%s) bo_num(%d)\n",
833                                 info->width, info->height, _tbm_surface_internal_format_to_str(info->format), num);
834         for (i = 0; i < num; i++) {
835                 if (surf->bos[i]) {
836                         tbm_bo_unref(surf->bos[i]);
837                         surf->bos[i] = NULL;
838                 }
839         }
840
841         free(surf);
842         surf = NULL;
843
844         if (LIST_IS_EMPTY(&g_surface_bufmgr->surf_list)) {
845                 LIST_DELINIT(&g_surface_bufmgr->surf_list);
846                 _deinit_surface_bufmgr();
847         }
848
849         _tbm_surface_mutex_unlock();
850
851         return NULL;
852 }
853
854 void
855 tbm_surface_internal_destroy(tbm_surface_h surface)
856 {
857         if (!tbm_surface_internal_is_valid(surface))
858                 return;
859
860         _tbm_surface_mutex_lock();
861
862         surface->refcnt--;
863
864         if (surface->refcnt > 0) {
865                 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
866                 _tbm_surface_mutex_unlock();
867                 return;
868         }
869
870         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
871
872         if (surface->refcnt == 0)
873                 _tbm_surface_internal_destroy(surface);
874
875         _tbm_surface_mutex_unlock();
876 }
877
878 void
879 tbm_surface_internal_ref(tbm_surface_h surface)
880 {
881         TBM_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
882
883         _tbm_surface_mutex_lock();
884
885         surface->refcnt++;
886
887         TBM_TRACE("tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
888
889         _tbm_surface_mutex_unlock();
890 }
891
892 void
893 tbm_surface_internal_unref(tbm_surface_h surface)
894 {
895         TBM_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
896
897         _tbm_surface_mutex_lock();
898
899         surface->refcnt--;
900
901         if (surface->refcnt > 0) {
902                 TBM_TRACE("reduce a refcnt(%d) of tbm_surface(%p)\n", surface->refcnt, surface);
903                 _tbm_surface_mutex_unlock();
904                 return;
905         }
906
907         TBM_TRACE("destroy tbm_surface(%p) refcnt(%d)\n", surface, surface->refcnt);
908
909         if (surface->refcnt == 0)
910                 _tbm_surface_internal_destroy(surface);
911
912         _tbm_surface_mutex_unlock();
913 }
914
915 int
916 tbm_surface_internal_get_num_bos(tbm_surface_h surface)
917 {
918         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
919
920         struct _tbm_surface *surf;
921         int num;
922
923         _tbm_surface_mutex_lock();
924
925         surf = (struct _tbm_surface *)surface;
926         num = surf->num_bos;
927
928         TBM_TRACE("tbm_surface(%p) num_bos(%d)\n", surface, num);
929
930         _tbm_surface_mutex_unlock();
931
932         return num;
933 }
934
935 tbm_bo
936 tbm_surface_internal_get_bo(tbm_surface_h surface, int bo_idx)
937 {
938         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), NULL);
939         TBM_RETURN_VAL_IF_FAIL(bo_idx > -1, NULL);
940
941         struct _tbm_surface *surf;
942         tbm_bo bo;
943
944         _tbm_surface_mutex_lock();
945
946         surf = (struct _tbm_surface *)surface;
947         bo = surf->bos[bo_idx];
948
949         TBM_TRACE("tbm_surface(%p) bo_idx(%d) tbm_bo(%p)\n", surface, bo_idx, bo);
950
951         _tbm_surface_mutex_unlock();
952
953         return bo;
954 }
955
956 int
957 tbm_surface_internal_get_size(tbm_surface_h surface)
958 {
959         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
960
961         struct _tbm_surface *surf;
962         unsigned int size;
963
964         _tbm_surface_mutex_lock();
965
966         surf = (struct _tbm_surface *)surface;
967         size = surf->info.size;
968
969         TBM_TRACE("tbm_surface(%p) size(%d)\n", surface, size);
970
971         _tbm_surface_mutex_unlock();
972
973         return size;
974 }
975
976 int
977 tbm_surface_internal_get_plane_data(tbm_surface_h surface, int plane_idx,
978                                     uint32_t *size, uint32_t *offset, uint32_t *pitch)
979 {
980         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
981         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
982
983         struct _tbm_surface *surf;
984
985         _tbm_surface_mutex_lock();
986
987         surf = (struct _tbm_surface *)surface;
988
989         if (plane_idx >= surf->info.num_planes) {
990                 TBM_TRACE("error: tbm_surface(%p) plane_idx(%d)\n", surface, plane_idx);
991                 _tbm_surface_mutex_unlock();
992                 return 0;
993         }
994
995         if (size)
996                 *size = surf->info.planes[plane_idx].size;
997
998         if (offset)
999                 *offset = surf->info.planes[plane_idx].offset;
1000
1001         if (pitch)
1002                 *pitch = surf->info.planes[plane_idx].stride;
1003
1004         TBM_TRACE("tbm_surface(%p) plane_idx(%d) size(%d) offset(%d) pitch(%d)\n", surface, plane_idx,
1005                                 surf->info.planes[plane_idx].size, surf->info.planes[plane_idx].offset,
1006                                 surf->info.planes[plane_idx].stride);
1007
1008         _tbm_surface_mutex_unlock();
1009
1010         return 1;
1011 }
1012
1013 int
1014 tbm_surface_internal_get_info(tbm_surface_h surface, int opt,
1015                               tbm_surface_info_s *info, int map)
1016 {
1017         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1018
1019         struct _tbm_surface *surf;
1020         tbm_bo_handle bo_handles[4];
1021         int i, j;
1022
1023         _tbm_surface_mutex_lock();
1024
1025         memset(bo_handles, 0, sizeof(tbm_bo_handle) * 4);
1026
1027         surf = (struct _tbm_surface *)surface;
1028
1029         memset(info, 0x00, sizeof(tbm_surface_info_s));
1030         info->width = surf->info.width;
1031         info->height = surf->info.height;
1032         info->format = surf->info.format;
1033         info->bpp = surf->info.bpp;
1034         info->size = surf->info.size;
1035         info->num_planes = surf->info.num_planes;
1036
1037         if (map == 1) {
1038                 for (i = 0; i < surf->num_bos; i++) {
1039                         bo_handles[i] = tbm_bo_map(surf->bos[i], TBM_DEVICE_CPU, opt);
1040                         if (bo_handles[i].ptr == NULL) {
1041                                 for (j = 0; j < i; j++)
1042                                         tbm_bo_unmap(surf->bos[j]);
1043
1044                                 TBM_TRACE("error: tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1045                                 _tbm_surface_mutex_unlock();
1046                                 return 0;
1047                         }
1048                 }
1049         } else {
1050                 for (i = 0; i < surf->num_bos; i++)
1051                         bo_handles[i] = tbm_bo_get_handle(surf->bos[i], TBM_DEVICE_CPU);
1052         }
1053
1054         for (i = 0; i < surf->info.num_planes; i++) {
1055                 info->planes[i].size = surf->info.planes[i].size;
1056                 info->planes[i].offset = surf->info.planes[i].offset;
1057                 info->planes[i].stride = surf->info.planes[i].stride;
1058
1059                 if (bo_handles[surf->planes_bo_idx[i]].ptr)
1060                         info->planes[i].ptr = bo_handles[surf->planes_bo_idx[i]].ptr +
1061                                               surf->info.planes[i].offset;
1062         }
1063
1064         TBM_TRACE("tbm_surface(%p) opt(%d) map(%d)\n", surface, opt, map);
1065
1066         _tbm_surface_mutex_unlock();
1067
1068         return 1;
1069 }
1070
1071 void
1072 tbm_surface_internal_unmap(tbm_surface_h surface)
1073 {
1074         TBM_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1075
1076         struct _tbm_surface *surf;
1077         int i;
1078
1079         _tbm_surface_mutex_lock();
1080
1081         surf = (struct _tbm_surface *)surface;
1082
1083         for (i = 0; i < surf->num_bos; i++)
1084                 tbm_bo_unmap(surf->bos[i]);
1085
1086         TBM_TRACE("tbm_surface(%p)\n", surface);
1087
1088         _tbm_surface_mutex_unlock();
1089 }
1090
1091 unsigned int
1092 tbm_surface_internal_get_width(tbm_surface_h surface)
1093 {
1094         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1095
1096         struct _tbm_surface *surf;
1097         unsigned int width;
1098
1099         _tbm_surface_mutex_lock();
1100
1101         surf = (struct _tbm_surface *)surface;
1102         width = surf->info.width;
1103
1104         TBM_TRACE("tbm_surface(%p) width(%d)\n", surface, width);
1105
1106         _tbm_surface_mutex_unlock();
1107
1108         return width;
1109 }
1110
1111 unsigned int
1112 tbm_surface_internal_get_height(tbm_surface_h surface)
1113 {
1114         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1115
1116         struct _tbm_surface *surf;
1117         unsigned int height;
1118
1119         _tbm_surface_mutex_lock();
1120
1121         surf = (struct _tbm_surface *)surface;
1122         height = surf->info.height;
1123
1124         TBM_TRACE("tbm_surface(%p) height(%d)\n", surface, height);
1125
1126         _tbm_surface_mutex_unlock();
1127
1128         return height;
1129
1130 }
1131
1132 tbm_format
1133 tbm_surface_internal_get_format(tbm_surface_h surface)
1134 {
1135         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1136
1137         struct _tbm_surface *surf;
1138         tbm_format format;
1139
1140         _tbm_surface_mutex_lock();
1141
1142         surf = (struct _tbm_surface *)surface;
1143         format = surf->info.format;
1144
1145         TBM_TRACE("tbm_surface(%p) format(%s)\n", surface, _tbm_surface_internal_format_to_str(format));
1146
1147         _tbm_surface_mutex_unlock();
1148
1149         return format;
1150 }
1151
1152 int
1153 tbm_surface_internal_get_plane_bo_idx(tbm_surface_h surface, int plane_idx)
1154 {
1155         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1156         TBM_RETURN_VAL_IF_FAIL(plane_idx > -1, 0);
1157         struct _tbm_surface *surf;
1158         int bo_idx;
1159
1160         _tbm_surface_mutex_lock();
1161
1162         surf = (struct _tbm_surface *)surface;
1163         bo_idx = surf->planes_bo_idx[plane_idx];
1164
1165         TBM_TRACE("tbm_surface(%p) plane_idx(%d) bo_idx(%d)\n", surface, plane_idx, bo_idx);
1166
1167         _tbm_surface_mutex_unlock();
1168
1169         return bo_idx;
1170 }
1171
1172 int
1173 tbm_surface_internal_add_user_data(tbm_surface_h surface, unsigned long key,
1174                                    tbm_data_free data_free_func)
1175 {
1176         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1177
1178         tbm_user_data *data;
1179
1180         /* check if the data according to the key exist if so, return false. */
1181         data = user_data_lookup(&surface->user_data_list, key);
1182         if (data) {
1183                 TBM_TRACE("warning: user data already exist tbm_surface(%p) key(%lu)\n", surface, key);
1184                 return 0;
1185         }
1186
1187         data = user_data_create(key, data_free_func);
1188         if (!data) {
1189                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1190                 return 0;
1191         }
1192
1193         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, data);
1194
1195         LIST_ADD(&data->item_link, &surface->user_data_list);
1196
1197         return 1;
1198 }
1199
1200 int
1201 tbm_surface_internal_set_user_data(tbm_surface_h surface, unsigned long key,
1202                                    void *data)
1203 {
1204         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1205
1206         tbm_user_data *old_data;
1207
1208         if (LIST_IS_EMPTY(&surface->user_data_list)) {
1209                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1210                 return 0;
1211         }
1212
1213         old_data = user_data_lookup(&surface->user_data_list, key);
1214         if (!old_data) {
1215                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1216                 return 0;
1217         }
1218
1219         if (old_data->data && old_data->free_func)
1220                 old_data->free_func(old_data->data);
1221
1222         old_data->data = data;
1223
1224         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1225
1226         return 1;
1227 }
1228
1229 int
1230 tbm_surface_internal_get_user_data(tbm_surface_h surface, unsigned long key,
1231                                    void **data)
1232 {
1233         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1234
1235         tbm_user_data *old_data;
1236
1237         if (!data || LIST_IS_EMPTY(&surface->user_data_list)) {
1238                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1239                 return 0;
1240         }
1241
1242         old_data = user_data_lookup(&surface->user_data_list, key);
1243         if (!old_data) {
1244                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1245                 *data = NULL;
1246                 return 0;
1247         }
1248
1249         *data = old_data->data;
1250
1251         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1252
1253         return 1;
1254 }
1255
1256 int
1257 tbm_surface_internal_delete_user_data(tbm_surface_h surface,
1258                                       unsigned long key)
1259 {
1260         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1261
1262         tbm_user_data *old_data = (void *)0;
1263
1264         if (LIST_IS_EMPTY(&surface->user_data_list)) {
1265                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1266                 return 0;
1267         }
1268
1269         old_data = user_data_lookup(&surface->user_data_list, key);
1270         if (!old_data) {
1271                 TBM_TRACE("error: tbm_surface(%p) key(%lu)\n", surface, key);
1272                 return 0;
1273         }
1274
1275         TBM_TRACE("tbm_surface(%p) key(%lu) data(%p)\n", surface, key, old_data->data);
1276
1277         user_data_delete(old_data);
1278
1279         return 1;
1280 }
1281
1282 /* LCOV_EXCL_START */
1283 unsigned int
1284 _tbm_surface_internal_get_debug_pid(tbm_surface_h surface)
1285 {
1286         TBM_RETURN_VAL_IF_FAIL(surface, 0);
1287
1288         return surface->debug_pid;
1289 }
1290
1291 void
1292 tbm_surface_internal_set_debug_pid(tbm_surface_h surface, unsigned int pid)
1293 {
1294         TBM_RETURN_IF_FAIL(tbm_surface_internal_is_valid(surface));
1295
1296         surface->debug_pid = pid;
1297 }
1298
1299 static tbm_surface_debug_data *
1300 _tbm_surface_internal_debug_data_create(char *key, char *value)
1301 {
1302         tbm_surface_debug_data *debug_data = NULL;
1303
1304         debug_data = calloc(1, sizeof(tbm_surface_debug_data));
1305         if (!debug_data)
1306                 return NULL;
1307
1308         if (key) debug_data->key = strdup(key);
1309         if (value) debug_data->value = strdup(value);
1310
1311         return debug_data;
1312 }
1313
1314 int
1315 tbm_surface_internal_set_debug_data(tbm_surface_h surface, char *key, char *value)
1316 {
1317         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), 0);
1318         TBM_RETURN_VAL_IF_FAIL(key, 0);
1319
1320         tbm_surface_debug_data *debug_data = NULL;
1321         tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1322         tbm_bufmgr bufmgr = surface->bufmgr;
1323
1324         TBM_RETURN_VAL_IF_FAIL(bufmgr, 0);
1325
1326         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1327                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1328                         if (!strcmp(old_data->key, key)) {
1329                                 if (value)
1330                                         old_data->value = strdup(value);
1331                                 else
1332                                         old_data->value = NULL;
1333                         }
1334                 }
1335         }
1336
1337         debug_data = _tbm_surface_internal_debug_data_create(key, value);
1338         if (!debug_data) {
1339                 TBM_TRACE("error: tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1340                 return 0;
1341         }
1342
1343         TBM_TRACE("tbm_surface(%p) key(%s) value(%s)\n", surface, key, value);
1344
1345         LIST_ADD(&debug_data->item_link, &surface->debug_data_list);
1346
1347         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
1348                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &bufmgr->debug_key_list, item_link) {
1349                         if (!strcmp(old_data->key, key))
1350                                 return 1;
1351                 }
1352         }
1353
1354         debug_data = _tbm_surface_internal_debug_data_create(key, NULL);
1355         LIST_ADD(&debug_data->item_link, &bufmgr->debug_key_list);
1356
1357         return 1;
1358 }
1359
1360 char *
1361 _tbm_surface_internal_get_debug_data(tbm_surface_h surface, char *key)
1362 {
1363         TBM_RETURN_VAL_IF_FAIL(tbm_surface_internal_is_valid(surface), NULL);
1364
1365         tbm_surface_debug_data *old_data = NULL, *tmp = NULL;
1366
1367         if (!LIST_IS_EMPTY(&surface->debug_data_list)) {
1368                 LIST_FOR_EACH_ENTRY_SAFE(old_data, tmp, &surface->debug_data_list, item_link) {
1369                         if (!strcmp(old_data->key, key))
1370                                 return old_data->value;
1371                 }
1372         }
1373
1374         return NULL;
1375 }
1376
1377 typedef struct _tbm_surface_dump_info tbm_surface_dump_info;
1378 typedef struct _tbm_surface_dump_buf_info tbm_surface_dump_buf_info;
1379
1380 struct _tbm_surface_dump_buf_info {
1381         int index;
1382         tbm_bo bo;
1383         int size;
1384         int dirty;
1385         int dirty_shm;
1386         int shm_stride;
1387         int shm_h;
1388         char name[1024];
1389
1390         tbm_surface_info_s info;
1391
1392         struct list_head link;
1393 };
1394
1395 struct _tbm_surface_dump_info {
1396         char *path;  // copy???
1397         int dump_max;
1398         int count;
1399         struct list_head *link;
1400         struct list_head surface_list; /* link of surface */
1401 };
1402
1403 static tbm_surface_dump_info *g_dump_info = NULL;
1404 static const char *dump_postfix[2] = {"png", "yuv"};
1405
1406 static void
1407 _tbm_surface_internal_dump_file_raw(const char *file, void *data1, int size1, void *data2,
1408                 int size2, void *data3, int size3)
1409 {
1410         unsigned int *blocks;
1411         FILE *fp = fopen(file, "w+");
1412         TBM_RETURN_IF_FAIL(fp != NULL);
1413
1414         blocks = (unsigned int *)data1;
1415         fwrite(blocks, 1, size1, fp);
1416
1417         if (size2 > 0) {
1418                 blocks = (unsigned int *)data2;
1419                 fwrite(blocks, 1, size2, fp);
1420         }
1421
1422         if (size3 > 0) {
1423                 blocks = (unsigned int *)data3;
1424                 fwrite(blocks, 1, size3, fp);
1425         }
1426
1427         fclose(fp);
1428 }
1429
1430 static void
1431 _tbm_surface_internal_dump_file_png(const char *file, const void *data, int width,
1432                 int height)
1433 {
1434         FILE *fp = fopen(file, "wb");
1435         TBM_RETURN_IF_FAIL(fp != NULL);
1436         int depth = 8;
1437
1438         png_structp pPngStruct =
1439                 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1440         if (!pPngStruct) {
1441                 fclose(fp);
1442                 return;
1443         }
1444
1445         png_infop pPngInfo = png_create_info_struct(pPngStruct);
1446         if (!pPngInfo) {
1447                 png_destroy_write_struct(&pPngStruct, NULL);
1448                 fclose(fp);
1449                 return;
1450         }
1451
1452         png_init_io(pPngStruct, fp);
1453         png_set_IHDR(pPngStruct,
1454                         pPngInfo,
1455                         width,
1456                         height,
1457                         depth,
1458                         PNG_COLOR_TYPE_RGBA,
1459                         PNG_INTERLACE_NONE,
1460                         PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1461
1462         png_set_bgr(pPngStruct);
1463         png_write_info(pPngStruct, pPngInfo);
1464
1465         const int pixel_size = 4;       // RGBA
1466         png_bytep *row_pointers =
1467                         png_malloc(pPngStruct, height * sizeof(png_byte *));
1468
1469         unsigned int *blocks = (unsigned int *)data;
1470         int y = 0;
1471         int x = 0;
1472
1473         for (; y < height; ++y) {
1474                 png_bytep row =
1475                         png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
1476                 row_pointers[y] = (png_bytep)row;
1477                 for (x = 0; x < width; ++x) {
1478                         unsigned int curBlock = blocks[y * width + x];
1479                         row[x * pixel_size] = (curBlock & 0xFF);
1480                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
1481                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
1482                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
1483                 }
1484         }
1485
1486         png_write_image(pPngStruct, row_pointers);
1487         png_write_end(pPngStruct, pPngInfo);
1488
1489         for (y = 0; y < height; y++)
1490                 png_free(pPngStruct, row_pointers[y]);
1491         png_free(pPngStruct, row_pointers);
1492
1493         png_destroy_write_struct(&pPngStruct, &pPngInfo);
1494
1495         fclose(fp);
1496 }
1497
1498 void
1499 tbm_surface_internal_dump_start(char *path, int w, int h, int count)
1500 {
1501         TBM_RETURN_IF_FAIL(path != NULL);
1502         TBM_RETURN_IF_FAIL(w > 0);
1503         TBM_RETURN_IF_FAIL(h > 0);
1504         TBM_RETURN_IF_FAIL(count > 0);
1505
1506         tbm_surface_dump_buf_info *buf_info = NULL;
1507         tbm_surface_dump_buf_info *tmp;
1508         tbm_bo bo = NULL;
1509         int i;
1510         int buffer_size;
1511         tbm_surface_h tbm_surface;
1512         tbm_surface_info_s info;
1513         tbm_surface_error_e err;
1514
1515         /* check running */
1516         if (g_dump_info) {
1517                 TBM_LOG_W("waring already running the tbm_surface_internal_dump.\n");
1518                 return;
1519         }
1520
1521         g_dump_info = calloc(1, sizeof(struct _tbm_surface_dump_info));
1522         TBM_RETURN_IF_FAIL(g_dump_info);
1523
1524         LIST_INITHEAD(&g_dump_info->surface_list);
1525         g_dump_info->count = 0;
1526         g_dump_info->dump_max = count;
1527
1528         /* get buffer size */
1529         tbm_surface = tbm_surface_create(w, h, TBM_FORMAT_ARGB8888);
1530         if (tbm_surface == NULL) {
1531                 TBM_LOG_E("tbm_surface_create fail\n");
1532                 free(g_dump_info);
1533                 g_dump_info = NULL;
1534                 return;
1535         }
1536         err = tbm_surface_map(tbm_surface, TBM_SURF_OPTION_READ, &info);
1537         if (err != TBM_SURFACE_ERROR_NONE) {
1538                 TBM_LOG_E("tbm_surface_map fail\n");
1539                 tbm_surface_destroy(tbm_surface);
1540                 free(g_dump_info);
1541                 g_dump_info = NULL;
1542                 return;
1543         }
1544         buffer_size = info.planes[0].stride * h;
1545         tbm_surface_unmap(tbm_surface);
1546         tbm_surface_destroy(tbm_surface);
1547
1548         /* create dump lists */
1549         for (i = 0; i < count; i++)     {
1550                 buf_info = calloc(1, sizeof(tbm_surface_dump_buf_info));
1551                 TBM_GOTO_VAL_IF_FAIL(buf_info, fail);
1552                 bo = tbm_bo_alloc(g_surface_bufmgr, buffer_size, TBM_BO_DEFAULT);
1553                 if (bo == NULL) {
1554                         free(buf_info);
1555                         goto fail;
1556                 }
1557
1558                 buf_info->index = i;
1559                 buf_info->bo = bo;
1560                 buf_info->size = buffer_size;
1561
1562                 LIST_ADDTAIL(&buf_info->link, &g_dump_info->surface_list);
1563         }
1564
1565         g_dump_info->path = path;
1566         g_dump_info->link = &g_dump_info->surface_list;
1567
1568         TBM_LOG_I("Dump Start.. path:%s, count:%d\n", g_dump_info->path, count);
1569
1570         return;
1571 fail:
1572         /* free resources */
1573         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1574                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1575                         tbm_bo_unref(buf_info->bo);
1576                         free(buf_info);
1577                 }
1578         }
1579
1580         TBM_LOG_E("Dump Start fail.. path:%s\n", g_dump_info->path);
1581
1582         free(g_dump_info);
1583         g_dump_info = NULL;
1584
1585         return;
1586 }
1587
1588 void
1589 tbm_surface_internal_dump_end(void)
1590 {
1591         tbm_surface_dump_buf_info *buf_info = NULL, *tmp = NULL;
1592         tbm_bo_handle bo_handle;
1593
1594         if (!g_dump_info)
1595                 return;
1596
1597         /* make files */
1598         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1599                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1600                         char file[2048];
1601
1602                         if (buf_info->dirty) {
1603                                 void *ptr1 = NULL;
1604                                 void *ptr2 = NULL;
1605
1606                                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1607                                 if (bo_handle.ptr == NULL)
1608                                         continue;
1609
1610                                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1611                                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1612
1613                                 switch (buf_info->info.format) {
1614                                 case TBM_FORMAT_ARGB8888:
1615                                 case TBM_FORMAT_XRGB8888:
1616                                         _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1617                                                                         buf_info->info.planes[0].stride >> 2, buf_info->info.height);
1618                                         break;
1619                                 case TBM_FORMAT_YVU420:
1620                                 case TBM_FORMAT_YUV420:
1621                                         ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1622                                         ptr2 = ptr1 + buf_info->info.planes[1].stride * (buf_info->info.height >> 1);
1623                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1624                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1625                                                                         ptr1,
1626                                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1627                                                                         ptr2,
1628                                                                         buf_info->info.planes[2].stride * (buf_info->info.height >> 1));
1629                                         break;
1630                                 case TBM_FORMAT_NV12:
1631                                 case TBM_FORMAT_NV21:
1632                                         ptr1 = bo_handle.ptr + buf_info->info.planes[0].stride * buf_info->info.height;
1633                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1634                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1635                                                                         ptr1,
1636                                                                         buf_info->info.planes[1].stride * (buf_info->info.height >> 1),
1637                                                                         NULL, 0);
1638                                         break;
1639                                 case TBM_FORMAT_YUYV:
1640                                 case TBM_FORMAT_UYVY:
1641                                         _tbm_surface_internal_dump_file_raw(file, bo_handle.ptr,
1642                                                                         buf_info->info.planes[0].stride * buf_info->info.height,
1643                                                                         NULL, 0, NULL, 0);
1644                                         break;
1645                                 default:
1646                                         TBM_LOG_E("can't dump %c%c%c%c buffer", FOURCC_STR(buf_info->info.format));
1647                                         tbm_bo_unmap(buf_info->bo);
1648                                         return;
1649                                 }
1650
1651                                 tbm_bo_unmap(buf_info->bo);
1652                         } else if (buf_info->dirty_shm) {
1653                                 bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_READ);
1654                                 if (bo_handle.ptr == NULL)
1655                                         continue;
1656
1657                                 snprintf(file, sizeof(file), "%s/%s", g_dump_info->path, buf_info->name);
1658                                 TBM_LOG_I("Dump File.. %s generated.\n", file);
1659
1660                                 _tbm_surface_internal_dump_file_png(file, bo_handle.ptr,
1661                                                                 buf_info->shm_stride >> 2, buf_info->shm_h);
1662
1663                                 tbm_bo_unmap(buf_info->bo);
1664                         }
1665                 }
1666         }
1667
1668         /* free resources */
1669         if (!LIST_IS_EMPTY(&g_dump_info->surface_list)) {
1670                 LIST_FOR_EACH_ENTRY_SAFE(buf_info, tmp, &g_dump_info->surface_list, link) {
1671                         tbm_bo_unref(buf_info->bo);
1672                         free(buf_info);
1673                 }
1674         }
1675
1676         free(g_dump_info);
1677         g_dump_info = NULL;
1678
1679         TBM_LOG_I("Dump End..\n");
1680 }
1681
1682 void
1683 tbm_surface_internal_dump_buffer(tbm_surface_h surface, const char *type)
1684 {
1685         TBM_RETURN_IF_FAIL(surface != NULL);
1686         TBM_RETURN_IF_FAIL(type != NULL);
1687
1688         tbm_surface_dump_buf_info *buf_info;
1689         tbm_surface_info_s info;
1690         struct list_head *next_link;
1691         tbm_bo_handle bo_handle;
1692         int ret;
1693         const char *postfix;
1694
1695         if (!g_dump_info)
1696                 return;
1697
1698         next_link = g_dump_info->link->next;
1699         TBM_RETURN_IF_FAIL(next_link != NULL);
1700
1701         if (next_link == &g_dump_info->surface_list) {
1702                 next_link = next_link->next;
1703                 TBM_RETURN_IF_FAIL(next_link != NULL);
1704         }
1705
1706         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1707         TBM_RETURN_IF_FAIL(buf_info != NULL);
1708
1709         ret = tbm_surface_map(surface, TBM_SURF_OPTION_READ|TBM_SURF_OPTION_WRITE, &info);
1710         TBM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
1711
1712         if (info.size > buf_info->size) {
1713                 TBM_LOG_W("Dump skip. surface over created buffer size(%d, %d)\n", info.size, buf_info->size);
1714                 tbm_surface_unmap(surface);
1715                 return;
1716         }
1717
1718         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
1719                 postfix = dump_postfix[0];
1720         else
1721                 postfix = dump_postfix[1];
1722
1723         /* make the file information */
1724         memcpy(&buf_info->info, &info, sizeof(tbm_surface_info_s));
1725
1726         /* dump */
1727         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1728         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1729         memset(bo_handle.ptr, 0x00, buf_info->size);
1730
1731         switch (info.format) {
1732         case TBM_FORMAT_ARGB8888:
1733         case TBM_FORMAT_XRGB8888:
1734                 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d_%p-%s.%s",
1735                                  _tbm_surface_internal_get_time(),
1736                                  g_dump_info->count++, surface, type, postfix);
1737                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.size);
1738                 break;
1739         case TBM_FORMAT_YVU420:
1740         case TBM_FORMAT_YUV420:
1741                 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1742                                  _tbm_surface_internal_get_time(),
1743                                  g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1744                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1745                 bo_handle.ptr += info.planes[0].stride * info.height;
1746                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1747                 bo_handle.ptr += info.planes[1].stride * (info.height >> 1);
1748                 memcpy(bo_handle.ptr, info.planes[2].ptr, info.planes[2].stride * (info.height >> 1));
1749                 break;
1750         case TBM_FORMAT_NV12:
1751         case TBM_FORMAT_NV21:
1752                 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1753                                  _tbm_surface_internal_get_time(),
1754                                  g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1755                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1756                 bo_handle.ptr += info.planes[0].stride * info.height;
1757                 memcpy(bo_handle.ptr, info.planes[1].ptr, info.planes[1].stride * (info.height >> 1));
1758                 break;
1759         case TBM_FORMAT_YUYV:
1760         case TBM_FORMAT_UYVY:
1761                 snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s_%dx%d_%c%c%c%c.%s",
1762                                  _tbm_surface_internal_get_time(),
1763                                  g_dump_info->count++, type, info.planes[0].stride, info.height, FOURCC_STR(info.format), postfix);
1764                 memcpy(bo_handle.ptr, info.planes[0].ptr, info.planes[0].stride * info.height);
1765                 break;
1766         default:
1767                 TBM_LOG_E("can't copy %c%c%c%c buffer", FOURCC_STR(info.format));
1768                 tbm_bo_unmap(buf_info->bo);
1769                 return;
1770         }
1771
1772         tbm_bo_unmap(buf_info->bo);
1773
1774         tbm_surface_unmap(surface);
1775
1776         buf_info->dirty = 1;
1777         buf_info->dirty_shm = 0;
1778
1779         if (g_dump_info->count == 1000)
1780                 g_dump_info->count = 0;
1781
1782         g_dump_info->link = next_link;
1783
1784         TBM_LOG_I("Dump %s \n", buf_info->name);
1785 }
1786
1787 void tbm_surface_internal_dump_shm_buffer(void *ptr, int w, int h, int  stride, const char *type)
1788 {
1789         TBM_RETURN_IF_FAIL(ptr != NULL);
1790         TBM_RETURN_IF_FAIL(w > 0);
1791         TBM_RETURN_IF_FAIL(h > 0);
1792         TBM_RETURN_IF_FAIL(stride > 0);
1793         TBM_RETURN_IF_FAIL(type != NULL);
1794
1795         tbm_surface_dump_buf_info *buf_info;
1796         struct list_head *next_link;
1797         tbm_bo_handle bo_handle;
1798
1799         if (!g_dump_info)
1800                 return;
1801
1802         next_link = g_dump_info->link->next;
1803         TBM_RETURN_IF_FAIL(next_link != NULL);
1804
1805         if (next_link == &g_dump_info->surface_list) {
1806                 next_link = next_link->next;
1807                 TBM_RETURN_IF_FAIL(next_link != NULL);
1808         }
1809
1810         buf_info = LIST_ENTRY(tbm_surface_dump_buf_info, next_link, link);
1811         TBM_RETURN_IF_FAIL(buf_info != NULL);
1812
1813         if (stride * h > buf_info->size) {
1814                 TBM_LOG_W("Dump skip. shm buffer over created buffer size(%d, %d)\n", stride * h, buf_info->size);
1815                 return;
1816         }
1817
1818         /* dump */
1819         bo_handle = tbm_bo_map(buf_info->bo, TBM_DEVICE_CPU, TBM_OPTION_WRITE);
1820         TBM_RETURN_IF_FAIL(bo_handle.ptr != NULL);
1821         memset(bo_handle.ptr, 0x00, buf_info->size);
1822         memset(&buf_info->info, 0x00, sizeof(tbm_surface_info_s));
1823
1824         snprintf(buf_info->name, sizeof(buf_info->name), "%10.3f_%03d-%s.%s",
1825                          _tbm_surface_internal_get_time(),
1826                          g_dump_info->count++, type, dump_postfix[0]);
1827         memcpy(bo_handle.ptr, ptr, stride * h);
1828
1829         tbm_bo_unmap(buf_info->bo);
1830
1831         buf_info->dirty = 0;
1832         buf_info->dirty_shm = 1;
1833         buf_info->shm_stride = stride;
1834         buf_info->shm_h = h;
1835
1836         if (g_dump_info->count == 1000)
1837                 g_dump_info->count = 0;
1838
1839         g_dump_info->link = next_link;
1840
1841         TBM_LOG_I("Dump %s \n", buf_info->name);
1842 }
1843
1844 void tbm_surface_internal_dump_all(char *path)
1845 {
1846         TBM_RETURN_IF_FAIL(path != NULL);
1847         int w = 0, h = 0, count = 0;
1848         tbm_surface_h surface = NULL, tmp = NULL;
1849
1850         count = _tbm_surface_get_max_size(&w, &h);
1851         if (count == 0) {
1852                 TBM_LOG_I("No tbm_surface.\n");
1853                 return;
1854         }
1855
1856         tbm_surface_internal_dump_start(path, w, h, count);
1857
1858         LIST_FOR_EACH_ENTRY_SAFE(surface, tmp, &g_surface_bufmgr->surf_list, item_link) {
1859                 tbm_surface_internal_dump_buffer(surface, "dump_all");
1860         }
1861
1862         tbm_surface_internal_dump_end();
1863 }
1864 /*LCOV_EXCL_STOP*/