summaryrefslogtreecommitdiffstats
path: root/src/gallium/winsys/virgl/drm
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/winsys/virgl/drm')
-rw-r--r--src/gallium/winsys/virgl/drm/Makefile.am34
-rw-r--r--src/gallium/winsys/virgl/drm/Makefile.sources2
-rw-r--r--src/gallium/winsys/virgl/drm/virgl_drm_public.h30
-rw-r--r--src/gallium/winsys/virgl/drm/virgl_drm_winsys.c764
-rw-r--r--src/gallium/winsys/virgl/drm/virgl_drm_winsys.h98
-rw-r--r--src/gallium/winsys/virgl/drm/virgl_hw.h286
-rw-r--r--src/gallium/winsys/virgl/drm/virtgpu_drm.h163
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