tbm_module: change the tbm_module_bo_xxx signature
[platform/core/uifw/libtbm.git] / src / tbm_bufmgr.c
1 /**************************************************************************
2
3 libtbm
4
5 Copyright 2012 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 "tbm_bufmgr.h"
35 #include "tbm_bufmgr_int.h"
36 #include "tbm_drm_helper.h"
37 #include "list.h"
38
39 #include <sys/resource.h>
40
41 int trace_mask = 0;
42
43 #ifdef HAVE_DLOG
44 int bDlog;
45 #endif
46
47 tbm_bufmgr gBufMgr;
48 int b_dump_queue;
49
50 static pthread_mutex_t gLock = PTHREAD_MUTEX_INITIALIZER;
51 static pthread_mutex_t tbm_bufmgr_lock = PTHREAD_MUTEX_INITIALIZER;
52 static double scale_factor = 0;
53 void _tbm_bufmgr_mutex_unlock(void);
54
55 //#define TBM_BUFMGR_INIT_TIME
56
57 #define MAX_SIZE_N(dest)        (sizeof(dest) - strlen(dest) - 1)
58
59 /* check condition */
60 #define TBM_BUFMGR_RETURN_IF_FAIL(cond) {\
61         if (!(cond)) {\
62                 TBM_ERR("'%s' failed.\n", #cond);\
63                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
64                 _tbm_bufmgr_mutex_unlock();\
65                 return;\
66         } \
67 }
68
69 #define TBM_BUFMGR_RETURN_VAL_IF_FAIL(cond, val) {\
70         if (!(cond)) {\
71                 TBM_ERR("'%s' failed.\n", #cond);\
72                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);\
73                 _tbm_bufmgr_mutex_unlock();\
74                 return val;\
75         } \
76 }
77
78 /* LCOV_EXCL_START */
79
80 static void
81 _tbm_bufmgr_check_bo_cnt(tbm_bufmgr bufmgr)
82 {
83         static int last_chk_bo_cnt = 0;
84
85         if ((bufmgr->bo_cnt >= 500) && ((bufmgr->bo_cnt % 20) == 0) &&
86                 (bufmgr->bo_cnt > last_chk_bo_cnt)) {
87                 TBM_DBG("============TBM BO CNT DEBUG: bo_cnt=%d\n", bufmgr->bo_cnt);
88                 tbm_bufmgr_debug_show(bufmgr);
89                 last_chk_bo_cnt = bufmgr->bo_cnt;
90         }
91 }
92
93 static void
94 _tbm_bufmgr_initialize_bo(tbm_bufmgr bufmgr, tbm_bo bo, int flags)
95 {
96         bo->bufmgr = bufmgr;
97         bo->flags = flags;
98         bo->magic = TBM_BO_MAGIC;
99         bo->ref_cnt = 1;
100
101         LIST_INITHEAD(&bo->user_data_list);
102
103         bufmgr->bo_cnt++;
104         LIST_ADD(&bo->item_link, &bufmgr->bo_list);
105 }
106
107 void
108 _tbm_bufmgr_mutex_lock(void)
109 {
110         pthread_mutex_lock(&tbm_bufmgr_lock);
111 }
112
113 void
114 _tbm_bufmgr_mutex_unlock(void)
115 {
116         pthread_mutex_unlock(&tbm_bufmgr_lock);
117 }
118
119 static int
120 _tbm_util_get_max_surface_size(int *w, int *h)
121 {
122         tbm_surface_info_s info;
123         tbm_surface_h surface = NULL;
124         int count = 0;
125
126         *w = 0;
127         *h = 0;
128
129         if (gBufMgr == NULL || LIST_IS_EMPTY(&gBufMgr->surf_list))
130                 return count;
131
132         LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link) {
133                 if (tbm_surface_get_info(surface, &info) == TBM_SURFACE_ERROR_NONE) {
134                         count++;
135                         if (*w < info.width)
136                                 *w = info.width;
137                         if (*h < info.height)
138                                 *h = info.height;
139                 }
140         }
141
142         return count;
143 }
144
145 static void
146 _tbm_util_get_appname_brief(char *brief)
147 {
148         char delim[] = "/";
149         char *token = NULL;
150         char temp[255] = {0,};
151         char *saveptr = NULL;
152
153         token = strtok_r(brief, delim, &saveptr);
154
155         while (token != NULL) {
156                 memset(temp, 0x00, 255 * sizeof(char));
157                 strncpy(temp, token, 254 * sizeof(char));
158                 token = strtok_r(NULL, delim, &saveptr);
159         }
160
161         snprintf(brief, sizeof(temp), "%s", temp);
162 }
163
164 static void
165 _tbm_util_get_appname_from_pid(long pid, char *str)
166 {
167         char fn_cmdline[255] = {0, }, cmdline[255];
168         FILE *fp;
169         int len;
170
171         if (pid <= 0) return;
172
173         snprintf(fn_cmdline, sizeof(fn_cmdline), "/proc/%ld/cmdline", pid);
174
175         fp = fopen(fn_cmdline, "r");
176         if (fp == 0) {
177                 TBM_ERR("cannot file open %s\n", fn_cmdline);
178                 return;
179         }
180
181         if (!fgets(cmdline, 255, fp)) {
182                 TBM_ERR("fail to get appname for pid(%ld)\n", pid);
183                 fclose(fp);
184                 return;
185         }
186
187         fclose(fp);
188
189         len = strlen(cmdline);
190         if (len < 1)
191                 memset(cmdline, 0x00, 255);
192         else
193                 cmdline[len] = 0;
194
195         snprintf(str, sizeof(cmdline), "%s", cmdline);
196 }
197
198 /* LCOV_EXCL_STOP */
199
200 static tbm_bufmgr
201 _tbm_bufmgr_init(int fd, int server)
202 {
203         tbm_error_e error = TBM_ERROR_NONE;
204
205 #ifdef TBM_BUFMGR_INIT_TIME
206         struct timeval start_tv, end_tv;
207 #endif
208         char *env;
209
210 #ifdef TBM_BUFMGR_INIT_TIME
211         /* get the start tv */
212         gettimeofday(&start_tv, NULL);
213 #endif
214
215         bDlog = 1;
216
217         /* LCOV_EXCL_START */
218 #ifdef TRACE
219         env = getenv("TBM_TRACE");
220         if (env) {
221                 trace_mask = atoi(env);
222                 TBM_DBG("TBM_TRACE=%s\n", env);
223         } else
224                 trace_mask = 0;
225 #endif
226
227         pthread_mutex_lock(&gLock);
228
229         _tbm_set_last_result(TBM_ERROR_NONE);
230
231         if (fd >= 0) {
232                 TBM_WRN("!!!!!WARNING:: The tbm_bufmgr_init DOSE NOT use argument fd ANYMORE.\n");
233                 TBM_WRN("!!!!!WARNING:: IT WILL BE CHANGED like tbm_bufmgr_init(int fd) --> tbm_bufmgr_init(void).\n");
234         }
235
236
237         /* initialize buffer manager */
238         if (gBufMgr) {
239                 gBufMgr->ref_count++;
240                 TBM_DBG("reuse  tbm_bufmgr(%p) ref_count(%d) fd(%d)\n", gBufMgr, gBufMgr->ref_count, gBufMgr->fd);
241                 pthread_mutex_unlock(&gLock);
242                 return gBufMgr;
243         }
244
245         TBM_DBG("bufmgr init\n");
246
247         /* allocate bufmgr */
248         gBufMgr = calloc(1, sizeof(struct _tbm_bufmgr));
249         if (!gBufMgr) {
250                 TBM_ERR("error: fail to alloc bufmgr fd(%d)\n", fd);
251                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
252                 pthread_mutex_unlock(&gLock);
253                 return NULL;
254         }
255
256         gBufMgr->fd = fd;
257
258         /* set the display_server flag before loading the backend module */
259         if (server) {
260                 TBM_INFO("The tbm_bufmgr(%p) is used by display server. Need to bind the native_display.\n", gBufMgr);
261                 gBufMgr->display_server = 1;
262         }
263
264         /* load bufmgr priv from env */
265         gBufMgr->module = tbm_module_load(gBufMgr->fd);
266         if (!gBufMgr->module) {
267                 TBM_ERR("error : Fail to load bufmgr backend\n");
268                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
269                 free(gBufMgr);
270                 gBufMgr = NULL;
271                 pthread_mutex_unlock(&gLock);
272                 return NULL;
273
274         }
275
276         /* check the essential capabilities of tbm_module */
277         gBufMgr->capabilities = tbm_module_get_capabilities(gBufMgr->module, &error);
278         if (gBufMgr->capabilities == TBM_BUFMGR_CAPABILITY_NONE) {
279                 TBM_ERR("The capabilities of the backend module is TBM_BUFMGR_CAPABILITY_NONE.");
280                 TBM_ERR("TBM_BUFMGR_CAPABILITY_SHARE_FD is the essential capability.");
281                 tbm_module_unload(gBufMgr->module);
282                 _tbm_set_last_result(error);
283                 free(gBufMgr);
284                 gBufMgr = NULL;
285                 pthread_mutex_unlock(&gLock);
286                 return NULL;
287         }
288
289         if (!(gBufMgr->capabilities & TBM_BUFMGR_CAPABILITY_SHARE_FD)) {
290                 TBM_ERR("The capabilities of the backend module had no TBM_BUFMGR_CAPABILITY_SHARE_FD.");
291                 TBM_ERR("The tbm backend has to get TBM_BUFMGR_CAPABILITY_SHARE_FD. ");
292                 tbm_module_unload(gBufMgr->module);
293                 _tbm_set_last_result(TBM_ERROR_INVALID_OPERATION);
294                 free(gBufMgr);
295                 gBufMgr = NULL;
296                 pthread_mutex_unlock(&gLock);
297                 return NULL;
298         }
299
300         /* LCOV_EXCL_STOP */
301
302         gBufMgr->ref_count = 1;
303
304         TBM_INFO("create tizen bufmgr:%p ref_count:%d\n",
305             gBufMgr, gBufMgr->ref_count);
306
307         /* setup the bo_lock_type */
308         env = getenv("BUFMGR_LOCK_TYPE");
309         if (env && !strcmp(env, "always"))
310                 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS;
311         else if (env && !strcmp(env, "none"))
312                 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_NEVER;
313         else if (env && !strcmp(env, "once"))
314                 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_ONCE;
315         else
316                 gBufMgr->bo_lock_type = TBM_BUFMGR_BO_LOCK_TYPE_ALWAYS;
317
318         TBM_DBG("BUFMGR_LOCK_TYPE=%s\n", env ? env : "default:once");
319
320         /* intialize bo_list */
321         LIST_INITHEAD(&gBufMgr->bo_list);
322
323         /* intialize surf_list */
324         LIST_INITHEAD(&gBufMgr->surf_list);
325
326         /* intialize surf_queue_list */
327         LIST_INITHEAD(&gBufMgr->surf_queue_list);
328
329         /* intialize debug_key_list */
330         LIST_INITHEAD(&gBufMgr->debug_key_list);
331
332 #ifdef TBM_BUFMGR_INIT_TIME
333         /* get the end tv */
334         gettimeofday(&end_tv, NULL);
335         TBM_INFO("tbm_bufmgr_init time: %ld ms", ((end_tv.tv_sec * 1000 + end_tv.tv_usec / 1000) - (start_tv.tv_sec * 1000 + start_tv.tv_usec / 1000)));
336 #endif
337
338         pthread_mutex_unlock(&gLock);
339
340         return gBufMgr;
341 }
342
343 tbm_bufmgr
344 tbm_bufmgr_init(int fd)
345 {
346         tbm_bufmgr bufmgr;
347
348         bufmgr = _tbm_bufmgr_init(fd, 0);
349
350         return bufmgr;
351 }
352
353 void
354 tbm_bufmgr_deinit(tbm_bufmgr bufmgr)
355 {
356         TBM_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
357
358         _tbm_bufmgr_mutex_lock();
359         pthread_mutex_lock(&gLock);
360         _tbm_set_last_result(TBM_ERROR_NONE);
361
362         if (!gBufMgr) {
363                 TBM_ERR("gBufmgr already destroy: bufmgr:%p\n", bufmgr);
364                 pthread_mutex_unlock(&gLock);
365                 _tbm_bufmgr_mutex_unlock();
366                 return;
367         }
368
369         bufmgr->ref_count--;
370         if (bufmgr->ref_count > 0) {
371                 TBM_DBG("reduce a ref_count(%d) of tbm_bufmgr(%p)\n", bufmgr->ref_count, bufmgr);
372                 pthread_mutex_unlock(&gLock);
373                 _tbm_bufmgr_mutex_unlock();
374                 return;
375         }
376
377         /* destroy bo_list */
378         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
379                 tbm_bo bo = NULL, tmp;
380
381                 LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bo_list, item_link) {
382                         TBM_ERR("Un-freed bo(%p, ref:%d)\n", bo, bo->ref_cnt);
383                         _tbm_bo_free(bo);
384                 }
385                 LIST_DELINIT(&bufmgr->bo_list);
386         }
387
388         /* destroy surf_list */
389         if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
390                 tbm_surface_h surf = NULL, tmp;
391
392                 LIST_FOR_EACH_ENTRY_SAFE(surf, tmp, &bufmgr->surf_list, item_link) {
393                         TBM_ERR("Un-freed surf(%p, ref:%d)\n", surf, surf->refcnt);
394                         tbm_surface_destroy(surf);
395                 }
396                 LIST_DELINIT(&bufmgr->surf_list);
397         }
398
399         tbm_module_unload(bufmgr->module);
400
401         if (bufmgr->fd > 0)
402                 close(bufmgr->fd);
403
404         TBM_INFO("destroy tbm_bufmgr(%p)\n", bufmgr);
405
406         free(bufmgr);
407         gBufMgr = NULL;
408
409         pthread_mutex_unlock(&gLock);
410         _tbm_bufmgr_mutex_unlock();
411 }
412
413 unsigned int
414 tbm_bufmgr_get_capability(tbm_bufmgr bufmgr)
415 {
416         unsigned int capabilities = TBM_BUFMGR_CAPABILITY_NONE;
417
418         _tbm_bufmgr_mutex_lock();
419         _tbm_set_last_result(TBM_ERROR_NONE);
420
421         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), TBM_BUFMGR_CAPABILITY_NONE);
422         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, TBM_BUFMGR_CAPABILITY_NONE);
423
424         capabilities = bufmgr->capabilities;
425
426         _tbm_bufmgr_mutex_unlock();
427
428         return capabilities;
429 }
430
431 /* LCOV_EXCL_START */
432 char *
433 tbm_bufmgr_debug_tbm_info_get(tbm_bufmgr bufmgr)
434 {
435         char app_name[255] = {0,}, title[512] = {0,};
436         tbm_surface_debug_data *debug_old_data = NULL;
437         char *str;
438         int len = 1024*4;
439         int c = 0;
440         int size;
441         tbm_error_e error;
442         long pid = 0;
443
444         pthread_mutex_lock(&gLock);
445         _tbm_set_last_result(TBM_ERROR_NONE);
446
447         if (!TBM_BUFMGR_IS_VALID(bufmgr) || (bufmgr != gBufMgr)) {
448                 TBM_ERR("invalid bufmgr\n");
449                 _tbm_set_last_result(TBM_ERROR_INVALID_PARAMETER);
450                 pthread_mutex_unlock(&gLock);
451                 return NULL;
452         }
453
454         str = malloc(len);
455         if (!str) {
456                 TBM_ERR("Fail to allocate the string.\n");
457                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
458                 pthread_mutex_unlock(&gLock);
459                 return NULL;
460         }
461
462         TBM_SNRPRINTF(str, len, c, "\n");
463         pid = syscall(SYS_getpid);
464         _tbm_util_get_appname_from_pid(pid, app_name);
465         _tbm_util_get_appname_brief(app_name);
466         TBM_SNRPRINTF(str, len, c, "===========================================TBM DEBUG: %s(%ld)===========================================\n",
467                   app_name, pid);
468
469         snprintf(title, 255, "%s", "no  surface     refcnt  width  height  bpp  size    n_b  n_p  flags    format    app_name              ");
470
471         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
472                 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
473                         strncat(title, "  ", MAX_SIZE_N(title));
474                         strncat(title, debug_old_data->key, MAX_SIZE_N(title));
475                 }
476         }
477
478         TBM_SNRPRINTF(str, len, c, "[tbm_surface information]\n");
479         TBM_SNRPRINTF(str, len, c, "%s\n", title);
480
481         /* show the tbm_surface information in surf_list */
482         if (!LIST_IS_EMPTY(&bufmgr->surf_list)) {
483                 tbm_surface_h surf = NULL;
484                 int surf_cnt = 0;
485
486                 LIST_FOR_EACH_ENTRY(surf, &bufmgr->surf_list, item_link) {
487                         char data[512] = {0,};
488                         unsigned int surf_pid = 0;
489                         int i;
490
491                         surf_pid = _tbm_surface_internal_get_debug_pid(surf);
492                         if (!surf_pid) {
493                                 /* if pid is null, set the self_pid */
494                                 surf_pid = syscall(SYS_getpid);;
495                         }
496
497                         memset(app_name, 0x0, 255 * sizeof(char));
498                         if (geteuid() == 0) {
499                                 _tbm_util_get_appname_from_pid(surf_pid, app_name);
500                                 _tbm_util_get_appname_brief(app_name);
501                         } else {
502                                 snprintf(app_name, sizeof(app_name), "%d", surf_pid);
503                         }
504
505                         snprintf(data, 255, "%-3d %-11p   %-5d %-6u %-7u %-4u %-7u  %-3d  %-3d %-8d %-9s %-22s",
506                                   ++surf_cnt,
507                                   surf,
508                                   surf->refcnt,
509                                   surf->info.width,
510                                   surf->info.height,
511                                   surf->info.bpp,
512                                   surf->info.size / 1024,
513                                   surf->num_bos,
514                                   surf->num_planes,
515                                   surf->flags,
516                                   _tbm_surface_internal_format_to_str(surf->info.format) + 11,
517                                   app_name);
518
519                         if (!LIST_IS_EMPTY(&bufmgr->debug_key_list)) {
520                                 LIST_FOR_EACH_ENTRY(debug_old_data, &bufmgr->debug_key_list, item_link) {
521                                         char *value;
522
523                                         strncat(data, "  ", MAX_SIZE_N(title));
524
525                                         value = _tbm_surface_internal_get_debug_data(surf, debug_old_data->key);
526                                         if (value)
527                                                 strncat(data, value, MAX_SIZE_N(title));
528                                         else
529                                                 strncat(data, "none", MAX_SIZE_N(title));
530                                 }
531                         }
532                         TBM_SNRPRINTF(str, len, c, "%s\n", data);
533
534                         for (i = 0; i < surf->num_bos; i++) {
535                                 size = tbm_bo_data_get_size(surf->bos[i]->bo_data, &error);
536                                 if (error != TBM_ERROR_NONE)
537                                         TBM_WRN("fail to get the size of bo.");
538                                 TBM_SNRPRINTF(str, len, c, " bo:%-12p  %-26d%-10d\n",
539                                           surf->bos[i],
540                                           surf->bos[i]->ref_cnt,
541                                           size / 1024);
542                         }
543                 }
544         } else
545                 TBM_SNRPRINTF(str, len, c, " no tbm_surfaces.\n");
546         TBM_SNRPRINTF(str, len, c, "\n");
547
548         TBM_SNRPRINTF(str, len, c, "[tbm_bo information]\n");
549         TBM_SNRPRINTF(str, len, c, "no  bo          refcnt  size    lock_cnt  map_cnt  flags   surface     name\n");
550
551         /* show the tbm_bo information in bo_list */
552         if (!LIST_IS_EMPTY(&bufmgr->bo_list)) {
553                 int bo_cnt = 0;
554                 tbm_bo bo = NULL;
555                 tbm_key key = 0;
556
557                 LIST_FOR_EACH_ENTRY(bo, &bufmgr->bo_list, item_link) {
558                         size = tbm_bo_data_get_size(bo->bo_data, &error);
559                         if (error != TBM_ERROR_NONE)
560                                 TBM_WRN("fail to get the size of bo.");
561                         key = tbm_bo_data_export_key(bo->bo_data, &error);
562                         if (error != TBM_ERROR_NONE)
563                                 TBM_WRN("fail to get the tdm_key of bo.");
564                         TBM_SNRPRINTF(str, len, c, "%-3d %-11p   %-5d %-7d    %-6d    %-5u %-7d %-11p  %-4d\n",
565                                   ++bo_cnt,
566                                   bo,
567                                   bo->ref_cnt,
568                                   size / 1024,
569                                   bo->lock_cnt,
570                                   bo->map_cnt,
571                                   bo->flags,
572                                   bo->surface,
573                                   key);
574                 }
575         } else
576                 TBM_SNRPRINTF(str, len, c, "no tbm_bos.\n");
577         TBM_SNRPRINTF(str, len, c, "\n");
578
579         TBM_SNRPRINTF(str, len, c, "========================================================================================================\n");
580
581         pthread_mutex_unlock(&gLock);
582
583         return str;
584 }
585
586 void
587 tbm_bufmgr_debug_show(tbm_bufmgr bufmgr)
588 {
589         char * str;
590         str = tbm_bufmgr_debug_tbm_info_get(bufmgr);
591         if (str) {
592                 TBM_DBG("       %s", str);
593                 free(str);
594         }
595 }
596
597 void
598 tbm_bufmgr_debug_trace(tbm_bufmgr bufmgr, int onoff)
599 {
600         _tbm_bufmgr_mutex_lock();
601         _tbm_set_last_result(TBM_ERROR_NONE);
602
603         TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
604         TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
605
606 #ifdef TRACE
607         TBM_LOG_D("bufmgr=%p onoff=%d\n", bufmgr, onoff);
608         bTrace = onoff;
609 #endif
610
611         _tbm_bufmgr_mutex_unlock();
612 }
613
614 void
615 tbm_bufmgr_debug_set_trace_mask(tbm_bufmgr bufmgr, tbm_bufmgr_debug_trace_mask mask, int set)
616 {
617         _tbm_bufmgr_mutex_lock();
618         _tbm_set_last_result(TBM_ERROR_NONE);
619
620         TBM_BUFMGR_RETURN_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr));
621         TBM_BUFMGR_RETURN_IF_FAIL(bufmgr == gBufMgr);
622
623         if (set == 1) {
624                 trace_mask |= mask;
625
626                 TBM_INFO("bufmgr=%p sets the trace_mask=%d\n", bufmgr, mask);
627                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_BO)
628                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_BO");
629                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL)
630                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL");
631                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE)
632                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE");
633                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE)
634                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE");
635         } else if (set == 0) {
636                 trace_mask &= ~mask;
637
638                 TBM_INFO("bufmgr=%p unsets the trace_mask=%d\n", bufmgr, mask);
639                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_BO)
640                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_BO");
641                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL)
642                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE_INTERNAL");
643                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE)
644                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE");
645                 if (trace_mask&TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE)
646                         TBM_INFO("  TBM_BUFGMR_DEBUG_TRACE_SURFACE_QUEUE");
647         } else {
648                 TBM_WRN("set value is wrong.(set=%d)", set);
649         }
650
651         _tbm_bufmgr_mutex_unlock();
652 }
653
654 void
655 tbm_bufmgr_debug_dump_set_scale(double scale)
656 {
657         pthread_mutex_lock(&gLock);
658         _tbm_set_last_result(TBM_ERROR_NONE);
659         scale_factor = scale;
660         pthread_mutex_unlock(&gLock);
661 }
662
663 int
664 tbm_bufmgr_debug_get_ref_count(void)
665 {
666         int refcnt;
667
668         pthread_mutex_lock(&gLock);
669
670         _tbm_set_last_result(TBM_ERROR_NONE);
671
672         refcnt = (gBufMgr) ? gBufMgr->ref_count : 0;
673
674         pthread_mutex_unlock(&gLock);
675
676         return refcnt;
677 }
678
679 int
680 tbm_bufmgr_debug_queue_dump(char *path, int count, int onoff)
681 {
682         pthread_mutex_lock(&gLock);
683         _tbm_set_last_result(TBM_ERROR_NONE);
684
685         if (onoff == 0) {
686                 TBM_DBG("count=%d onoff=%d\n", count, onoff);
687                 b_dump_queue = 0;
688                 tbm_surface_internal_dump_end();
689         } else {
690                 int w, h;
691
692                 if (path == NULL) {
693                         TBM_ERR("path is null");
694                         pthread_mutex_unlock(&gLock);
695                         return 0;
696                 }
697                 TBM_DBG("path=%s count=%d onoff=%d\n", path, count, onoff);
698
699                 if (_tbm_util_get_max_surface_size(&w, &h) == 0) {
700                         TBM_ERR("Fail to get tbm_surface size.\n");
701                         pthread_mutex_unlock(&gLock);
702                         return 0;
703                 }
704
705                 tbm_surface_internal_dump_with_scale_start(path, w, h, count, scale_factor);
706                 scale_factor = 0;
707
708                 b_dump_queue = 1;
709         }
710
711         pthread_mutex_unlock(&gLock);
712
713         return 1;
714 }
715
716 int
717 tbm_bufmgr_debug_dump_all(char *path)
718 {
719         int w, h, count = 0;
720         tbm_surface_h surface = NULL;
721
722         pthread_mutex_lock(&gLock);
723         _tbm_set_last_result(TBM_ERROR_NONE);
724
725         if (!path) {
726                 TBM_ERR("path is null.\n");
727                 pthread_mutex_unlock(&gLock);
728                 return 0;
729         }
730
731         TBM_DBG("path=%s\n", path);
732
733         count = _tbm_util_get_max_surface_size(&w, &h);
734         if (count == 0) {
735                 TBM_ERR("No tbm_surface.\n");
736                 pthread_mutex_unlock(&gLock);
737                 return 0;
738         }
739
740         tbm_surface_internal_dump_with_scale_start(path, w, h, count, scale_factor);
741         scale_factor = 0;
742
743         LIST_FOR_EACH_ENTRY(surface, &gBufMgr->surf_list, item_link)
744                 tbm_surface_internal_dump_buffer(surface, "dump_all");
745
746         tbm_surface_internal_dump_end();
747
748         pthread_mutex_unlock(&gLock);
749
750         return 1;
751 }
752
753 /* internal function */
754 tbm_bufmgr
755 _tbm_bufmgr_get_bufmgr(void)
756 {
757         return gBufMgr;
758 }
759
760 int
761 tbm_bufmgr_bind_native_display(tbm_bufmgr bufmgr, void *native_display)
762 {
763         tbm_error_e error;
764
765         _tbm_bufmgr_mutex_lock();
766         _tbm_set_last_result(TBM_ERROR_NONE);
767
768         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), 0);
769
770         error = tbm_module_bind_native_display(bufmgr->module, native_display);
771         if (error != TBM_ERROR_NONE) {
772                 _tbm_set_last_result(error);
773                 _tbm_bufmgr_mutex_unlock();
774
775                 if (error == TBM_ERROR_NOT_SUPPORTED) {
776                         TBM_WRN("Not supported, so skip: tbm_bufmgr(%p) native_display(%p)", bufmgr, native_display);
777                         return 1;
778                 }
779
780                 return 0;
781         }
782
783         TBM_INFO("tbm_bufmgr(%p) native_display(%p)\n", bufmgr, native_display);
784
785         _tbm_bufmgr_mutex_unlock();
786
787         return 1;
788 }
789
790 tbm_bufmgr
791 tbm_bufmgr_server_init(void)
792 {
793         tbm_bufmgr bufmgr;
794
795         bufmgr = _tbm_bufmgr_init(-1, 1);
796
797         return bufmgr;
798 }
799
800 int
801 tbm_bufmgr_set_bo_lock_type(tbm_bufmgr bufmgr, tbm_bufmgr_bo_lock_type bo_lock_type)
802 {
803         _tbm_bufmgr_mutex_lock();
804         _tbm_set_last_result(TBM_ERROR_NONE);
805
806         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), 0);
807         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, 0);
808
809         pthread_mutex_lock(&gLock);
810         gBufMgr->bo_lock_type = bo_lock_type;
811         pthread_mutex_unlock(&gLock);
812
813         TBM_INFO("The bo_lock_type of the bo is %d\n", bo_lock_type);
814
815         _tbm_bufmgr_mutex_unlock();
816
817         return 1;
818 }
819
820
821 int tbm_bufmgr_get_fd_limit(void)
822 {
823         struct rlimit lim;
824
825         if (getrlimit(RLIMIT_NOFILE, &lim))
826                 return 1024;
827
828         return (int)lim.rlim_cur;
829 }
830
831 tbm_bufmgr tbm_bufmgr_get(void)
832 {
833         return gBufMgr;
834 }
835
836
837 tbm_bo
838 tbm_bufmgr_internal_find_bo(tbm_bufmgr bufmgr, tbm_bo bo)
839 {
840         tbm_bo bo2 = NULL;
841
842         TBM_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(gBufMgr), NULL);
843         TBM_RETURN_VAL_IF_FAIL(bufmgr == gBufMgr, NULL);
844
845         if (LIST_IS_EMPTY(&bufmgr->bo_list))
846                 return NULL;
847
848         LIST_FOR_EACH_ENTRY(bo2, &bufmgr->bo_list, item_link) {
849                 if (tbm_module_compare_bo_data(bufmgr->module, bo2->bo_data, bo->bo_data))
850                         return bo2;
851         }
852
853         return NULL;
854 }
855
856 tbm_bo
857 tbm_bufmgr_internal_alloc_bo(tbm_bufmgr bufmgr, int size, int flags, tbm_error_e *error)
858 {
859         tbm_bo bo;
860         tbm_bo_data *bo_data;
861
862         _tbm_bufmgr_check_bo_cnt(bufmgr);
863
864         bo = calloc(1, sizeof(struct _tbm_bo));
865         if (!bo) {
866                 /* LCOV_EXCL_START */
867                 TBM_ERR("memory allocationc failed.");
868                 *error = TBM_ERROR_OUT_OF_MEMORY;
869                 return NULL;
870                 /* LCOV_EXCL_STOP */
871         }
872
873         bo_data = tbm_module_alloc_bo_data(bufmgr->module, bo, size, flags, error);
874         if (!bo_data) {
875                 /* LCOV_EXCL_START */
876                 TBM_ERR("tbm_module_alloc_bo_data failed. size:%d flags:%s error:%d", size, _tbm_flag_to_str(flags), *error);
877                 free(bo);
878                 return NULL;
879                 /* LCOV_EXCL_STOP */
880         }
881         bo->bo_data = bo_data;
882
883         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
884
885         return bo;
886 }
887
888
889 /* LCOV_EXCL_START */
890
891 tbm_bo
892 tbm_bufmgr_internal_alloc_bo_with_format(tbm_bufmgr bufmgr, int format, int bo_idx, int width,
893                                                 int height, int bpp, tbm_bo_memory_type flags, tbm_error_e *error)
894 {
895         tbm_bo bo = NULL;
896
897         _tbm_bufmgr_mutex_lock();
898         _tbm_set_last_result(TBM_ERROR_NONE);
899
900         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
901
902         _tbm_bufmgr_check_bo_cnt(bufmgr);
903
904         bo = calloc(1, sizeof(struct _tbm_bo));
905         if (!bo) {
906                 /* LCOV_EXCL_START */
907                 TBM_ERR("memory allocationc failed.");
908                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
909                 /* LCOV_EXCL_STOP */
910                 goto fail;
911         }
912
913         bo->bo_data = tbm_module_alloc_bo_data_with_format(bufmgr->module, format, bo_idx, width, height, bpp, flags, error);
914         if (!bo->bo_data) {
915                 /* LCOV_EXCL_START */
916                 _tbm_set_last_result(*error);
917                 /* LCOV_EXCL_STOP */
918                 goto fail;
919         }
920
921         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
922
923         _tbm_bufmgr_mutex_unlock();
924
925         return bo;
926
927 fail:
928         if (bo)
929                 free(bo);
930         _tbm_bufmgr_mutex_unlock();
931
932         return NULL;
933 }
934
935 tbm_bo
936 tbm_bufmgr_internal_alloc_bo_with_bo_data(tbm_bufmgr bufmgr, tbm_bo_data *bo_data, int flags)
937 {
938         tbm_bo bo, bo2 = NULL;
939
940         _tbm_bufmgr_mutex_lock();
941         _tbm_set_last_result(TBM_ERROR_NONE);
942
943         TBM_BUFMGR_RETURN_VAL_IF_FAIL(TBM_BUFMGR_IS_VALID(bufmgr), NULL);
944         TBM_BUFMGR_RETURN_VAL_IF_FAIL(bo_data, NULL);
945
946         _tbm_bufmgr_check_bo_cnt(bufmgr);
947
948         bo = calloc(1, sizeof(struct _tbm_bo));
949         if (!bo) {
950                 /* LCOV_EXCL_START */
951                 TBM_ERR("memory allocationc failed.");
952                 _tbm_set_last_result(TBM_ERROR_OUT_OF_MEMORY);
953                 _tbm_bufmgr_mutex_unlock();
954                 return NULL;
955                 /* LCOV_EXCL_STOP */
956         }
957         bo->bo_data = bo_data;
958         bo->get_from_surface_data = 1;
959
960         // return an existed bo if the bo is already created with the same bo_data.
961         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
962         if (bo2) {
963                 bo2->ref_cnt++;
964                 free(bo);
965                 _tbm_bufmgr_mutex_unlock();
966                 return bo2;
967         }
968
969         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
970
971         TBM_TRACE_BO("bo(%p) refcnt(%d), flag(%s)", bo, bo->ref_cnt, _tbm_flag_to_str(bo->flags));
972
973         _tbm_bufmgr_mutex_unlock();
974
975         return bo;
976 }
977
978 tbm_bo
979 tbm_bufmgr_internal_import_bo_with_key(tbm_bufmgr bufmgr, unsigned int key, tbm_error_e *error)
980 {
981         tbm_bo bo, bo2;
982         int flags;
983
984         _tbm_bufmgr_check_bo_cnt(bufmgr);
985
986         bo = calloc(1, sizeof(struct _tbm_bo));
987         if (!bo) {
988                 /* LCOV_EXCL_START */
989                 TBM_ERR("memory allocationc failed.");
990                 *error = TBM_ERROR_OUT_OF_MEMORY;
991                 return NULL;
992                 /* LCOV_EXCL_STOP */
993         }
994
995         bo->bo_data = tbm_module_import_bo_data_with_key(bufmgr->module, bo, key, error);
996         if (!bo->bo_data) {
997                 /* LCOV_EXCL_START */
998                 TBM_ERR("tbm_module_import_bo_data_with_key failed. tbm_key:%d", key);
999                 free(bo);
1000                 return NULL;
1001                 /* LCOV_EXCL_STOP */
1002         }
1003
1004         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
1005         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
1006         if (bo2) {
1007                 TBM_TRACE_BO("find bo(%p) ref(%d) key(%d) flag(%s) in list",
1008                                         bo2, bo2->ref_cnt, key, _tbm_flag_to_str(bo2->flags));
1009                 bo2->ref_cnt++;
1010                 free(bo);
1011                 return bo2;
1012         }
1013
1014         flags = tbm_bo_data_get_memory_types(bo->bo_data, error);
1015         if (*error != TBM_ERROR_NONE) {
1016                 TBM_ERR("fail to get the bo flags(memory_types)");
1017                 flags = TBM_BO_DEFAULT;
1018         }
1019
1020         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
1021
1022         return bo;
1023 }
1024
1025 tbm_bo
1026 tbm_bufmgr_internal_import_bo_with_fd(tbm_bufmgr bufmgr, tbm_fd fd, tbm_error_e *error)
1027 {
1028         tbm_bo bo, bo2;
1029         int flags;
1030
1031         _tbm_bufmgr_check_bo_cnt(bufmgr);
1032
1033         bo = calloc(1, sizeof(struct _tbm_bo));
1034         if (!bo) {
1035                 /* LCOV_EXCL_START */
1036                 TBM_ERR("memory allocationc failed.");
1037                 *error = TBM_ERROR_OUT_OF_MEMORY;
1038                 return NULL;
1039                 /* LCOV_EXCL_STOP */
1040         }
1041
1042         bo->bo_data = tbm_module_import_bo_data_with_fd(bufmgr->module, bo, fd, error);
1043         if (!bo->bo_data) {
1044                 /* LCOV_EXCL_START */
1045                 TBM_ERR("tbm_module_import_bo_data_with_fd failed. tbm_fd:%d", fd);
1046                 free(bo);
1047                 return NULL;
1048                 /* LCOV_EXCL_STOP */
1049         }
1050
1051         // return the existed bo2 if bo->bo_data and bo2->bo_data is the same
1052         bo2 = tbm_bufmgr_internal_find_bo(bufmgr, bo);
1053         if (bo2) {
1054                 TBM_TRACE_BO("find bo(%p) ref(%d) fd(%d) flag(%s) in list",
1055                                         bo2, bo2->ref_cnt, fd, _tbm_flag_to_str(bo2->flags));
1056                 bo2->ref_cnt++;
1057                 free(bo);
1058                 return bo2;
1059         }
1060
1061         flags = tbm_bo_data_get_memory_types(bo->bo_data, error);
1062         if (*error != TBM_ERROR_NONE) {
1063                 TBM_ERR("fail to get the bo flags(memory_types)");
1064                 flags = TBM_BO_DEFAULT;
1065         }
1066
1067         _tbm_bufmgr_initialize_bo(bufmgr, bo, flags);
1068
1069         return bo;
1070 }
1071
1072 /* LCOV_EXCL_STOP */