Package version up to 3.0.5
[platform/adaptation/emulator/libtbm-vigs.git] / src / libtbm-vigs / tbm_bufmgr_vigs.c
1 /*
2  * buffer manager for libtbm-vigs
3  *
4  * Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact :
7  * Stanislav Vorobiov <s.vorobiov@samsung.com>
8  * Jinhyung Jo <jinhyung.jo@samsung.com>
9  * Sangho Park <sangho1206.park@samsung.com>
10  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this software and associated documentation files (the "Software"), to deal
14  * in the Software without restriction, including without limitation the rights
15  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  * copies of the Software, and to permit persons to whom the Software is
17  * furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in
20  * all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28  * THE SOFTWARE.
29  *
30  * Contributors:
31  * - S-Core Co., Ltd
32  *
33  */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include "vigs.h"
40 #include <string.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <errno.h>
45 #include <xf86drm.h>
46 #include <tbm_backend.h>
47 #include <tbm_drm_helper.h>
48 #include <tbm_log.h>
49
50 #define STRERR_BUFSIZE 128
51
52 #define VIGS_DRM_NAME "vigs"
53
54 /* global singleton drm_dev. this is shared with yagl. */
55 struct vigs_drm_device *g_drm_dev = NULL;
56
57 static uint32_t tbm_bufmgr_vigs_color_format_list[] = {
58         TBM_FORMAT_RGB888,
59         TBM_FORMAT_ARGB8888,
60         TBM_FORMAT_RGBA8888,
61         TBM_FORMAT_XRGB8888,
62         TBM_FORMAT_XBGR8888,
63         TBM_FORMAT_NV21,
64         TBM_FORMAT_NV61,
65         TBM_FORMAT_YUV420,
66 };
67
68 typedef struct _tbm_bufmgr_vigs *tbm_bufmgr_vigs;
69 typedef struct _tbm_bo_vigs *tbm_bo_vigs;
70
71 /* tbm buffor object for vigs */
72 struct _tbm_bo_vigs {
73         struct vigs_drm_surface *sfc;
74
75         tbm_bufmgr_vigs bufmgr_vigs;
76 };
77
78 /* tbm bufmgr private for vigs */
79 struct _tbm_bufmgr_vigs {
80         struct vigs_drm_device *drm_dev;
81         void *hash_bos;
82
83         tbm_backend_bufmgr_func *bufmgr_func;
84         tbm_backend_bo_func *bo_func;
85
86         tbm_bufmgr bufmgr;
87 };
88
89 static int _tbm_vigs_open_drm(void)
90 {
91         int fd = -1;
92
93         fd = drmOpen(VIGS_DRM_NAME, NULL);
94         if (fd < 0) {
95                 TBM_ERR("open vigs drm device failed");
96                 return -1;
97         }
98
99         return fd;
100 }
101
102 static unsigned int
103 _get_name(int fd, unsigned int gem)
104 {
105         struct drm_gem_flink arg = {0,};
106
107         arg.handle = gem;
108         if (drmIoctl(fd, DRM_IOCTL_GEM_FLINK, &arg)) {
109                 TBM_ERR("fail to DRM_IOCTL_GEM_FLINK gem:%d", gem);
110                 return 0;
111         }
112
113         return (unsigned int)arg.name;
114 }
115
116 static tbm_bo_handle get_tbm_bo_handle(struct vigs_drm_surface *sfc, int device)
117 {
118         tbm_bo_handle bo_handle;
119         int ret;
120         struct vigs_drm_gem *gem = &sfc->gem;
121         char buf[STRERR_BUFSIZE];
122
123         memset(&bo_handle, 0, sizeof(bo_handle));
124
125         switch (device) {
126         case TBM_DEVICE_DEFAULT:
127         case TBM_DEVICE_2D:
128                 bo_handle.u32 = gem->handle;
129                 break;
130         case TBM_DEVICE_CPU:
131                 ret = vigs_drm_gem_map(gem, 1);
132
133                 if (ret == 0)
134                         bo_handle.ptr = gem->vaddr;
135                 else
136                         TBM_ERR("vigs_drm_gem_map failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
137
138                 break;
139         case TBM_DEVICE_3D:
140                 bo_handle.ptr = (void *)sfc;
141                 break;
142         case TBM_DEVICE_MM:
143                 TBM_ERR("TBM_DEVICE_MM not supported");
144                 break;
145         default:
146                 TBM_ERR("%d not supported", device);
147                 break;
148         }
149
150         return bo_handle;
151 }
152
153 static tbm_bufmgr_capability
154 tbm_vigs_bufmgr_get_capabilities(tbm_backend_bufmgr_data *bufmgr_data, tbm_error_e *error)
155 {
156         tbm_bufmgr_capability capabilities = TBM_BUFMGR_CAPABILITY_NONE;
157
158         capabilities = TBM_BUFMGR_CAPABILITY_SHARE_KEY|TBM_BUFMGR_CAPABILITY_SHARE_FD;
159
160         if (error)
161                 *error = TBM_ERROR_NONE;
162
163         return capabilities;
164 }
165
166 static tbm_error_e
167 tbm_vigs_bufmgr_bind_native_display(tbm_backend_bufmgr_data *bufmgr_data, tbm_native_display *native_display)
168 {
169         tbm_bufmgr_vigs bufmgr_vigs = (tbm_bufmgr_vigs)bufmgr_data;
170         struct vigs_drm_device *drm_dev;
171         char *device_name;
172         int ret = 0;
173
174         if (bufmgr_vigs == NULL || bufmgr_vigs->drm_dev ==  NULL) {
175                 TBM_ERR("bufmgr_data is null\n");
176                 return TBM_ERROR_INVALID_PARAMETER;
177         }
178
179         drm_dev = bufmgr_vigs->drm_dev;
180
181         device_name = drmGetDeviceNameFromFd(drm_dev->fd);
182         if (!device_name) {
183                 TBM_ERR("drmGetDeviceNameFromFd failed");
184                 return TBM_ERROR_INVALID_OPERATION;
185         }
186
187         ret = tbm_drm_helper_wl_auth_server_init(native_display, drm_dev->fd, device_name, 0);
188         if (!ret) {
189                 TBM_ERR("tbm_drm_helper_wl_auth_server_init failed");
190                 free(device_name);
191                 return TBM_ERROR_INVALID_OPERATION;
192         }
193
194         free(device_name);
195
196         return TBM_ERROR_NONE;
197 }
198
199 static tbm_error_e
200 tbm_vigs_bufmgr_get_supported_formats(tbm_backend_bufmgr_data *bufmgr_data,
201                                                         uint32_t **formats, uint32_t *num)
202 {
203         tbm_bufmgr_vigs bufmgr_vigs = (tbm_bufmgr_vigs)bufmgr_data;
204         uint32_t *color_formats;
205
206         if (!bufmgr_vigs)
207                 return TBM_ERROR_INVALID_PARAMETER;
208
209         color_formats = (uint32_t *) calloc(1, sizeof(tbm_bufmgr_vigs_color_format_list));
210         if (!color_formats)
211                 return TBM_ERROR_OUT_OF_MEMORY;
212
213         memcpy(color_formats, tbm_bufmgr_vigs_color_format_list, sizeof(tbm_bufmgr_vigs_color_format_list));
214
215         *formats = color_formats;
216         *num = sizeof(tbm_bufmgr_vigs_color_format_list) / sizeof(tbm_bufmgr_vigs_color_format_list[0]);
217
218         return TBM_ERROR_NONE;
219 }
220
221 static tbm_error_e
222 tbm_vigs_bufmgr_get_plane_data(tbm_backend_bufmgr_data *bufmgr_data,
223                                                          tbm_format format, int plane_idx, int width,
224                                                          int height, uint32_t * size, uint32_t * offset,
225                                                          uint32_t * pitch, int *bo_idx)
226 {
227         tbm_bufmgr_vigs bufmgr_vigs = (tbm_bufmgr_vigs)bufmgr_data;
228
229         *size = 0;
230         *offset = 0;
231         *pitch = 0;
232         *bo_idx = 0;
233
234         if (!bufmgr_vigs)
235                 return TBM_ERROR_INVALID_PARAMETER;
236
237         switch (format) {
238         case TBM_FORMAT_RGB888:
239                 *size = width * height * 3;
240                 *offset = 0;
241                 *pitch = width * 3;
242                 *bo_idx = 0;
243                 return TBM_ERROR_NONE;
244         case TBM_FORMAT_XRGB8888:
245         case TBM_FORMAT_XBGR8888:
246         case TBM_FORMAT_ARGB8888:
247         case TBM_FORMAT_RGBA8888:
248                 *size = width * height * 4;
249                 *offset = 0;
250                 *pitch = width * 4;
251                 *bo_idx = 0;
252                 return TBM_ERROR_NONE;
253         case TBM_FORMAT_NV21:
254                 if (plane_idx == 0) {
255                         *size = width * height;
256                         *offset = 0;
257                         *pitch = width;
258                         *bo_idx = 0;
259                 } else if (plane_idx == 1) {
260                         *size = width * (height >> 1);
261                         *offset = width * height;
262                         *pitch = width;
263                         *bo_idx = 0;
264                 } else {
265                         return TBM_ERROR_INVALID_PARAMETER;
266                 }
267                 return TBM_ERROR_NONE;
268         case TBM_FORMAT_NV61:
269                 if (plane_idx == 0) {
270                         *size = width * height;
271                         *offset = 0;
272                         *pitch = width;
273                         *bo_idx = 0;
274                 } else if (plane_idx == 1) {
275                         *size = width * height;
276                         *offset = width * height;
277                         *pitch = width;
278                         *bo_idx = 0;
279                 } else {
280                         return TBM_ERROR_INVALID_PARAMETER;
281                 }
282                 return TBM_ERROR_NONE;
283         case TBM_FORMAT_YUV420:
284                 if (plane_idx == 0) {
285                         *size = width * height;
286                         *offset = 0;
287                         *pitch = width;
288                         *bo_idx = 0;
289                 } else if (plane_idx == 1) {
290                         *size = (width * height) >> 2;
291                         *offset = width * height;
292                         *pitch = width >> 1;
293                         *bo_idx = 0;
294                 } else if (plane_idx == 2) {
295                         *size = (width * height) >> 2;
296                         *offset = (width * height) + (width * height >> 2);
297                         *pitch = width >> 1;
298                         *bo_idx = 0;
299                 } else {
300                         return TBM_ERROR_INVALID_PARAMETER;
301                 }
302                 return TBM_ERROR_NONE;
303         default:
304                 return TBM_ERROR_INVALID_PARAMETER;
305         }
306 }
307
308 static tbm_backend_bo_data *
309 tbm_vigs_bufmgr_alloc_bo(tbm_backend_bufmgr_data *bufmgr_data, unsigned int size,
310                                         tbm_bo_memory_type flags, tbm_error_e *error)
311 {
312         tbm_bufmgr_vigs bufmgr_vigs = (tbm_bufmgr_vigs)bufmgr_data;
313         tbm_bo_vigs bo_vigs;
314         struct vigs_drm_device *drm_dev;
315         struct vigs_drm_surface *sfc;
316         uint32_t width = 2048, height;
317         int ret;
318         char buf[STRERR_BUFSIZE];
319
320         if (bufmgr_vigs == NULL || bufmgr_vigs->drm_dev ==  NULL) {
321                 TBM_ERR("bufmgr_data is null\n");
322                 if (error)
323                         *error = TBM_ERROR_INVALID_PARAMETER;
324                 return NULL;
325         }
326
327         drm_dev = bufmgr_vigs->drm_dev;
328
329         height = ((uint32_t) size + (width * 4) - 1) / (width * 4);
330
331         ret = vigs_drm_surface_create(drm_dev, width, height, width * 4, vigs_drm_surface_bgra8888, 0, &sfc);
332         if (ret != 0) {
333                 TBM_ERR("vigs_drm_suface_create failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
334                 if (error)
335                         *error = TBM_ERROR_INVALID_PARAMETER;
336                 return NULL;
337         }
338
339         bo_vigs = calloc(1, sizeof(struct _tbm_bo_vigs));
340         if (!bo_vigs) {
341                 TBM_ERR("fail to allocate the bo_vigs private\n");
342                 vigs_drm_gem_unref(&sfc->gem);
343                 if (error)
344                         *error = TBM_ERROR_OUT_OF_MEMORY;
345                 return NULL;
346         }
347         bo_vigs->bufmgr_vigs = bufmgr_vigs;
348         bo_vigs->sfc = sfc;
349
350         ret = vigs_drm_gem_get_name(&sfc->gem);
351         if (ret != 0) {
352                 TBM_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
353                 vigs_drm_gem_unref(&sfc->gem);
354                 free(bo_vigs);
355                 if (error)
356                         *error = TBM_ERROR_INVALID_OPERATION;
357                 return 0;
358         }
359
360         if (drmHashInsert(bufmgr_vigs->hash_bos, bo_vigs->sfc->gem.name, (void *)bo_vigs) < 0)
361                 TBM_ERR("Cannot insert bo_vigs to Hash(%d)\n", bo_vigs->sfc->gem.name);
362
363         TBM_DBG("size = %d, flags = 0x%X", size, flags);
364
365         if (error)
366                 *error = TBM_ERROR_NONE;
367
368         return (tbm_backend_bo_data *)bo_vigs;
369 }
370
371 static tbm_backend_bo_data *
372 tbm_bufmgr_vigs_alloc_bo_with_format(tbm_backend_bufmgr_data *bufmgr_data, int format,  int bo_idx,
373                                                                 int width, int height, tbm_bo_memory_type flags, tbm_error_e *error)
374 {
375         tbm_bufmgr_vigs bufmgr_vigs = (tbm_bufmgr_vigs)bufmgr_data;
376         tbm_bo_vigs bo_vigs;
377         struct vigs_drm_device *drm_dev;
378         struct vigs_drm_surface *sfc;
379         int ret;
380         char buf[STRERR_BUFSIZE];
381
382         if (bufmgr_vigs == NULL || bufmgr_vigs->drm_dev ==  NULL) {
383                 TBM_ERR("bufmgr_data is null\n");
384                 if (error)
385                         *error = TBM_ERROR_INVALID_PARAMETER;
386                 return NULL;
387         }
388
389         if (bo_idx != 0) {
390                 TBM_ERR("Not supported bo idx");
391                 if (error)
392                         *error = TBM_ERROR_INVALID_PARAMETER;
393                 return NULL;
394         }
395
396         drm_dev = bufmgr_vigs->drm_dev;
397
398         switch (format) {
399         case TBM_FORMAT_RGB888:
400                 ret = vigs_drm_surface_create(drm_dev, width, height, width * 3, vigs_drm_surface_bgra8888, 0, &sfc);
401                 break;
402         case TBM_FORMAT_XRGB8888:
403         case TBM_FORMAT_XBGR8888:
404                 ret = vigs_drm_surface_create(drm_dev, width, height, width * 4, vigs_drm_surface_bgra8888, 0, &sfc);
405                 break;
406         case TBM_FORMAT_ARGB8888:
407         case TBM_FORMAT_RGBA8888:
408                 ret = vigs_drm_surface_create(drm_dev, width, height, width * 4, vigs_drm_surface_bgra8888, 0, &sfc);
409                 break;
410         case TBM_FORMAT_NV21:
411                 ret = vigs_drm_surface_create(drm_dev, width, height * 3 >> 1, width, vigs_drm_surface_bgra8888, 0, &sfc);
412                 break;
413         case TBM_FORMAT_NV61:
414                 ret = vigs_drm_surface_create(drm_dev, width, height * 2, width, vigs_drm_surface_bgra8888, 0, &sfc);
415                 break;
416         case TBM_FORMAT_YUV420:
417                 ret = vigs_drm_surface_create(drm_dev, width >> 2, height * 3 >> 1, width, vigs_drm_surface_bgra8888, 0, &sfc);
418                 break;
419         default:
420                 TBM_ERR("Not supported format");
421                 if (error)
422                         *error = TBM_ERROR_INVALID_PARAMETER;
423                 return NULL;
424         }
425
426         if (ret != 0) {
427                 TBM_ERR("vigs_drm_suface_create failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
428                 if (error)
429                         *error = TBM_ERROR_INVALID_PARAMETER;
430                 return NULL;
431         }
432
433         bo_vigs = calloc(1, sizeof(struct _tbm_bo_vigs));
434         if (!bo_vigs) {
435                 TBM_ERR("fail to allocate the bo_vigs private\n");
436                 vigs_drm_gem_unref(&sfc->gem);
437                 if (error)
438                         *error = TBM_ERROR_OUT_OF_MEMORY;
439                 return NULL;
440         }
441         bo_vigs->bufmgr_vigs = bufmgr_vigs;
442         bo_vigs->sfc = sfc;
443
444         ret = vigs_drm_gem_get_name(&sfc->gem);
445         if (ret != 0) {
446                 TBM_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
447                 vigs_drm_gem_unref(&sfc->gem);
448                 free(bo_vigs);
449                 if (error)
450                         *error = TBM_ERROR_INVALID_OPERATION;
451                 return 0;
452         }
453
454         if (drmHashInsert(bufmgr_vigs->hash_bos, bo_vigs->sfc->gem.name, (void *)bo_vigs) < 0)
455                 TBM_ERR("Cannot insert bo_vigs to Hash(%d)\n", bo_vigs->sfc->gem.name);
456
457         TBM_DBG("width = %d, height = %d, format = %x, flags = 0x%X bo_idx = %d",
458                         width, height, format, flags, bo_idx);
459
460         if (error)
461                 *error = TBM_ERROR_NONE;
462
463         return (tbm_backend_bo_data *)bo_vigs;
464 }
465
466 static tbm_backend_bo_data *
467 tbm_vigs_bufmgr_import_fd(tbm_backend_bufmgr_data *bufmgr_data, tbm_fd key, tbm_error_e *error)
468 {
469         tbm_bufmgr_vigs bufmgr_vigs = (tbm_bufmgr_vigs)bufmgr_data;
470         tbm_bo_vigs bo_vigs;
471         struct vigs_drm_device *drm_dev;
472         struct vigs_drm_surface *sfc;
473         int ret;
474         char buf[STRERR_BUFSIZE];
475         struct drm_prime_handle arg = {0, };
476         unsigned int gem;
477         unsigned int name;
478
479         if (bufmgr_vigs == NULL || bufmgr_vigs->drm_dev ==  NULL) {
480                 TBM_ERR("bufmgr_data is null\n");
481                 if (error)
482                         *error = TBM_ERROR_INVALID_PARAMETER;
483                 return NULL;
484         }
485
486         drm_dev = bufmgr_vigs->drm_dev;
487
488         arg.fd = key;
489         if (drmIoctl(bufmgr_vigs->drm_dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &arg)) {
490                 TBM_ERR("Cannot get gem handle from fd:%d (%s)\n",
491                                arg.fd, strerror_r(errno, buf, STRERR_BUFSIZE));
492                 if (error)
493                         *error = TBM_ERROR_INVALID_OPERATION;
494                 return NULL;
495         }
496         gem = arg.handle;
497
498         name = _get_name(bufmgr_vigs->drm_dev->fd, gem);
499         if (!name) {
500                 TBM_ERR("Cannot get name from gem:%d, fd:%d (%s)\n",
501                                gem, key, strerror_r(errno, buf, STRERR_BUFSIZE));
502                 if (error)
503                         *error = TBM_ERROR_INVALID_OPERATION;
504                 return NULL;
505         }
506
507         ret = drmHashLookup(bufmgr_vigs->hash_bos, name, (void **)&bo_vigs);
508         if (ret == 0) {
509                 if (gem == bo_vigs->sfc->gem.handle) {
510                         if (error)
511                                 *error = TBM_ERROR_NONE;
512                         return (tbm_backend_bo_data *)bo_vigs;
513                 }
514         }
515
516         ret = vigs_drm_prime_import_fd(drm_dev, key, &sfc);
517         if (ret != 0) {
518                 TBM_ERR("vigs_drm_prime_import_fd failed for key %d: %s",
519                         key, strerror_r(errno, buf, STRERR_BUFSIZE));
520                 if (error)
521                         *error = TBM_ERROR_INVALID_OPERATION;
522                 return NULL;
523         }
524
525         bo_vigs = calloc(1, sizeof(struct _tbm_bo_vigs));
526         if (!bo_vigs) {
527                 TBM_ERR("fail to allocate the bo_vigs private\n");
528                 vigs_drm_gem_unref(&sfc->gem);
529                 if (error)
530                         *error = TBM_ERROR_OUT_OF_MEMORY;
531                 return NULL;
532         }
533         bo_vigs->bufmgr_vigs = bufmgr_vigs;
534         bo_vigs->sfc = sfc;
535
536         ret = vigs_drm_gem_get_name(&sfc->gem);
537         if (ret != 0) {
538                 TBM_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
539                 vigs_drm_gem_unref(&sfc->gem);
540                 free(bo_vigs);
541                 if (error)
542                         *error = TBM_ERROR_INVALID_OPERATION;
543                 return 0;
544         }
545
546         if (drmHashInsert(bufmgr_vigs->hash_bos, bo_vigs->sfc->gem.name, (void *)bo_vigs) < 0)
547                 TBM_ERR("Cannot insert bo_vigs to Hash(%d)\n", bo_vigs->sfc->gem.name);
548
549         TBM_DBG("bo_vigs = %p, key = %u handle = %u", bo_vigs, key, sfc->gem.handle);
550
551         if (error)
552                 *error = TBM_ERROR_NONE;
553
554         return (tbm_backend_bo_data *)bo_vigs;
555 }
556
557 static tbm_backend_bo_data *
558 tbm_vigs_bufmgr_import_key(tbm_backend_bufmgr_data *bufmgr_data, tbm_key key, tbm_error_e *error)
559 {
560         tbm_bufmgr_vigs bufmgr_vigs = (tbm_bufmgr_vigs)bufmgr_data;
561         tbm_bo_vigs bo_vigs;
562         struct vigs_drm_device *drm_dev;
563         int ret;
564         struct vigs_drm_surface *sfc;
565         char buf[STRERR_BUFSIZE];
566
567         if (bufmgr_vigs == NULL || bufmgr_vigs->drm_dev ==  NULL) {
568                 TBM_ERR("bufmgr_data is null\n");
569                 if (error)
570                         *error = TBM_ERROR_INVALID_PARAMETER;
571                 return NULL;
572         }
573
574         drm_dev = bufmgr_vigs->drm_dev;
575
576         ret = drmHashLookup(bufmgr_vigs->hash_bos, key, (void **)&bo_vigs);
577         if (ret == 0) {
578                 if (error)
579                         *error = TBM_ERROR_NONE;
580                 return (tbm_backend_bo_data *)bo_vigs;
581         }
582
583         ret = vigs_drm_surface_open(drm_dev, key, &sfc);
584         if (ret != 0) {
585                 TBM_ERR("vigs_drm_surface_open failed for key %u: %s",
586                         key, strerror_r(errno, buf, STRERR_BUFSIZE));
587                 if (error)
588                         *error = TBM_ERROR_INVALID_OPERATION;
589                 return NULL;
590         }
591
592         bo_vigs = calloc(1, sizeof(struct _tbm_bo_vigs));
593         if (!bo_vigs) {
594                 TBM_ERR("fail to allocate the bo_vigs private\n");
595                 vigs_drm_gem_unref(&sfc->gem);
596                 if (error)
597                         *error = TBM_ERROR_OUT_OF_MEMORY;
598                 return NULL;
599         }
600         bo_vigs->bufmgr_vigs = bufmgr_vigs;
601         bo_vigs->sfc = sfc;
602
603         ret = vigs_drm_gem_get_name(&sfc->gem);
604         if (ret != 0) {
605                 TBM_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
606                 vigs_drm_gem_unref(&sfc->gem);
607                 free(bo_vigs);
608                 if (error)
609                         *error = TBM_ERROR_INVALID_OPERATION;
610                 return 0;
611         }
612
613         if (drmHashInsert(bufmgr_vigs->hash_bos, bo_vigs->sfc->gem.name, (void *)bo_vigs) < 0)
614                 TBM_ERR("Cannot insert bo_vigs to Hash(%d)\n", bo_vigs->sfc->gem.name);
615
616         TBM_DBG("bo_vigs = %p, key = %u handle = %u", bo_vigs, key, sfc->gem.handle);
617
618         if (error)
619                 *error = TBM_ERROR_NONE;
620
621         return (tbm_backend_bo_data *)bo_vigs;
622 }
623
624 static void
625 tbm_vigs_bo_free(tbm_backend_bo_data *bo_data)
626 {
627         tbm_bo_vigs bo_vigs = (tbm_bo_vigs)bo_data;
628         tbm_bo_vigs temp;
629         struct vigs_drm_surface *sfc;
630         tbm_bufmgr_vigs bufmgr_vigs;
631         int ret;
632
633         if (!bo_data)
634                 return;
635
636         bufmgr_vigs = bo_vigs->bufmgr_vigs;
637         if (!bufmgr_vigs)
638                 return;
639
640         TBM_DBG("bo_vigs = %p", bo_vigs);
641
642         sfc = bo_vigs->sfc;
643
644         /* delete bo from hash */
645         ret = drmHashLookup(bufmgr_vigs->hash_bos, sfc->gem.name,
646                              (void **)&temp);
647         if (ret == 0)
648                 drmHashDelete(bufmgr_vigs->hash_bos, sfc->gem.name);
649         else
650                 TBM_ERR("Cannot find bo_vigs to Hash(%d), ret=%d\n", sfc->gem.name, ret);
651
652         vigs_drm_gem_unref(&sfc->gem);
653
654         free(bo_vigs);
655 }
656
657 static int
658 tbm_vigs_bo_get_size(tbm_backend_bo_data *bo_data, tbm_error_e *error)
659 {
660         tbm_bo_vigs bo_vigs = (tbm_bo_vigs)bo_data;
661         struct vigs_drm_surface *sfc;
662
663         if (!bo_vigs || !bo_vigs->sfc) {
664                 if (error)
665                         *error = TBM_ERROR_INVALID_PARAMETER;
666                 return 0;
667         }
668
669         TBM_DBG("bo_vigs = %p", bo_vigs);
670
671         sfc = bo_vigs->sfc;
672
673         if (error)
674                 *error = TBM_ERROR_NONE;
675
676         return sfc->gem.size;
677 }
678
679 static tbm_bo_memory_type
680 tbm_vigs_bo_get_memory_type(tbm_backend_bo_data *bo_data, tbm_error_e *error)
681 {
682         tbm_bo_vigs bo_vigs = (tbm_bo_vigs)bo_data;
683
684         if (!bo_vigs || !bo_vigs->sfc) {
685                 if (error)
686                         *error = TBM_ERROR_INVALID_PARAMETER;
687                 return TBM_BO_DEFAULT;
688         }
689
690         if (error)
691                 *error = TBM_ERROR_NONE;
692
693         return TBM_BO_DEFAULT;
694 }
695
696 static tbm_bo_handle
697 tbm_vigs_bo_get_handle(tbm_backend_bo_data *bo_data, tbm_bo_device_type device, tbm_error_e *error)
698 {
699         tbm_bo_vigs bo_vigs = (tbm_bo_vigs)bo_data;
700         struct vigs_drm_surface *sfc;
701         tbm_bo_handle handle;
702
703         if (!bo_vigs || !bo_vigs->sfc) {
704                 if (error)
705                         *error = TBM_ERROR_INVALID_PARAMETER;
706                 return (tbm_bo_handle) NULL;
707         }
708
709         sfc = bo_vigs->sfc;
710
711         TBM_DBG("bo_vigs = %p, device = %d", bo_vigs, device);
712
713         handle = get_tbm_bo_handle(sfc, device);
714         if (!handle.ptr) {
715                 if (error)
716                         *error = TBM_ERROR_INVALID_PARAMETER;
717                 return handle;
718         }
719
720         if (error)
721                 *error = TBM_ERROR_NONE;
722
723         return handle;
724 }
725
726 static tbm_bo_handle
727 tbm_vigs_bo_map(tbm_backend_bo_data *bo_data, tbm_bo_device_type device,
728                                 tbm_bo_access_option opt, tbm_error_e *error)
729 {
730         tbm_bo_vigs bo_vigs = (tbm_bo_vigs)bo_data;
731         struct vigs_drm_surface *sfc;
732         tbm_bo_handle handle;
733         uint32_t saf = 0;
734
735         if (!bo_vigs || !bo_vigs->sfc) {
736                 if (error)
737                         *error = TBM_ERROR_INVALID_PARAMETER;
738                 return (tbm_bo_handle) NULL;
739         }
740
741         sfc = bo_vigs->sfc;
742
743         TBM_DBG("bo_vigs = %p, device = %d, opt = %d", bo_vigs, device, opt);
744
745         handle = get_tbm_bo_handle(sfc, device);
746         if (!handle.ptr) {
747                 if (error)
748                         *error = TBM_ERROR_INVALID_PARAMETER;
749                 return handle;
750         }
751
752         if ((opt & TBM_OPTION_READ) != 0)
753                 saf |= VIGS_DRM_SAF_READ;
754
755         if ((opt & TBM_OPTION_WRITE) != 0)
756                 saf |= VIGS_DRM_SAF_WRITE;
757
758         vigs_drm_surface_start_access(sfc, saf);
759
760         if (error)
761                 *error = TBM_ERROR_NONE;
762
763         return handle;
764 }
765
766 static tbm_error_e
767 tbm_vigs_bo_unmap(tbm_backend_bo_data *bo_data)
768 {
769         tbm_bo_vigs bo_vigs = (tbm_bo_vigs)bo_data;
770         struct vigs_drm_surface *sfc;
771
772         if (!bo_vigs || !bo_vigs->sfc)
773                 return TBM_ERROR_INVALID_PARAMETER;
774
775         sfc = bo_vigs->sfc;
776
777         TBM_DBG("bo_vigs = %p", bo_vigs);
778
779         vigs_drm_surface_end_access(sfc, 1);
780
781         return TBM_ERROR_NONE;
782 }
783
784 static tbm_error_e
785 tbm_vigs_bo_lock(tbm_backend_bo_data *bo_data, tbm_bo_device_type device,
786                                 tbm_bo_access_option opt)
787 {
788         tbm_bo_vigs bo_vigs = (tbm_bo_vigs)bo_data;
789
790         if (!bo_vigs || !bo_vigs->sfc)
791                 return TBM_ERROR_INVALID_PARAMETER;
792
793         TBM_DBG("bo_vigs = %p", bo_vigs);
794
795         return TBM_ERROR_NONE;
796 }
797
798 static tbm_error_e
799 tbm_vigs_bo_unlock(tbm_backend_bo_data *bo_data)
800 {
801         tbm_bo_vigs bo_vigs = (tbm_bo_vigs)bo_data;
802
803         if (!bo_vigs || !bo_vigs->sfc)
804                 return TBM_ERROR_INVALID_PARAMETER;
805
806         TBM_DBG("bo_vigs = %p", bo_data);
807
808         return TBM_ERROR_NONE;
809 }
810
811 tbm_fd
812 tbm_vigs_bo_export_fd(tbm_backend_bo_data *bo_data, tbm_error_e *error)
813 {
814         tbm_bo_vigs bo_vigs = (tbm_bo_vigs)bo_data;
815         tbm_bufmgr_vigs bufmgr_vigs;
816         struct vigs_drm_surface *sfc;
817         struct vigs_drm_device *drm_dev;
818         int ret, fd = 0;
819         char buf[STRERR_BUFSIZE];
820
821         if (!bo_vigs || !bo_vigs->sfc) {
822                 if (error)
823                         *error = TBM_ERROR_INVALID_PARAMETER;
824                 return -1;
825         }
826
827         bufmgr_vigs = bo_vigs->bufmgr_vigs;
828         if (!bufmgr_vigs || !bufmgr_vigs->drm_dev) {
829                 if (error)
830                         *error = TBM_ERROR_INVALID_PARAMETER;
831                 return -1;
832         }
833
834         drm_dev = bufmgr_vigs->drm_dev;
835         sfc = bo_vigs->sfc;
836
837         ret = vigs_drm_prime_export_fd(drm_dev, sfc, &fd);
838         if (ret != 0) {
839                 TBM_ERR("vigs_drm_prime_export_fd failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
840                 if (error)
841                         *error = TBM_ERROR_INVALID_OPERATION;
842                 return -1;
843         }
844
845         TBM_DBG("    bo_vigs:%p, gem:%d(%d)\n", bo_vigs, sfc->gem);
846
847         if (error)
848                 *error = TBM_ERROR_NONE;
849
850         return (tbm_fd)fd;
851 }
852
853 static tbm_key
854 tbm_vigs_bo_export_key(tbm_backend_bo_data *bo_data, tbm_error_e *error)
855 {
856         tbm_bo_vigs bo_vigs = (tbm_bo_vigs)bo_data;
857         struct vigs_drm_surface *sfc;
858         int ret;
859         char buf[STRERR_BUFSIZE];
860
861         if (!bo_vigs || !bo_vigs->sfc) {
862                 if (error)
863                         *error = TBM_ERROR_INVALID_PARAMETER;
864                 return 0;
865         }
866
867         sfc = bo_vigs->sfc;
868
869         ret = vigs_drm_gem_get_name(&sfc->gem);
870         if (ret != 0) {
871                 TBM_ERR("vigs_drm_gem_get_name failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
872                 if (error)
873                         *error = TBM_ERROR_INVALID_OPERATION;
874                 return 0;
875         }
876
877         TBM_DBG("    bo_vigs:%p, gem:%d(%d)\n", bo_vigs, sfc->gem);
878
879         if (error)
880                 *error = TBM_ERROR_NONE;
881
882         return (tbm_key)sfc->gem.name;
883 }
884
885 static void
886 tbm_vigs_deinit(tbm_backend_bufmgr_data *bufmgr_data)
887 {
888         tbm_bufmgr_vigs bufmgr_vigs = (tbm_bufmgr_vigs)bufmgr_data;
889         struct vigs_drm_device *drm_dev;
890         tbm_error_e error;
891         tbm_bufmgr bufmgr;
892         unsigned long key;
893         void *value;
894
895         TBM_DBG("enter");
896
897         if (!bufmgr_vigs)
898                 return;
899
900         drm_dev = bufmgr_vigs->drm_dev;
901         if (!drm_dev)
902                 return;
903
904         bufmgr = bufmgr_vigs->bufmgr;
905         if (!bufmgr)
906                 return;
907
908         if (bufmgr_vigs->hash_bos) {
909                 while (drmHashFirst(bufmgr_vigs->hash_bos, &key, &value) > 0) {
910                         free(value);
911                         drmHashDelete(bufmgr_vigs->hash_bos, key);
912                 }
913
914                 drmHashDestroy(bufmgr_vigs->hash_bos);
915                 bufmgr_vigs->hash_bos = NULL;
916         }
917
918         if (tbm_backend_bufmgr_query_display_server(bufmgr, &error)) {
919                 tbm_drm_helper_wl_auth_server_deinit();
920                 tbm_drm_helper_unset_tbm_master_fd();
921         }
922
923         close(drm_dev->fd);
924
925         vigs_drm_device_destroy(drm_dev);
926
927         g_drm_dev = NULL;
928 }
929
930 static tbm_backend_bufmgr_data *
931 tbm_vigs_init(tbm_bufmgr bufmgr, tbm_error_e *error)
932 {
933         tbm_bufmgr_vigs bufmgr_vigs = NULL;
934         tbm_backend_bufmgr_func *bufmgr_func = NULL;
935         tbm_backend_bo_func *bo_func = NULL;
936         int ret = 0;
937         struct vigs_drm_device *drm_dev = NULL;
938         int drm_fd = -1;
939         tbm_error_e err;
940         char buf[STRERR_BUFSIZE];
941         int set_master = 0;
942
943         TBM_DBG("enter");
944
945         if (!bufmgr) {
946                 TBM_ERR("bufmgr is null.\n");
947                 if (error)
948                         *error = TBM_ERROR_INVALID_PARAMETER;
949                 return NULL;
950         }
951
952         bufmgr_vigs = calloc(1, sizeof(struct _tbm_bufmgr_vigs));
953         if (!bufmgr_vigs) {
954                 TBM_ERR("fail to alloc bufmgr_vigs!\n");
955                 if (error)
956                         *error = TBM_ERROR_OUT_OF_MEMORY;
957                 return NULL;
958         }
959
960         /* check the master_fd which already had opened */
961         drm_fd = tbm_drm_helper_get_master_fd();
962         if (drm_fd < 0) {
963                 drm_fd = _tbm_vigs_open_drm();
964                 if (drm_fd < 0) {
965                         TBM_ERR("fail to open drm!\n");
966                         if (error)
967                                 *error = TBM_ERROR_INVALID_OPERATION;
968                         goto fail_open_drm;
969                 }
970
971                 if (drmIsMaster(drm_fd)) {
972                         tbm_drm_helper_set_tbm_master_fd(drm_fd);
973                         set_master = 1;
974                         TBM_INFO("This is Master FD(%d) from open_drm.", drm_fd);
975                 } else {
976                         /* close the fd and get the authenticated fd from the master fd */
977                         close(drm_fd);
978                         drm_fd = -1;
979
980                         /* get the authenticated drm fd from the master fd */
981                         if (!tbm_drm_helper_get_auth_info(&(drm_fd), NULL, NULL)) {
982                                 TBM_ERR("fail to get auth drm info!\n");
983                                 if (error)
984                                         *error = TBM_ERROR_INVALID_OPERATION;
985                                 goto fail_get_auth_info;
986                         }
987                         TBM_INFO("This is Authenticated FD(%d)", drm_fd);
988                 }
989         } else {
990                 TBM_INFO("This is Master FD from tbm_drm_helper_get_master_fd(%d)", drm_fd);
991         }
992         tbm_drm_helper_set_fd(drm_fd);
993
994         ret = vigs_drm_device_create(drm_fd, &drm_dev);
995         if (ret != 0) {
996                 TBM_ERR("vigs_drm_device_create failed: %s", strerror_r(errno, buf, STRERR_BUFSIZE));
997                 if (error)
998                         *error = TBM_ERROR_INVALID_OPERATION;
999                 goto fail_create_vigs_drm_device;
1000         }
1001         bufmgr_vigs->drm_dev = drm_dev;
1002         g_drm_dev = drm_dev;
1003
1004         bufmgr_vigs->hash_bos = drmHashCreate();
1005
1006         /* alloc and register bufmgr_funcs */
1007         bufmgr_func = tbm_backend_bufmgr_alloc_bufmgr_func(bufmgr, &err);
1008         if (!bufmgr_func) {
1009                 TBM_ERR("fail to alloc bufmgr_func! err(%d)\n", err);
1010                 if (error)
1011                         *error = TBM_ERROR_OUT_OF_MEMORY;
1012                 goto fail_alloc_bufmgr_func;
1013         }
1014
1015         bufmgr_func->bufmgr_get_capabilities = tbm_vigs_bufmgr_get_capabilities;
1016         bufmgr_func->bufmgr_bind_native_display = tbm_vigs_bufmgr_bind_native_display;
1017         bufmgr_func->bufmgr_get_supported_formats = tbm_vigs_bufmgr_get_supported_formats;
1018         bufmgr_func->bufmgr_get_plane_data = tbm_vigs_bufmgr_get_plane_data;
1019         bufmgr_func->bufmgr_alloc_bo = tbm_vigs_bufmgr_alloc_bo;
1020         bufmgr_func->bufmgr_alloc_bo_with_format = tbm_bufmgr_vigs_alloc_bo_with_format;
1021         bufmgr_func->bufmgr_import_fd = tbm_vigs_bufmgr_import_fd;
1022         bufmgr_func->bufmgr_import_key = tbm_vigs_bufmgr_import_key;
1023
1024         err = tbm_backend_bufmgr_register_bufmgr_func(bufmgr, bufmgr_func);
1025         if (err != TBM_ERROR_NONE) {
1026                 TBM_ERR("fail to register bufmgr_func! err(%d)\n", err);
1027                 if (error)
1028                         *error = TBM_ERROR_INVALID_OPERATION;
1029                 goto fail_register_bufmgr_func;
1030         }
1031         bufmgr_vigs->bufmgr_func = bufmgr_func;
1032
1033         /* alloc and register bo_funcs */
1034         bo_func = tbm_backend_bufmgr_alloc_bo_func(bufmgr, &err);
1035         if (!bo_func) {
1036                 TBM_ERR("fail to alloc bo_func! err(%d)\n", err);
1037                 if (error)
1038                         *error = TBM_ERROR_OUT_OF_MEMORY;
1039                 goto fail_alloc_bo_func;
1040         }
1041
1042         bo_func->bo_free = tbm_vigs_bo_free;
1043         bo_func->bo_get_size = tbm_vigs_bo_get_size;
1044         bo_func->bo_get_memory_types = tbm_vigs_bo_get_memory_type;
1045         bo_func->bo_get_handle = tbm_vigs_bo_get_handle;
1046         bo_func->bo_map = tbm_vigs_bo_map;
1047         bo_func->bo_unmap = tbm_vigs_bo_unmap;
1048         bo_func->bo_lock = tbm_vigs_bo_lock;
1049         bo_func->bo_unlock = tbm_vigs_bo_unlock;
1050         bo_func->bo_export_fd = tbm_vigs_bo_export_fd;
1051         bo_func->bo_export_key = tbm_vigs_bo_export_key;
1052
1053         err = tbm_backend_bufmgr_register_bo_func(bufmgr, bo_func);
1054         if (err != TBM_ERROR_NONE) {
1055                 TBM_ERR("fail to register bo_func! err(%d)\n", err);
1056                 if (error)
1057                         *error = TBM_ERROR_INVALID_OPERATION;
1058                 goto fail_register_bo_func;
1059         }
1060         bufmgr_vigs->bo_func = bo_func;
1061
1062         TBM_INFO("initialized");
1063
1064         return (tbm_backend_bufmgr_data *)bufmgr_vigs;
1065
1066 fail_register_bo_func:
1067         tbm_backend_bufmgr_free_bo_func(bufmgr, bo_func);
1068 fail_alloc_bo_func:
1069 fail_register_bufmgr_func:
1070         tbm_backend_bufmgr_free_bufmgr_func(bufmgr, bufmgr_func);
1071 fail_alloc_bufmgr_func:
1072         drmHashDestroy(bufmgr_vigs->hash_bos);
1073         vigs_drm_device_destroy(drm_dev);
1074 fail_create_vigs_drm_device:
1075         if (set_master)
1076                 tbm_drm_helper_unset_tbm_master_fd();
1077         if (drm_fd >= 0)
1078                 close(drm_fd);
1079 fail_get_auth_info:
1080 fail_open_drm:
1081         if (bufmgr_vigs)
1082                 free(bufmgr_vigs);
1083         g_drm_dev = NULL;
1084         return NULL;
1085 }
1086
1087 tbm_backend_module tbm_backend_module_data = {
1088         "vigs",
1089         "Samsung",
1090         TBM_BACKEND_ABI_VERSION_3_0,
1091         tbm_vigs_init,
1092         tbm_vigs_deinit
1093 };
1094
1095 struct vigs_drm_device *
1096 tbm_vigs_get_drm_dev(void)
1097 {
1098         return g_drm_dev;
1099 }