diff options
Diffstat (limited to 'src/gallium/winsys/virgl/drm')
-rw-r--r-- | src/gallium/winsys/virgl/drm/Makefile.am | 34 | ||||
-rw-r--r-- | src/gallium/winsys/virgl/drm/Makefile.sources | 2 | ||||
-rw-r--r-- | src/gallium/winsys/virgl/drm/virgl_drm_public.h | 30 | ||||
-rw-r--r-- | src/gallium/winsys/virgl/drm/virgl_drm_winsys.c | 764 | ||||
-rw-r--r-- | src/gallium/winsys/virgl/drm/virgl_drm_winsys.h | 98 | ||||
-rw-r--r-- | src/gallium/winsys/virgl/drm/virgl_hw.h | 286 | ||||
-rw-r--r-- | src/gallium/winsys/virgl/drm/virtgpu_drm.h | 163 |
7 files changed, 1377 insertions, 0 deletions
diff --git a/src/gallium/winsys/virgl/drm/Makefile.am b/src/gallium/winsys/virgl/drm/Makefile.am new file mode 100644 index 00000000000..49680e065be --- /dev/null +++ b/src/gallium/winsys/virgl/drm/Makefile.am @@ -0,0 +1,34 @@ +# Copyright © 2015 Red Hat Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +include Makefile.sources +include $(top_srcdir)/src/gallium/Automake.inc + +AM_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/gallium/drivers \ + $(GALLIUM_CFLAGS) \ + $(LIBDRM_CFLAGS) + +noinst_LTLIBRARIES = libvirgldrm.la + +libvirgldrm_la_SOURCES = $(C_SOURCES) diff --git a/src/gallium/winsys/virgl/drm/Makefile.sources b/src/gallium/winsys/virgl/drm/Makefile.sources new file mode 100644 index 00000000000..c0baed87c79 --- /dev/null +++ b/src/gallium/winsys/virgl/drm/Makefile.sources @@ -0,0 +1,2 @@ +C_SOURCES := \ + virgl_drm_winsys.c diff --git a/src/gallium/winsys/virgl/drm/virgl_drm_public.h b/src/gallium/winsys/virgl/drm/virgl_drm_public.h new file mode 100644 index 00000000000..be01021ca9a --- /dev/null +++ b/src/gallium/winsys/virgl/drm/virgl_drm_public.h @@ -0,0 +1,30 @@ +/* + * Copyright 2014, 2015 Red Hat. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef VIRGL_DRM_PUBLIC_H +#define VIRGL_DRM_PUBLIC_H + +struct virgl_winsys; + +struct virgl_winsys *virgl_drm_winsys_create(int drmFD); + +#endif diff --git a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c new file mode 100644 index 00000000000..77972cfc358 --- /dev/null +++ b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.c @@ -0,0 +1,764 @@ +/* + * Copyright 2014, 2015 Red Hat. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* TODO - remove this */ +#define _FILE_OFFSET_BITS 64 + +#include "virgl_drm_winsys.h" +#include "virgl_drm_public.h" +#include "util/u_memory.h" +#include "util/u_format.h" +#include "state_tracker/drm_driver.h" + +#include "os/os_mman.h" +#include "os/os_time.h" +#include <sys/ioctl.h> +#include <errno.h> +#include <xf86drm.h> +#include <fcntl.h> +#include <stdio.h> +#include "virtgpu_drm.h" + +static inline boolean can_cache_resource(struct virgl_hw_res *res) +{ + return res->cacheable == TRUE; +} + +static void virgl_hw_res_destroy(struct virgl_drm_winsys *qdws, + struct virgl_hw_res *res) +{ + struct drm_gem_close args; + + if (res->name) { + pipe_mutex_lock(qdws->bo_handles_mutex); + util_hash_table_remove(qdws->bo_handles, + (void *)(uintptr_t)res->name); + pipe_mutex_unlock(qdws->bo_handles_mutex); + } + + if (res->ptr) + os_munmap(res->ptr, res->size); + + args.handle = res->bo_handle; + drmIoctl(qdws->fd, DRM_IOCTL_GEM_CLOSE, &args); + FREE(res); +} + +static boolean virgl_drm_resource_is_busy(struct virgl_drm_winsys *qdws, struct virgl_hw_res *res) +{ + struct drm_virtgpu_3d_wait waitcmd; + int ret; + + waitcmd.handle = res->bo_handle; + waitcmd.flags = VIRTGPU_WAIT_NOWAIT; + + ret = drmIoctl(qdws->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd); + if (ret && errno == EBUSY) + return TRUE; + return FALSE; +} + +static void +virgl_cache_flush(struct virgl_drm_winsys *qdws) +{ + struct list_head *curr, *next; + struct virgl_hw_res *res; + + pipe_mutex_lock(qdws->mutex); + curr = qdws->delayed.next; + next = curr->next; + + while (curr != &qdws->delayed) { + res = LIST_ENTRY(struct virgl_hw_res, curr, head); + LIST_DEL(&res->head); + virgl_hw_res_destroy(qdws, res); + curr = next; + next = curr->next; + } + pipe_mutex_unlock(qdws->mutex); +} +static void +virgl_drm_winsys_destroy(struct virgl_winsys *qws) +{ + struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws); + + virgl_cache_flush(qdws); + + util_hash_table_destroy(qdws->bo_handles); + pipe_mutex_destroy(qdws->bo_handles_mutex); + pipe_mutex_destroy(qdws->mutex); + + FREE(qdws); +} + +static void +virgl_cache_list_check_free(struct virgl_drm_winsys *qdws) +{ + struct list_head *curr, *next; + struct virgl_hw_res *res; + int64_t now; + + now = os_time_get(); + curr = qdws->delayed.next; + next = curr->next; + while (curr != &qdws->delayed) { + res = LIST_ENTRY(struct virgl_hw_res, curr, head); + if (!os_time_timeout(res->start, res->end, now)) + break; + + LIST_DEL(&res->head); + virgl_hw_res_destroy(qdws, res); + curr = next; + next = curr->next; + } +} + +static void virgl_drm_resource_reference(struct virgl_drm_winsys *qdws, + struct virgl_hw_res **dres, + struct virgl_hw_res *sres) +{ + struct virgl_hw_res *old = *dres; + if (pipe_reference(&(*dres)->reference, &sres->reference)) { + + if (!can_cache_resource(old)) { + virgl_hw_res_destroy(qdws, old); + } else { + pipe_mutex_lock(qdws->mutex); + virgl_cache_list_check_free(qdws); + + old->start = os_time_get(); + old->end = old->start + qdws->usecs; + LIST_ADDTAIL(&old->head, &qdws->delayed); + qdws->num_delayed++; + pipe_mutex_unlock(qdws->mutex); + } + } + *dres = sres; +} + +static struct virgl_hw_res *virgl_drm_winsys_resource_create(struct virgl_winsys *qws, + enum pipe_texture_target target, + uint32_t format, + uint32_t bind, + uint32_t width, + uint32_t height, + uint32_t depth, + uint32_t array_size, + uint32_t last_level, + uint32_t nr_samples, + uint32_t size) +{ + struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws); + struct drm_virtgpu_resource_create createcmd; + int ret; + struct virgl_hw_res *res; + uint32_t stride = width * util_format_get_blocksize(format); + + res = CALLOC_STRUCT(virgl_hw_res); + if (!res) + return NULL; + + createcmd.target = target; + createcmd.format = format; + createcmd.bind = bind; + createcmd.width = width; + createcmd.height = height; + createcmd.depth = depth; + createcmd.array_size = array_size; + createcmd.last_level = last_level; + createcmd.nr_samples = nr_samples; + createcmd.res_handle = 0; + createcmd.stride = stride; + createcmd.size = size; + createcmd.flags = 0; + + ret = drmIoctl(qdws->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE, &createcmd); + if (ret != 0) { + FREE(res); + return NULL; + } + + res->bind = bind; + res->format = format; + + res->res_handle = createcmd.res_handle; + res->bo_handle = createcmd.bo_handle; + res->size = size; + res->stride = stride; + pipe_reference_init(&res->reference, 1); + res->num_cs_references = 0; + return res; +} + +static inline int virgl_is_res_compat(struct virgl_drm_winsys *qdws, + struct virgl_hw_res *res, + uint32_t size, uint32_t bind, uint32_t format) +{ + if (res->bind != bind) + return 0; + if (res->format != format) + return 0; + if (res->size < size) + return 0; + if (res->size > size * 2) + return 0; + + if (virgl_drm_resource_is_busy(qdws, res)) { + return -1; + } + + return 1; +} + +static int +virgl_bo_transfer_put(struct virgl_winsys *vws, + struct virgl_hw_res *res, + const struct pipe_box *box, + uint32_t stride, uint32_t layer_stride, + uint32_t buf_offset, uint32_t level) +{ + struct virgl_drm_winsys *vdws = virgl_drm_winsys(vws); + struct drm_virtgpu_3d_transfer_to_host tohostcmd; + int ret; + + tohostcmd.bo_handle = res->bo_handle; + tohostcmd.box = *(struct drm_virtgpu_3d_box *)box; + tohostcmd.offset = buf_offset; + tohostcmd.level = level; + // tohostcmd.stride = stride; + // tohostcmd.layer_stride = stride; + ret = drmIoctl(vdws->fd, DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST, &tohostcmd); + return ret; +} + +static int +virgl_bo_transfer_get(struct virgl_winsys *vws, + struct virgl_hw_res *res, + const struct pipe_box *box, + uint32_t stride, uint32_t layer_stride, + uint32_t buf_offset, uint32_t level) +{ + struct virgl_drm_winsys *vdws = virgl_drm_winsys(vws); + struct drm_virtgpu_3d_transfer_from_host fromhostcmd; + int ret; + + fromhostcmd.bo_handle = res->bo_handle; + fromhostcmd.level = level; + fromhostcmd.offset = buf_offset; + // fromhostcmd.stride = stride; + // fromhostcmd.layer_stride = layer_stride; + fromhostcmd.box = *(struct drm_virtgpu_3d_box *)box; + ret = drmIoctl(vdws->fd, DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST, &fromhostcmd); + return ret; +} + +static struct virgl_hw_res *virgl_drm_winsys_resource_cache_create(struct virgl_winsys *qws, + enum pipe_texture_target target, + uint32_t format, + uint32_t bind, + uint32_t width, + uint32_t height, + uint32_t depth, + uint32_t array_size, + uint32_t last_level, + uint32_t nr_samples, + uint32_t size) +{ + struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws); + struct virgl_hw_res *res, *curr_res; + struct list_head *curr, *next; + int64_t now; + int ret; + + /* only store binds for vertex/index/const buffers */ + if (bind != VIRGL_BIND_CONSTANT_BUFFER && bind != VIRGL_BIND_INDEX_BUFFER && + bind != VIRGL_BIND_VERTEX_BUFFER && bind != VIRGL_BIND_CUSTOM) + goto alloc; + + pipe_mutex_lock(qdws->mutex); + + res = NULL; + curr = qdws->delayed.next; + next = curr->next; + + now = os_time_get(); + while (curr != &qdws->delayed) { + curr_res = LIST_ENTRY(struct virgl_hw_res, curr, head); + + if (!res && (ret = virgl_is_res_compat(qdws, curr_res, size, bind, format) > 0)) + res = curr_res; + else if (os_time_timeout(curr_res->start, curr_res->end, now)) { + LIST_DEL(&curr_res->head); + virgl_hw_res_destroy(qdws, curr_res); + } else + break; + + if (ret == -1) + break; + + curr = next; + next = curr->next; + } + + if (!res && ret != -1) { + while (curr != &qdws->delayed) { + curr_res = LIST_ENTRY(struct virgl_hw_res, curr, head); + ret = virgl_is_res_compat(qdws, curr_res, size, bind, format); + if (ret > 0) { + res = curr_res; + break; + } + if (ret == -1) + break; + curr = next; + next = curr->next; + } + } + + if (res) { + LIST_DEL(&res->head); + --qdws->num_delayed; + pipe_mutex_unlock(qdws->mutex); + pipe_reference_init(&res->reference, 1); + return res; + } + + pipe_mutex_unlock(qdws->mutex); + +alloc: + res = virgl_drm_winsys_resource_create(qws, target, format, bind, + width, height, depth, array_size, + last_level, nr_samples, size); + if (bind == VIRGL_BIND_CONSTANT_BUFFER || bind == VIRGL_BIND_INDEX_BUFFER || + bind == VIRGL_BIND_VERTEX_BUFFER) + res->cacheable = TRUE; + return res; +} + +static struct virgl_hw_res *virgl_drm_winsys_resource_create_handle(struct virgl_winsys *qws, + struct winsys_handle *whandle) +{ + struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws); + struct drm_gem_open open_arg = {}; + struct drm_virtgpu_resource_info info_arg = {}; + struct virgl_hw_res *res; + + pipe_mutex_lock(qdws->bo_handles_mutex); + + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + res = util_hash_table_get(qdws->bo_handles, (void*)(uintptr_t)whandle->handle); + if (res) { + struct virgl_hw_res *r = NULL; + virgl_drm_resource_reference(qdws, &r, res); + goto done; + } + } + + res = CALLOC_STRUCT(virgl_hw_res); + if (!res) + goto done; + + if (whandle->type == DRM_API_HANDLE_TYPE_FD) { + int r; + uint32_t handle; + r = drmPrimeFDToHandle(qdws->fd, whandle->handle, &handle); + if (r) { + FREE(res); + res = NULL; + goto done; + } + res->bo_handle = handle; + } else { + memset(&open_arg, 0, sizeof(open_arg)); + open_arg.name = whandle->handle; + if (drmIoctl(qdws->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) { + FREE(res); + res = NULL; + goto done; + } + res->bo_handle = open_arg.handle; + } + res->name = whandle->handle; + + memset(&info_arg, 0, sizeof(info_arg)); + info_arg.bo_handle = res->bo_handle; + + if (drmIoctl(qdws->fd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO, &info_arg)) { + /* close */ + FREE(res); + res = NULL; + goto done; + } + + res->res_handle = info_arg.res_handle; + + res->size = info_arg.size; + res->stride = info_arg.stride; + pipe_reference_init(&res->reference, 1); + res->num_cs_references = 0; + + util_hash_table_set(qdws->bo_handles, (void *)(uintptr_t)whandle->handle, res); + +done: + pipe_mutex_unlock(qdws->bo_handles_mutex); + return res; +} + +static boolean virgl_drm_winsys_resource_get_handle(struct virgl_winsys *qws, + struct virgl_hw_res *res, + uint32_t stride, + struct winsys_handle *whandle) + { + struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws); + struct drm_gem_flink flink; + + if (!res) + return FALSE; + memset(&flink, 0, sizeof(flink)); + + if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) { + if (!res->flinked) { + flink.handle = res->bo_handle; + + if (drmIoctl(qdws->fd, DRM_IOCTL_GEM_FLINK, &flink)) { + return FALSE; + } + res->flinked = TRUE; + res->flink = flink.name; + + pipe_mutex_lock(qdws->bo_handles_mutex); + util_hash_table_set(qdws->bo_handles, (void *)(uintptr_t)res->flink, res); + pipe_mutex_unlock(qdws->bo_handles_mutex); + } + whandle->handle = res->flink; + } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) { + whandle->handle = res->bo_handle; + } else if (whandle->type == DRM_API_HANDLE_TYPE_FD) { + if (drmPrimeHandleToFD(qdws->fd, res->bo_handle, DRM_CLOEXEC, (int*)&whandle->handle)) + return FALSE; + } + whandle->stride = stride; + return TRUE; +} + +static void virgl_drm_winsys_resource_unref(struct virgl_winsys *qws, + struct virgl_hw_res *hres) +{ + struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws); + + virgl_drm_resource_reference(qdws, &hres, NULL); +} + +static void *virgl_drm_resource_map(struct virgl_winsys *qws, struct virgl_hw_res *res) +{ + struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws); + struct drm_virtgpu_map mmap_arg; + void *ptr; + + if (res->ptr) + return res->ptr; + + mmap_arg.handle = res->bo_handle; + if (drmIoctl(qdws->fd, DRM_IOCTL_VIRTGPU_MAP, &mmap_arg)) + return NULL; + + ptr = os_mmap(0, res->size, PROT_READ|PROT_WRITE, MAP_SHARED, + qdws->fd, mmap_arg.offset); + if (ptr == MAP_FAILED) + return NULL; + + res->ptr = ptr; + return ptr; + +} + +static void virgl_drm_resource_wait(struct virgl_winsys *qws, struct virgl_hw_res *res) +{ + struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws); + struct drm_virtgpu_3d_wait waitcmd; + int ret; + + waitcmd.handle = res->bo_handle; + waitcmd.flags = 0; + again: + ret = drmIoctl(qdws->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd); + if (ret == -EAGAIN) + goto again; +} + +static struct virgl_cmd_buf *virgl_drm_cmd_buf_create(struct virgl_winsys *qws) +{ + struct virgl_drm_cmd_buf *cbuf; + + cbuf = CALLOC_STRUCT(virgl_drm_cmd_buf); + if (!cbuf) + return NULL; + + cbuf->ws = qws; + + cbuf->nres = 512; + cbuf->res_bo = (struct virgl_hw_res **) + CALLOC(cbuf->nres, sizeof(struct virgl_hw_buf*)); + if (!cbuf->res_bo) { + FREE(cbuf); + return NULL; + } + cbuf->res_hlist = (uint32_t *)malloc(cbuf->nres * sizeof(uint32_t)); + if (!cbuf->res_hlist) { + FREE(cbuf->res_bo); + FREE(cbuf); + return NULL; + } + + cbuf->base.buf = cbuf->buf; + return &cbuf->base; +} + +static void virgl_drm_cmd_buf_destroy(struct virgl_cmd_buf *_cbuf) +{ + struct virgl_drm_cmd_buf *cbuf = (struct virgl_drm_cmd_buf *)_cbuf; + + FREE(cbuf->res_hlist); + FREE(cbuf->res_bo); + FREE(cbuf); + +} + +static boolean virgl_drm_lookup_res(struct virgl_drm_cmd_buf *cbuf, + struct virgl_hw_res *res) +{ + unsigned hash = res->res_handle & (sizeof(cbuf->is_handle_added)-1); + int i; + + if (cbuf->is_handle_added[hash]) { + i = cbuf->reloc_indices_hashlist[hash]; + if (cbuf->res_bo[i] == res) + return true; + + for (i = 0; i < cbuf->cres; i++) { + if (cbuf->res_bo[i] == res) { + cbuf->reloc_indices_hashlist[hash] = i; + return true; + } + } + } + return false; +} + +static void virgl_drm_add_res(struct virgl_drm_winsys *qdws, + struct virgl_drm_cmd_buf *cbuf, struct virgl_hw_res *res) +{ + unsigned hash = res->res_handle & (sizeof(cbuf->is_handle_added)-1); + + if (cbuf->cres > cbuf->nres) { + fprintf(stderr,"failure to add relocation\n"); + return; + } + + cbuf->res_bo[cbuf->cres] = NULL; + virgl_drm_resource_reference(qdws, &cbuf->res_bo[cbuf->cres], res); + cbuf->res_hlist[cbuf->cres] = res->bo_handle; + cbuf->is_handle_added[hash] = TRUE; + + cbuf->reloc_indices_hashlist[hash] = cbuf->cres; + p_atomic_inc(&res->num_cs_references); + cbuf->cres++; +} + +static void virgl_drm_release_all_res(struct virgl_drm_winsys *qdws, + struct virgl_drm_cmd_buf *cbuf) +{ + int i; + + for (i = 0; i < cbuf->cres; i++) { + p_atomic_dec(&cbuf->res_bo[i]->num_cs_references); + virgl_drm_resource_reference(qdws, &cbuf->res_bo[i], NULL); + } + cbuf->cres = 0; +} + +static void virgl_drm_emit_res(struct virgl_winsys *qws, + struct virgl_cmd_buf *_cbuf, struct virgl_hw_res *res, boolean write_buf) +{ + struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws); + struct virgl_drm_cmd_buf *cbuf = (struct virgl_drm_cmd_buf *)_cbuf; + boolean already_in_list = virgl_drm_lookup_res(cbuf, res); + + if (write_buf) + cbuf->base.buf[cbuf->base.cdw++] = res->res_handle; + + if (!already_in_list) + virgl_drm_add_res(qdws, cbuf, res); +} + +static boolean virgl_drm_res_is_ref(struct virgl_winsys *qws, + struct virgl_cmd_buf *_cbuf, + struct virgl_hw_res *res) +{ + if (!res->num_cs_references) + return FALSE; + + return TRUE; +} + +static int virgl_drm_winsys_submit_cmd(struct virgl_winsys *qws, struct virgl_cmd_buf *_cbuf) +{ + struct virgl_drm_winsys *qdws = virgl_drm_winsys(qws); + struct virgl_drm_cmd_buf *cbuf = (struct virgl_drm_cmd_buf *)_cbuf; + struct drm_virtgpu_execbuffer eb; + int ret; + + if (cbuf->base.cdw == 0) + return 0; + + memset(&eb, 0, sizeof(struct drm_virtgpu_execbuffer)); + eb.command = (unsigned long)(void*)cbuf->buf; + eb.size = cbuf->base.cdw * 4; + eb.num_bo_handles = cbuf->cres; + eb.bo_handles = (unsigned long)(void *)cbuf->res_hlist; + + ret = drmIoctl(qdws->fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &eb); + if (ret == -1) + fprintf(stderr,"got error from kernel - expect bad rendering %d\n", errno); + cbuf->base.cdw = 0; + + virgl_drm_release_all_res(qdws, cbuf); + + memset(cbuf->is_handle_added, 0, sizeof(cbuf->is_handle_added)); + return ret; +} + +static int virgl_drm_get_caps(struct virgl_winsys *vws, struct virgl_drm_caps *caps) +{ + struct virgl_drm_winsys *vdws = virgl_drm_winsys(vws); + struct drm_virtgpu_get_caps args; + int ret; + + memset(&args, 0, sizeof(args)); + + args.cap_set_id = 1; + args.addr = (unsigned long)&caps->caps; + args.size = sizeof(union virgl_caps); + ret = drmIoctl(vdws->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &args); + return ret; +} + +#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x))) + +static unsigned handle_hash(void *key) +{ + return PTR_TO_UINT(key); +} + +static int handle_compare(void *key1, void *key2) +{ + return PTR_TO_UINT(key1) != PTR_TO_UINT(key2); +} + +static struct pipe_fence_handle * +virgl_cs_create_fence(struct virgl_winsys *vws) +{ + struct virgl_hw_res *res; + + res = virgl_drm_winsys_resource_cache_create(vws, + PIPE_BUFFER, + PIPE_FORMAT_R8_UNORM, + VIRGL_BIND_CUSTOM, + 8, 1, 1, 0, 0, 0, 8); + + return (struct pipe_fence_handle *)res; +} + +static bool virgl_fence_wait(struct virgl_winsys *vws, + struct pipe_fence_handle *fence, + uint64_t timeout) +{ + struct virgl_drm_winsys *vdws = virgl_drm_winsys(vws); + struct virgl_hw_res *res = (struct virgl_hw_res *)fence; + + if (timeout == 0) + return virgl_drm_resource_is_busy(vdws, res); + + if (timeout != PIPE_TIMEOUT_INFINITE) { + int64_t start_time = os_time_get(); + timeout /= 1000; + while (virgl_drm_resource_is_busy(vdws, res)) { + if (os_time_get() - start_time >= timeout) + return FALSE; + os_time_sleep(10); + } + return TRUE; + } + virgl_drm_resource_wait(vws, res); + return TRUE; +} + +static void virgl_fence_reference(struct virgl_winsys *vws, + struct pipe_fence_handle **dst, + struct pipe_fence_handle *src) +{ + struct virgl_drm_winsys *vdws = virgl_drm_winsys(vws); + virgl_drm_resource_reference(vdws, (struct virgl_hw_res **)dst, + (struct virgl_hw_res *)src); +} + + +struct virgl_winsys * +virgl_drm_winsys_create(int drmFD) +{ + struct virgl_drm_winsys *qdws; + + qdws = CALLOC_STRUCT(virgl_drm_winsys); + if (!qdws) + return NULL; + + qdws->fd = drmFD; + qdws->num_delayed = 0; + qdws->usecs = 1000000; + LIST_INITHEAD(&qdws->delayed); + pipe_mutex_init(qdws->mutex); + pipe_mutex_init(qdws->bo_handles_mutex); + qdws->bo_handles = util_hash_table_create(handle_hash, handle_compare); + qdws->base.destroy = virgl_drm_winsys_destroy; + + qdws->base.transfer_put = virgl_bo_transfer_put; + qdws->base.transfer_get = virgl_bo_transfer_get; + qdws->base.resource_create = virgl_drm_winsys_resource_cache_create; + qdws->base.resource_unref = virgl_drm_winsys_resource_unref; + qdws->base.resource_create_from_handle = virgl_drm_winsys_resource_create_handle; + qdws->base.resource_get_handle = virgl_drm_winsys_resource_get_handle; + qdws->base.resource_map = virgl_drm_resource_map; + qdws->base.resource_wait = virgl_drm_resource_wait; + qdws->base.cmd_buf_create = virgl_drm_cmd_buf_create; + qdws->base.cmd_buf_destroy = virgl_drm_cmd_buf_destroy; + qdws->base.submit_cmd = virgl_drm_winsys_submit_cmd; + qdws->base.emit_res = virgl_drm_emit_res; + qdws->base.res_is_referenced = virgl_drm_res_is_ref; + + qdws->base.cs_create_fence = virgl_cs_create_fence; + qdws->base.fence_wait = virgl_fence_wait; + qdws->base.fence_reference = virgl_fence_reference; + + qdws->base.get_caps = virgl_drm_get_caps; + return &qdws->base; + +} diff --git a/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h new file mode 100644 index 00000000000..c9b25a00977 --- /dev/null +++ b/src/gallium/winsys/virgl/drm/virgl_drm_winsys.h @@ -0,0 +1,98 @@ +/* + * Copyright 2014, 2015 Red Hat. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef VIRGL_DRM_WINSYS_H +#define VIRGL_DRM_WINSYS_H + +#include <stdint.h> +#include "pipe/p_compiler.h" +#include "drm.h" + +#include "os/os_thread.h" +#include "util/list.h" +#include "util/u_inlines.h" +#include "util/u_hash_table.h" + +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_context.h" + +#include "virgl_hw.h" +#include "virgl/virgl_winsys.h" + +struct virgl_drm_winsys; + +struct virgl_hw_res { + struct pipe_reference reference; + uint32_t res_handle; + uint32_t bo_handle; + uint32_t name; + int num_cs_references; + uint32_t size; + void *ptr; + uint32_t stride; + + struct list_head head; + uint32_t format; + uint32_t bind; + boolean cacheable; + int64_t start, end; + boolean flinked; + uint32_t flink; +}; + +struct virgl_drm_winsys +{ + struct virgl_winsys base; + int fd; + struct list_head delayed; + int num_delayed; + unsigned usecs; + pipe_mutex mutex; + + struct util_hash_table *bo_handles; + pipe_mutex bo_handles_mutex; +}; + +struct virgl_drm_cmd_buf { + struct virgl_cmd_buf base; + + uint32_t buf[VIRGL_MAX_CMDBUF_DWORDS]; + + unsigned nres; + unsigned cres; + struct virgl_hw_res **res_bo; + struct virgl_winsys *ws; + uint32_t *res_hlist; + + char is_handle_added[512]; + unsigned reloc_indices_hashlist[512]; + +}; + +static inline struct virgl_drm_winsys * +virgl_drm_winsys(struct virgl_winsys *iws) +{ + return (struct virgl_drm_winsys *)iws; +} + +#endif diff --git a/src/gallium/winsys/virgl/drm/virgl_hw.h b/src/gallium/winsys/virgl/drm/virgl_hw.h new file mode 100644 index 00000000000..e3c56db2ac6 --- /dev/null +++ b/src/gallium/winsys/virgl/drm/virgl_hw.h @@ -0,0 +1,286 @@ +/* + * Copyright 2014, 2015 Red Hat. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef VIRGL_HW_H +#define VIRGL_HW_H + +struct virgl_box { + uint32_t x, y, z; + uint32_t w, h, d; +}; + +/* formats known by the HW device - based on gallium subset */ +enum virgl_formats { + VIRGL_FORMAT_B8G8R8A8_UNORM = 1, + VIRGL_FORMAT_B8G8R8X8_UNORM = 2, + VIRGL_FORMAT_A8R8G8B8_UNORM = 3, + VIRGL_FORMAT_X8R8G8B8_UNORM = 4, + VIRGL_FORMAT_B5G5R5A1_UNORM = 5, + VIRGL_FORMAT_B4G4R4A4_UNORM = 6, + VIRGL_FORMAT_B5G6R5_UNORM = 7, + VIRGL_FORMAT_L8_UNORM = 9, /**< ubyte luminance */ + VIRGL_FORMAT_A8_UNORM = 10, /**< ubyte alpha */ + VIRGL_FORMAT_L8A8_UNORM = 12, /**< ubyte alpha, luminance */ + VIRGL_FORMAT_L16_UNORM = 13, /**< ushort luminance */ + + VIRGL_FORMAT_Z16_UNORM = 16, + VIRGL_FORMAT_Z32_UNORM = 17, + VIRGL_FORMAT_Z32_FLOAT = 18, + VIRGL_FORMAT_Z24_UNORM_S8_UINT = 19, + VIRGL_FORMAT_S8_UINT_Z24_UNORM = 20, + VIRGL_FORMAT_Z24X8_UNORM = 21, + VIRGL_FORMAT_S8_UINT = 23, /**< ubyte stencil */ + + VIRGL_FORMAT_R32_FLOAT = 28, + VIRGL_FORMAT_R32G32_FLOAT = 29, + VIRGL_FORMAT_R32G32B32_FLOAT = 30, + VIRGL_FORMAT_R32G32B32A32_FLOAT = 31, + + VIRGL_FORMAT_R16_UNORM = 48, + VIRGL_FORMAT_R16G16_UNORM = 49, + + VIRGL_FORMAT_R16G16B16A16_UNORM = 51, + + VIRGL_FORMAT_R16_SNORM = 56, + VIRGL_FORMAT_R16G16_SNORM = 57, + VIRGL_FORMAT_R16G16B16A16_SNORM = 59, + + VIRGL_FORMAT_R8_UNORM = 64, + VIRGL_FORMAT_R8G8_UNORM = 65, + + VIRGL_FORMAT_R8G8B8A8_UNORM = 67, + + VIRGL_FORMAT_R8_SNORM = 74, + VIRGL_FORMAT_R8G8_SNORM = 75, + VIRGL_FORMAT_R8G8B8_SNORM = 76, + VIRGL_FORMAT_R8G8B8A8_SNORM = 77, + + VIRGL_FORMAT_R16_FLOAT = 91, + VIRGL_FORMAT_R16G16_FLOAT = 92, + VIRGL_FORMAT_R16G16B16_FLOAT = 93, + VIRGL_FORMAT_R16G16B16A16_FLOAT = 94, + + VIRGL_FORMAT_L8_SRGB = 95, + VIRGL_FORMAT_L8A8_SRGB = 96, + VIRGL_FORMAT_B8G8R8A8_SRGB = 100, + VIRGL_FORMAT_B8G8R8X8_SRGB = 101, + + /* compressed formats */ + VIRGL_FORMAT_DXT1_RGB = 105, + VIRGL_FORMAT_DXT1_RGBA = 106, + VIRGL_FORMAT_DXT3_RGBA = 107, + VIRGL_FORMAT_DXT5_RGBA = 108, + + /* sRGB, compressed */ + VIRGL_FORMAT_DXT1_SRGB = 109, + VIRGL_FORMAT_DXT1_SRGBA = 110, + VIRGL_FORMAT_DXT3_SRGBA = 111, + VIRGL_FORMAT_DXT5_SRGBA = 112, + + /* rgtc compressed */ + VIRGL_FORMAT_RGTC1_UNORM = 113, + VIRGL_FORMAT_RGTC1_SNORM = 114, + VIRGL_FORMAT_RGTC2_UNORM = 115, + VIRGL_FORMAT_RGTC2_SNORM = 116, + + VIRGL_FORMAT_A8B8G8R8_UNORM = 121, + VIRGL_FORMAT_B5G5R5X1_UNORM = 122, + VIRGL_FORMAT_R11G11B10_FLOAT = 124, + VIRGL_FORMAT_R9G9B9E5_FLOAT = 125, + VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT = 126, + + VIRGL_FORMAT_B10G10R10A2_UNORM = 131, + VIRGL_FORMAT_R8G8B8X8_UNORM = 134, + VIRGL_FORMAT_B4G4R4X4_UNORM = 135, + VIRGL_FORMAT_B2G3R3_UNORM = 139, + + VIRGL_FORMAT_L16A16_UNORM = 140, + VIRGL_FORMAT_A16_UNORM = 141, + + VIRGL_FORMAT_A8_SNORM = 147, + VIRGL_FORMAT_L8_SNORM = 148, + VIRGL_FORMAT_L8A8_SNORM = 149, + + VIRGL_FORMAT_A16_SNORM = 151, + VIRGL_FORMAT_L16_SNORM = 152, + VIRGL_FORMAT_L16A16_SNORM = 153, + + VIRGL_FORMAT_A16_FLOAT = 155, + VIRGL_FORMAT_L16_FLOAT = 156, + VIRGL_FORMAT_L16A16_FLOAT = 157, + + VIRGL_FORMAT_A32_FLOAT = 159, + VIRGL_FORMAT_L32_FLOAT = 160, + VIRGL_FORMAT_L32A32_FLOAT = 161, + + VIRGL_FORMAT_R8_UINT = 177, + VIRGL_FORMAT_R8G8_UINT = 178, + VIRGL_FORMAT_R8G8B8_UINT = 179, + VIRGL_FORMAT_R8G8B8A8_UINT = 180, + + VIRGL_FORMAT_R8_SINT = 181, + VIRGL_FORMAT_R8G8_SINT = 182, + VIRGL_FORMAT_R8G8B8_SINT = 183, + VIRGL_FORMAT_R8G8B8A8_SINT = 184, + + VIRGL_FORMAT_R16_UINT = 185, + VIRGL_FORMAT_R16G16_UINT = 186, + VIRGL_FORMAT_R16G16B16_UINT = 187, + VIRGL_FORMAT_R16G16B16A16_UINT = 188, + + VIRGL_FORMAT_R16_SINT = 189, + VIRGL_FORMAT_R16G16_SINT = 190, + VIRGL_FORMAT_R16G16B16_SINT = 191, + VIRGL_FORMAT_R16G16B16A16_SINT = 192, + VIRGL_FORMAT_R32_UINT = 193, + VIRGL_FORMAT_R32G32_UINT = 194, + VIRGL_FORMAT_R32G32B32_UINT = 195, + VIRGL_FORMAT_R32G32B32A32_UINT = 196, + + VIRGL_FORMAT_R32_SINT = 197, + VIRGL_FORMAT_R32G32_SINT = 198, + VIRGL_FORMAT_R32G32B32_SINT = 199, + VIRGL_FORMAT_R32G32B32A32_SINT = 200, + + VIRGL_FORMAT_A8_UINT = 201, + VIRGL_FORMAT_L8_UINT = 203, + VIRGL_FORMAT_L8A8_UINT = 204, + + VIRGL_FORMAT_A8_SINT = 205, + VIRGL_FORMAT_L8_SINT = 207, + VIRGL_FORMAT_L8A8_SINT = 208, + + VIRGL_FORMAT_A16_UINT = 209, + VIRGL_FORMAT_L16_UINT = 211, + VIRGL_FORMAT_L16A16_UINT = 212, + + VIRGL_FORMAT_A16_SINT = 213, + VIRGL_FORMAT_L16_SINT = 215, + VIRGL_FORMAT_L16A16_SINT = 216, + + VIRGL_FORMAT_A32_UINT = 217, + VIRGL_FORMAT_L32_UINT = 219, + VIRGL_FORMAT_L32A32_UINT = 220, + + VIRGL_FORMAT_A32_SINT = 221, + VIRGL_FORMAT_L32_SINT = 223, + VIRGL_FORMAT_L32A32_SINT = 224, + + VIRGL_FORMAT_B10G10R10A2_UINT = 225, + VIRGL_FORMAT_R8G8B8X8_SNORM = 229, + + VIRGL_FORMAT_R8G8B8X8_SRGB = 230, + + VIRGL_FORMAT_B10G10R10X2_UNORM = 233, + VIRGL_FORMAT_R16G16B16X16_UNORM = 234, + VIRGL_FORMAT_R16G16B16X16_SNORM = 235, + VIRGL_FORMAT_MAX, +}; + +#define VIRGL_BIND_DEPTH_STENCIL (1 << 0) +#define VIRGL_BIND_RENDER_TARGET (1 << 1) +#define VIRGL_BIND_SAMPLER_VIEW (1 << 3) +#define VIRGL_BIND_VERTEX_BUFFER (1 << 4) +#define VIRGL_BIND_INDEX_BUFFER (1 << 5) +#define VIRGL_BIND_CONSTANT_BUFFER (1 << 6) +#define VIRGL_BIND_DISPLAY_TARGET (1 << 7) +#define VIRGL_BIND_STREAM_OUTPUT (1 << 11) +#define VIRGL_BIND_CURSOR (1 << 16) +#define VIRGL_BIND_CUSTOM (1 << 17) +#define VIRGL_BIND_SCANOUT (1 << 18) + +struct virgl_caps_bool_set1 { + unsigned indep_blend_enable:1; + unsigned indep_blend_func:1; + unsigned cube_map_array:1; + unsigned shader_stencil_export:1; + unsigned conditional_render:1; + unsigned start_instance:1; + unsigned primitive_restart:1; + unsigned blend_eq_sep:1; + unsigned instanceid:1; + unsigned vertex_element_instance_divisor:1; + unsigned seamless_cube_map:1; + unsigned occlusion_query:1; + unsigned timer_query:1; + unsigned streamout_pause_resume:1; + unsigned texture_multisample:1; + unsigned fragment_coord_conventions:1; + unsigned depth_clip_disable:1; + unsigned seamless_cube_map_per_texture:1; + unsigned ubo:1; + unsigned color_clamping:1; /* not in GL 3.1 core profile */ + unsigned poly_stipple:1; /* not in GL 3.1 core profile */ + unsigned mirror_clamp:1; + unsigned texture_query_lod:1; +}; + +/* endless expansion capabilites - current gallium has 252 formats */ +struct virgl_supported_format_mask { + uint32_t bitmask[16]; +}; +/* capabilities set 2 - version 1 - 32-bit and float values */ +struct virgl_caps_v1 { + uint32_t max_version; + struct virgl_supported_format_mask sampler; + struct virgl_supported_format_mask render; + struct virgl_supported_format_mask depthstencil; + struct virgl_supported_format_mask vertexbuffer; + struct virgl_caps_bool_set1 bset; + uint32_t glsl_level; + uint32_t max_texture_array_layers; + uint32_t max_streamout_buffers; + uint32_t max_dual_source_render_targets; + uint32_t max_render_targets; + uint32_t max_samples; + uint32_t prim_mask; + uint32_t max_tbo_size; + uint32_t max_uniform_blocks; + uint32_t max_viewports; + uint32_t max_texture_gather_components; +}; + +union virgl_caps { + uint32_t max_version; + struct virgl_caps_v1 v1; +}; + +enum virgl_errors { + VIRGL_ERROR_NONE, + VIRGL_ERROR_UNKNOWN, + VIRGL_ERROR_UNKNOWN_RESOURCE_FORMAT, +}; + +enum virgl_ctx_errors { + VIRGL_ERROR_CTX_NONE, + VIRGL_ERROR_CTX_UNKNOWN, + VIRGL_ERROR_CTX_ILLEGAL_SHADER, + VIRGL_ERROR_CTX_ILLEGAL_HANDLE, + VIRGL_ERROR_CTX_ILLEGAL_RESOURCE, + VIRGL_ERROR_CTX_ILLEGAL_SURFACE, + VIRGL_ERROR_CTX_ILLEGAL_VERTEX_FORMAT, + VIRGL_ERROR_CTX_ILLEGAL_CMD_BUFFER, +}; + + +#define VIRGL_RESOURCE_Y_0_TOP (1 << 0) +#endif diff --git a/src/gallium/winsys/virgl/drm/virtgpu_drm.h b/src/gallium/winsys/virgl/drm/virtgpu_drm.h new file mode 100644 index 00000000000..fcc789edbff --- /dev/null +++ b/src/gallium/winsys/virgl/drm/virtgpu_drm.h @@ -0,0 +1,163 @@ +/* + * Copyright 2013 Red Hat + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef VIRTGPU_DRM_H +#define VIRTGPU_DRM_H + +#include <stddef.h> +#include "drm/drm.h" + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + * + * Do not use pointers, use uint64_t instead for 32 bit / 64 bit user/kernel + * compatibility Keep fields aligned to their size + */ + +#define DRM_VIRTGPU_MAP 0x01 +#define DRM_VIRTGPU_EXECBUFFER 0x02 +#define DRM_VIRTGPU_GETPARAM 0x03 +#define DRM_VIRTGPU_RESOURCE_CREATE 0x04 +#define DRM_VIRTGPU_RESOURCE_INFO 0x05 +#define DRM_VIRTGPU_TRANSFER_FROM_HOST 0x06 +#define DRM_VIRTGPU_TRANSFER_TO_HOST 0x07 +#define DRM_VIRTGPU_WAIT 0x08 +#define DRM_VIRTGPU_GET_CAPS 0x09 + +struct drm_virtgpu_map { + uint64_t offset; /* use for mmap system call */ + uint32_t handle; + uint32_t pad; +}; + +struct drm_virtgpu_execbuffer { + uint32_t flags; /* for future use */ + uint32_t size; + uint64_t command; /* void* */ + uint64_t bo_handles; + uint32_t num_bo_handles; + uint32_t pad; +}; + +#define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */ + +struct drm_virtgpu_getparam { + uint64_t param; + uint64_t value; +}; + +/* NO_BO flags? NO resource flag? */ +/* resource flag for y_0_top */ +struct drm_virtgpu_resource_create { + uint32_t target; + uint32_t format; + uint32_t bind; + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t array_size; + uint32_t last_level; + uint32_t nr_samples; + uint32_t flags; + uint32_t bo_handle; /* if this is set - recreate a new resource attached to this bo ? */ + uint32_t res_handle; /* returned by kernel */ + uint32_t size; /* validate transfer in the host */ + uint32_t stride; /* validate transfer in the host */ +}; + +struct drm_virtgpu_resource_info { + uint32_t bo_handle; + uint32_t res_handle; + uint32_t size; + uint32_t stride; +}; + +struct drm_virtgpu_3d_box { + uint32_t x, y, z; + uint32_t w, h, d; +}; + +struct drm_virtgpu_3d_transfer_to_host { + uint32_t bo_handle; + struct drm_virtgpu_3d_box box; + uint32_t level; + uint32_t offset; +}; + +struct drm_virtgpu_3d_transfer_from_host { + uint32_t bo_handle; + struct drm_virtgpu_3d_box box; + uint32_t level; + uint32_t offset; +}; + +#define VIRTGPU_WAIT_NOWAIT 1 /* like it */ +struct drm_virtgpu_3d_wait { + uint32_t handle; /* 0 is an invalid handle */ + uint32_t flags; +}; + +struct drm_virtgpu_get_caps { + uint32_t cap_set_id; + uint32_t cap_set_ver; + uint64_t addr; + uint32_t size; + uint32_t pad; +}; + +#define DRM_IOCTL_VIRTGPU_MAP \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map) + +#define DRM_IOCTL_VIRTGPU_EXECBUFFER \ + DRM_IOW(DRM_COMMAND_BASE + DRM_VIRTGPU_EXECBUFFER,\ + struct drm_virtgpu_execbuffer) + +#define DRM_IOCTL_VIRTGPU_GETPARAM \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GETPARAM,\ + struct drm_virtgpu_getparam) + +#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE, \ + struct drm_virtgpu_resource_create) + +#define DRM_IOCTL_VIRTGPU_RESOURCE_INFO \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_INFO, \ + struct drm_virtgpu_resource_info) + +#define DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_FROM_HOST, \ + struct drm_virtgpu_3d_transfer_from_host) + +#define DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_TO_HOST, \ + struct drm_virtgpu_3d_transfer_to_host) + +#define DRM_IOCTL_VIRTGPU_WAIT \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_WAIT, \ + struct drm_virtgpu_3d_wait) + +#define DRM_IOCTL_VIRTGPU_GET_CAPS \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GET_CAPS, \ + struct drm_virtgpu_get_caps) + +#endif |