3 * Copyright (c) 2013 Samsung Electronics Co., Ltd.
5 * Stanislav Vorobiov <s.vorobiov@samsung.com>
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice (including the next
15 * paragraph) shall be included in all copies or substantial portions of the
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
38 #include <linux/stddef.h>
41 #include <xf86atomic.h>
46 #define vigs_offsetof(type, member) ((size_t)&((type*)0)->member)
48 #define vigs_containerof(ptr, type, member) ((type*)((char*)(ptr) - vigs_offsetof(type, member)))
50 struct vigs_drm_gem_info
55 struct vigs_drm_gem_impl
57 struct vigs_drm_gem_info info;
59 struct vigs_drm_gem gem;
62 struct vigs_drm_surface_impl
64 struct vigs_drm_gem_info gem_info;
66 struct vigs_drm_surface base;
69 struct vigs_drm_execbuffer_impl
71 struct vigs_drm_gem_info gem_info;
73 struct vigs_drm_execbuffer base;
76 static void vigs_drm_gem_close(struct vigs_drm_device *dev, uint32_t handle)
78 struct drm_gem_close req =
84 drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
88 static void vigs_drm_gem_impl_init(struct vigs_drm_gem_impl *gem_impl,
89 struct vigs_drm_device *dev,
94 atomic_set(&gem_impl->info.ref_count, 1);
95 gem_impl->gem.dev = dev;
96 gem_impl->gem.size = size;
97 gem_impl->gem.handle = handle;
98 gem_impl->gem.name = name;
101 int vigs_drm_device_create(int fd, struct vigs_drm_device **dev)
103 drmVersionPtr version;
107 *dev = calloc(sizeof(**dev), 1);
114 version = drmGetVersion(fd);
121 major = version->version_major;
123 drmFreeVersion(version);
125 if (major != DRM_VIGS_DRIVER_VERSION) {
142 void vigs_drm_device_destroy(struct vigs_drm_device *dev)
147 int vigs_drm_device_get_protocol_version(struct vigs_drm_device *dev,
148 uint32_t *protocol_version)
150 struct drm_vigs_get_protocol_version req;
153 ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_GET_PROTOCOL_VERSION, &req);
159 if (protocol_version) {
160 *protocol_version = req.version;
166 void vigs_drm_gem_ref(struct vigs_drm_gem *gem)
168 struct vigs_drm_gem_impl *gem_impl;
174 gem_impl = vigs_containerof(gem, struct vigs_drm_gem_impl, gem);
176 atomic_inc(&gem_impl->info.ref_count);
179 void vigs_drm_gem_unref(struct vigs_drm_gem *gem)
181 struct vigs_drm_gem_impl *gem_impl;
187 gem_impl = vigs_containerof(gem, struct vigs_drm_gem_impl, gem);
189 assert(atomic_read(&gem_impl->info.ref_count) > 0);
190 if (!atomic_dec_and_test(&gem_impl->info.ref_count)) {
195 munmap(gem->vaddr, gem->size);
198 vigs_drm_gem_close(gem->dev, gem->handle);
203 int vigs_drm_gem_get_name(struct vigs_drm_gem *gem)
205 struct drm_gem_flink req =
207 .handle = gem->handle,
215 ret = drmIoctl(gem->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
221 gem->name = req.name;
226 int vigs_drm_gem_map(struct vigs_drm_gem *gem, int track_access)
228 struct drm_vigs_gem_map req =
230 .handle = gem->handle,
231 .track_access = track_access
239 ret = drmIoctl(gem->dev->fd, DRM_IOCTL_VIGS_GEM_MAP, &req);
245 gem->vaddr = (void*)req.address;
250 void vigs_drm_gem_unmap(struct vigs_drm_gem *gem)
256 munmap(gem->vaddr, gem->size);
260 int vigs_drm_surface_create(struct vigs_drm_device *dev,
265 struct vigs_drm_surface **sfc)
267 struct vigs_drm_surface_impl *sfc_impl;
268 struct drm_vigs_create_surface req =
277 sfc_impl = calloc(sizeof(*sfc_impl), 1);
284 ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_CREATE_SURFACE, &req);
291 vigs_drm_gem_impl_init((struct vigs_drm_gem_impl*)sfc_impl,
297 sfc_impl->base.width = width;
298 sfc_impl->base.height = height;
299 sfc_impl->base.stride = stride;
300 sfc_impl->base.format = format;
301 sfc_impl->base.id = req.id;
303 *sfc = &sfc_impl->base;
315 int vigs_drm_surface_open(struct vigs_drm_device *dev,
317 struct vigs_drm_surface **sfc)
319 struct vigs_drm_surface_impl *sfc_impl;
320 struct drm_gem_open req =
324 struct drm_vigs_surface_info info_req;
327 sfc_impl = calloc(sizeof(*sfc_impl), 1);
334 ret = drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req);
341 info_req.handle = req.handle;
343 ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_SURFACE_INFO, &info_req);
350 vigs_drm_gem_impl_init((struct vigs_drm_gem_impl*)sfc_impl,
356 sfc_impl->base.width = info_req.width;
357 sfc_impl->base.height = info_req.height;
358 sfc_impl->base.stride = info_req.stride;
359 sfc_impl->base.format = info_req.format;
360 sfc_impl->base.id = info_req.id;
362 *sfc = &sfc_impl->base;
367 vigs_drm_gem_close(dev, req.handle);
376 int vigs_drm_surface_set_gpu_dirty(struct vigs_drm_surface *sfc)
378 struct drm_vigs_surface_set_gpu_dirty req =
380 .handle = sfc->gem.handle
384 ret = drmIoctl(sfc->gem.dev->fd, DRM_IOCTL_VIGS_SURFACE_SET_GPU_DIRTY, &req);
386 return (ret != 0) ? -errno : 0;
389 int vigs_drm_surface_start_access(struct vigs_drm_surface *sfc,
392 struct drm_vigs_surface_start_access req =
394 .address = (unsigned long)sfc->gem.vaddr,
399 ret = drmIoctl(sfc->gem.dev->fd, DRM_IOCTL_VIGS_SURFACE_START_ACCESS, &req);
401 return (ret != 0) ? -errno : 0;
404 int vigs_drm_surface_end_access(struct vigs_drm_surface *sfc,
407 struct drm_vigs_surface_end_access req =
409 .address = (unsigned long)sfc->gem.vaddr,
414 ret = drmIoctl(sfc->gem.dev->fd, DRM_IOCTL_VIGS_SURFACE_END_ACCESS, &req);
416 return (ret != 0) ? -errno : 0;
419 int vigs_drm_execbuffer_create(struct vigs_drm_device *dev,
421 struct vigs_drm_execbuffer **execbuffer)
423 struct vigs_drm_execbuffer_impl *execbuffer_impl;
424 struct drm_vigs_create_execbuffer req =
430 execbuffer_impl = calloc(sizeof(*execbuffer_impl), 1);
432 if (!execbuffer_impl) {
437 ret = drmIoctl(dev->fd, DRM_IOCTL_VIGS_CREATE_EXECBUFFER, &req);
444 vigs_drm_gem_impl_init((struct vigs_drm_gem_impl*)execbuffer_impl,
450 *execbuffer = &execbuffer_impl->base;
455 free(execbuffer_impl);
462 int vigs_drm_execbuffer_open(struct vigs_drm_device *dev,
464 struct vigs_drm_execbuffer **execbuffer)
466 struct vigs_drm_execbuffer_impl *execbuffer_impl;
467 struct drm_gem_open req =
473 execbuffer_impl = calloc(sizeof(*execbuffer_impl), 1);
475 if (!execbuffer_impl) {
480 ret = drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req);
487 vigs_drm_gem_impl_init((struct vigs_drm_gem_impl*)execbuffer_impl,
493 *execbuffer = &execbuffer_impl->base;
498 free(execbuffer_impl);
505 int vigs_drm_execbuffer_exec(struct vigs_drm_execbuffer *execbuffer)
507 struct drm_vigs_exec req =
509 .handle = execbuffer->gem.handle
513 ret = drmIoctl(execbuffer->gem.dev->fd, DRM_IOCTL_VIGS_EXEC, &req);
515 return (ret != 0) ? -errno : 0;