e8b111f823b42c4e8571d1295dd874c2d9e085a1
[platform/adaptation/emulator/libtbm-vigs.git] / src / tbm_bufmgr_emulator.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 <tbm_bufmgr.h>
40 #include <tbm_bufmgr_backend.h>
41 #include <tbm_surface.h>
42 #include "vigs.h"
43 #include "tbm_emulator_log.h"
44 #include <string.h>
45 #include <stdlib.h>
46
47 static uint32_t tbm_bufmgr_emulator_color_format_list[] =
48 {
49     TBM_FORMAT_ARGB8888,
50     TBM_FORMAT_XRGB8888,
51     TBM_FORMAT_NV21,
52     TBM_FORMAT_NV61,
53     TBM_FORMAT_YUV420,
54 };
55
56 static tbm_bo_handle get_tbm_bo_handle(struct vigs_drm_gem *gem,
57                                        int device)
58 {
59     tbm_bo_handle bo_handle;
60     int ret;
61
62     memset(&bo_handle, 0, sizeof(bo_handle));
63
64     switch (device) {
65     case TBM_DEVICE_DEFAULT:
66     case TBM_DEVICE_2D:
67         bo_handle.u32 = gem->handle;
68         break;
69     case TBM_DEVICE_CPU:
70         ret = vigs_drm_gem_map(gem, 1);
71
72         if (ret == 0) {
73             bo_handle.ptr = gem->vaddr;
74         } else {
75             TBM_EMULATOR_LOG_ERROR("vigs_drm_gem_map failed: %s",
76                                    strerror(-ret));
77         }
78
79         break;
80     case TBM_DEVICE_3D:
81         TBM_EMULATOR_LOG_ERROR("TBM_DEVICE_3D not supported");
82         break;
83     case TBM_DEVICE_MM:
84         TBM_EMULATOR_LOG_ERROR("TBM_DEVICE_MM not supported");
85         break;
86     default:
87         TBM_EMULATOR_LOG_ERROR("%d not supported", device);
88         break;
89     }
90
91     return bo_handle;
92 }
93
94 static void tbm_bufmgr_emulator_deinit(void *priv)
95 {
96     struct vigs_drm_device *drm_dev = priv;
97
98     TBM_EMULATOR_LOG_DEBUG("enter");
99
100     vigs_drm_device_destroy(drm_dev);
101 }
102
103 static int tbm_bufmgr_emulator_bo_size(tbm_bo bo)
104 {
105     struct vigs_drm_surface *sfc;
106
107     TBM_EMULATOR_LOG_DEBUG("bo = %p", bo);
108
109     sfc = (struct vigs_drm_surface*)tbm_backend_get_bo_priv(bo);
110
111     return sfc->gem.size;
112 }
113
114 static void *tbm_bufmgr_emulator_bo_alloc(tbm_bo bo, int size, int flags)
115 {
116     struct vigs_drm_device *drm_dev;
117     struct vigs_drm_surface *sfc;
118     uint32_t width = 2048, height;
119     int ret;
120
121     TBM_EMULATOR_LOG_DEBUG("size = %d, flags = 0x%X", size, flags);
122
123     drm_dev = (struct vigs_drm_device*)tbm_backend_get_bufmgr_priv(bo);
124
125     height = ((uint32_t)size + (width * 4) - 1) / (width * 4);
126
127     ret = vigs_drm_surface_create(drm_dev,
128                                   width, height,
129                                   width * 4,
130                                   vigs_drm_surface_bgra8888, 0,
131                                   &sfc);
132
133     if (ret != 0) {
134         TBM_EMULATOR_LOG_ERROR("vigs_drm_suface_create failed: %s",
135                                strerror(-ret));
136         return NULL;
137     }
138
139     return sfc;
140 }
141
142 static void tbm_bufmgr_emulator_bo_free(tbm_bo bo)
143 {
144     struct vigs_drm_surface *sfc;
145
146     TBM_EMULATOR_LOG_DEBUG("bo = %p", bo);
147
148     sfc = (struct vigs_drm_surface*)tbm_backend_get_bo_priv(bo);
149
150     vigs_drm_gem_unref(&sfc->gem);
151 }
152
153 static void *tbm_bufmgr_emulator_bo_import(tbm_bo bo, unsigned int key)
154 {
155     struct vigs_drm_device *drm_dev;
156     int ret;
157     struct vigs_drm_surface *sfc;
158
159     TBM_EMULATOR_LOG_DEBUG("bo = %p, key = %u", bo, key);
160
161     drm_dev = (struct vigs_drm_device*)tbm_backend_get_bufmgr_priv(bo);
162
163     ret = vigs_drm_surface_open(drm_dev, key, &sfc);
164
165     if (ret != 0) {
166         TBM_EMULATOR_LOG_ERROR("vigs_drm_surface_open failed for key %u: %s",
167                                key,
168                                strerror(-ret));
169         return NULL;
170     }
171
172     TBM_EMULATOR_LOG_DEBUG("handle = %u", sfc->gem.handle);
173
174     return sfc;
175 }
176
177 static unsigned int tbm_bufmgr_emulator_bo_export(tbm_bo bo)
178 {
179     struct vigs_drm_surface *sfc;
180     int ret;
181
182     TBM_EMULATOR_LOG_DEBUG("bo = %p", bo);
183
184     sfc = (struct vigs_drm_surface*)tbm_backend_get_bo_priv(bo);
185
186     ret = vigs_drm_gem_get_name(&sfc->gem);
187
188     if (ret != 0) {
189         TBM_EMULATOR_LOG_ERROR("vigs_drm_gem_get_name failed: %s",
190                                strerror(-ret));
191         return 0;
192     }
193
194     return sfc->gem.name;
195 }
196
197 static tbm_bo_handle tbm_bufmgr_emulator_bo_get_handle(tbm_bo bo, int device)
198 {
199     struct vigs_drm_surface *sfc;
200
201     TBM_EMULATOR_LOG_DEBUG("bo = %p, device = %d", bo, device);
202
203     sfc = (struct vigs_drm_surface*)tbm_backend_get_bo_priv(bo);
204
205     return get_tbm_bo_handle(&sfc->gem, device);
206 }
207
208 static tbm_bo_handle tbm_bufmgr_emulator_bo_map(tbm_bo bo, int device, int opt)
209 {
210     struct vigs_drm_surface *sfc;
211     tbm_bo_handle handle;
212     uint32_t saf = 0;
213
214     TBM_EMULATOR_LOG_DEBUG("bo = %p, device = %d, opt = %d", bo, device, opt);
215
216     sfc = (struct vigs_drm_surface*)tbm_backend_get_bo_priv(bo);
217
218     handle = get_tbm_bo_handle(&sfc->gem, device);
219
220     if (!handle.ptr) {
221         return handle;
222     }
223
224     if ((opt & TBM_OPTION_READ) != 0) {
225         saf |= VIGS_DRM_SAF_READ;
226     }
227
228     if ((opt & TBM_OPTION_WRITE) != 0) {
229         saf |= VIGS_DRM_SAF_WRITE;
230     }
231
232     vigs_drm_surface_start_access(sfc, saf);
233
234     return handle;
235 }
236
237 static int tbm_bufmgr_emulator_bo_unmap(tbm_bo bo)
238 {
239     struct vigs_drm_surface *sfc;
240
241     TBM_EMULATOR_LOG_DEBUG("bo = %p", bo);
242
243     sfc = (struct vigs_drm_surface*)tbm_backend_get_bo_priv(bo);
244
245     vigs_drm_surface_end_access(sfc, 1);
246
247     return 1;
248 }
249
250 static int tbm_bufmgr_emulator_bo_cache_flush(tbm_bo bo, int flags)
251 {
252     TBM_EMULATOR_LOG_DEBUG("bo = %p, flags = %d", bo, flags);
253     return 1;
254 }
255
256 static int tbm_bufmgr_emulator_bo_lock(tbm_bo bo)
257 {
258     TBM_EMULATOR_LOG_DEBUG("bo = %p", bo);
259     return 1;
260 }
261
262 static int tbm_bufmgr_emulator_bo_unlock(tbm_bo bo)
263 {
264     TBM_EMULATOR_LOG_DEBUG("bo = %p", bo);
265     return 1;
266 }
267
268 static int tbm_bufmgr_emulator_bo_get_global_key(tbm_bo bo)
269 {
270     struct vigs_drm_surface *sfc;
271     int ret;
272
273     TBM_EMULATOR_LOG_DEBUG("bo = %p", bo);
274
275     sfc = (struct vigs_drm_surface*)tbm_backend_get_bo_priv(bo);
276
277     ret = vigs_drm_gem_get_name(&sfc->gem);
278
279     if (ret != 0) {
280         TBM_EMULATOR_LOG_ERROR("vigs_drm_gem_get_name failed: %s",
281                                strerror(-ret));
282         return 0;
283     }
284
285     return sfc->gem.name;
286 }
287
288 static int tbm_bufmgr_emulator_surface_get_plane_data(tbm_surface_h surface, int width, int height, tbm_format format, int plane_idx, uint32_t *size, uint32_t *offset, uint32_t *pitch)
289 {
290     *size = 0;
291     *offset = 0;
292     *pitch = 0;
293
294     switch(format) {
295     case TBM_FORMAT_XRGB8888:
296     case TBM_FORMAT_ARGB8888:
297         *size = width * height * 4;
298         *offset = 0;
299         *pitch = width * 4;
300         return 1;
301     case TBM_FORMAT_NV21:
302         if (plane_idx == 0) {
303             *size = width * height;
304             *offset = 0;
305             *pitch = width;
306         } else if (plane_idx == 1) {
307             *size = width * (height >> 1);
308             *offset = width * height;
309             *pitch = width;
310         } else {
311             return 0;
312         }
313         return 1;
314     case TBM_FORMAT_NV61:
315         if (plane_idx == 0) {
316             *size = width * height;
317             *offset = 0;
318             *pitch = width;
319         } else if (plane_idx == 1) {
320             *size = width * height;
321             *offset = width * height;
322             *pitch = width;
323         } else {
324             return 0;
325         }
326         return 1;
327     case TBM_FORMAT_YUV420:
328         if (plane_idx == 0) {
329             *size = width * height;
330             *offset = 0;
331             *pitch = width;
332         } else if (plane_idx == 1) {
333             *size = (width * height) >> 2;
334             *offset = width * height;
335             *pitch = width >> 1 ;
336         } else if (plane_idx == 2) {
337             *size = (width * height) >> 2;
338             *offset = (width * height) + (width  * height >> 2);
339             *pitch = width >> 1;
340         } else {
341             return 0;
342         }
343         return 1;
344     default:
345         return 0;
346     }
347 }
348
349 static int tbm_bufmgr_emulator_surface_get_size(tbm_surface_h surface, int width, int height, tbm_format format)
350 {
351     int bpp;
352
353     switch(format) {
354     case TBM_FORMAT_XRGB8888:
355     case TBM_FORMAT_ARGB8888:
356         bpp = 32;
357         break;
358     /* NV21 : Y/CrCb 4:2:0 */
359     /* YUV420 : YUV 4:2:0 */
360     case TBM_FORMAT_NV21:
361     case TBM_FORMAT_YUV420:
362         bpp = 12;
363         break;
364     /* NV61 : Y/CrCb 4:2:2 */
365     case TBM_FORMAT_NV61:
366         bpp = 16;
367         break;
368     default:
369         return 0;
370     }
371     return (width * height * bpp) >> 3;
372 }
373
374 static int tbm_bufmgr_emulator_surface_supported_format(uint32_t **formats, uint32_t *num)
375 {
376     uint32_t *color_formats;
377
378     color_formats = (uint32_t*)calloc(1, sizeof(tbm_bufmgr_emulator_color_format_list));
379
380     if (!color_formats) {
381         return 0;
382     }
383
384     memcpy(color_formats,
385            tbm_bufmgr_emulator_color_format_list,
386            sizeof(tbm_bufmgr_emulator_color_format_list));
387
388     *formats = color_formats;
389     *num = sizeof(tbm_bufmgr_emulator_color_format_list)/sizeof(tbm_bufmgr_emulator_color_format_list[0]);
390
391     return 1;
392 }
393
394
395 MODULEINITPPROTO(tbm_bufmgr_emulator_init);
396
397 static TBMModuleVersionInfo EmulatorVersRec =
398 {
399     "emulator",
400     "Samsung",
401     TBM_ABI_VERSION,
402 };
403
404 TBMModuleData tbmModuleData = { &EmulatorVersRec, tbm_bufmgr_emulator_init };
405
406 int tbm_bufmgr_emulator_init(tbm_bufmgr bufmgr, int fd)
407 {
408     int ret = 0;
409     struct vigs_drm_device *drm_dev = NULL;
410     tbm_bufmgr_backend backend = NULL;
411
412     TBM_EMULATOR_LOG_DEBUG("enter");
413
414     if (!bufmgr) {
415         return 0;
416     }
417
418     ret = vigs_drm_device_create(fd, &drm_dev);
419
420     if (ret != 0) {
421         TBM_EMULATOR_LOG_ERROR("vigs_drm_device_create failed: %s", strerror(-ret));
422         goto fail;
423     }
424
425     backend = tbm_backend_alloc();
426
427     if (!backend) {
428         TBM_EMULATOR_LOG_ERROR("tbm_backend_alloc failed");
429         goto fail;
430     }
431
432     backend->flags = TBM_CACHE_CTRL_BACKEND|TBM_LOCK_CTRL_BACKEND;
433     backend->priv = (void*)drm_dev;
434     backend->bufmgr_deinit = tbm_bufmgr_emulator_deinit;
435     backend->bo_size = tbm_bufmgr_emulator_bo_size;
436     backend->bo_alloc = tbm_bufmgr_emulator_bo_alloc;
437     backend->bo_free = tbm_bufmgr_emulator_bo_free;
438     backend->bo_import = tbm_bufmgr_emulator_bo_import;
439     backend->bo_export = tbm_bufmgr_emulator_bo_export;
440     backend->bo_get_handle = tbm_bufmgr_emulator_bo_get_handle;
441     backend->bo_map = tbm_bufmgr_emulator_bo_map;
442     backend->bo_unmap = tbm_bufmgr_emulator_bo_unmap;
443     backend->bo_cache_flush = tbm_bufmgr_emulator_bo_cache_flush;
444     backend->bo_get_global_key = tbm_bufmgr_emulator_bo_get_global_key;
445     backend->bo_lock = tbm_bufmgr_emulator_bo_lock;
446     backend->bo_unlock = tbm_bufmgr_emulator_bo_unlock;
447     backend->surface_get_plane_data = tbm_bufmgr_emulator_surface_get_plane_data;
448     backend->surface_get_size = tbm_bufmgr_emulator_surface_get_size;
449     backend->surface_supported_format = tbm_bufmgr_emulator_surface_supported_format;
450
451     if (!tbm_backend_init(bufmgr, backend)) {
452         TBM_EMULATOR_LOG_ERROR("tbm_backend_init failed");
453         goto fail;
454     }
455
456     TBM_EMULATOR_LOG_INFO("initialized");
457
458     return 1;
459
460 fail:
461     if (backend) {
462         tbm_backend_free(backend);
463     }
464
465     if (drm_dev) {
466         vigs_drm_device_destroy(drm_dev);
467     }
468
469     return 0;
470 }