Commit a8987b88 authored by Dave Airlie's avatar Dave Airlie

virgl: add driver for virtio-gpu 3D (v2)

virgl is the 3D acceleration backend for the
virtio-gpu shipping with qemu.

The 3D acceleration is designed around gallium
and TGSI as the virtualisation layer. The backend
renderer translates the virgl interface into
OpenGL currently.

This is the initial import of the driver to mesa.

The kernel driver portions are lined up for drm-next.

Currently this driver supports up to GL3.3 and some
misc extensions if the host driver exposes it. It is
planned to iterate the virgl API to new GL levels
as mesa host drivers gain features.

v2: fix resource tracking across flushes to avoid
->bind hack in mapping.
consolidate mapping and waiting code for transfers.
use u_range for dirt tracking.
handle larger shaders in protocol.
include virtgpu_drm.h in mesa for now.
add translation layer for gallium tgsi to virgl tgsi.
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 531f5d12
......@@ -866,7 +866,7 @@ GALLIUM_DRIVERS_DEFAULT="r300,r600,svga,swrast"
AC_ARG_WITH([gallium-drivers],
[AS_HELP_STRING([--with-gallium-drivers@<:@=DIRS...@:>@],
[comma delimited Gallium drivers list, e.g.
"i915,ilo,nouveau,r300,r600,radeonsi,freedreno,svga,swrast,vc4"
"i915,ilo,nouveau,r300,r600,radeonsi,freedreno,svga,swrast,vc4,virgl"
@<:@default=r300,r600,svga,swrast@:>@])],
[with_gallium_drivers="$withval"],
[with_gallium_drivers="$GALLIUM_DRIVERS_DEFAULT"])
......@@ -2185,6 +2185,12 @@ if test -n "$with_gallium_drivers"; then
PKG_CHECK_MODULES([SIMPENROSE], [simpenrose],
[USE_VC4_SIMULATOR=yes], [USE_VC4_SIMULATOR=no])
;;
xvirgl)
HAVE_GALLIUM_VIRGL=yes
gallium_require_drm "virgl"
gallium_require_drm_loader
require_egl_drm "virgl"
;;
*)
AC_MSG_ERROR([Unknown Gallium driver: $driver])
;;
......@@ -2256,6 +2262,7 @@ AM_CONDITIONAL(HAVE_GALLIUM_FREEDRENO, test "x$HAVE_GALLIUM_FREEDRENO" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_SOFTPIPE, test "x$HAVE_GALLIUM_SOFTPIPE" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_LLVMPIPE, test "x$HAVE_GALLIUM_LLVMPIPE" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_VC4, test "x$HAVE_GALLIUM_VC4" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_VIRGL, test "x$HAVE_GALLIUM_VIRGL" = xyes)
AM_CONDITIONAL(HAVE_GALLIUM_STATIC_TARGETS, test "x$enable_shared_pipe_drivers" = xno)
......@@ -2376,6 +2383,7 @@ AC_CONFIG_FILES([Makefile
src/gallium/drivers/svga/Makefile
src/gallium/drivers/trace/Makefile
src/gallium/drivers/vc4/Makefile
src/gallium/drivers/virgl/Makefile
src/gallium/state_trackers/clover/Makefile
src/gallium/state_trackers/dri/Makefile
src/gallium/state_trackers/glx/xlib/Makefile
......@@ -2416,6 +2424,7 @@ AC_CONFIG_FILES([Makefile
src/gallium/winsys/sw/wrapper/Makefile
src/gallium/winsys/sw/xlib/Makefile
src/gallium/winsys/vc4/drm/Makefile
src/gallium/winsys/virgl/drm/Makefile
src/gbm/Makefile
src/gbm/main/gbm.pc
src/glsl/Makefile
......
......@@ -82,6 +82,11 @@ if HAVE_GALLIUM_VC4
SUBDIRS += drivers/vc4 winsys/vc4/drm
endif
## virgl
if HAVE_GALLIUM_VIRGL
SUBDIRS += drivers/virgl winsys/virgl/drm
endif
## the sw winsys'
SUBDIRS += winsys/sw/null
......
......@@ -59,6 +59,11 @@
#include "vc4/drm/vc4_drm_public.h"
#endif
#if GALLIUM_VIRGL
#include "virgl/drm/virgl_drm_public.h"
#include "virgl/virgl_public.h"
#endif
static char* driver_name = NULL;
/* XXX: We need to teardown the winsys if *screen_create() fails. */
......@@ -296,6 +301,33 @@ pipe_freedreno_create_screen(int fd)
}
#endif
#if defined(GALLIUM_VIRGL)
#if defined(DRI_TARGET)
const __DRIextension **__driDriverGetExtensions_virtio_gpu(void);
PUBLIC const __DRIextension **__driDriverGetExtensions_virtio_gpu(void)
{
globalDriverAPI = &galliumdrm_driver_api;
return galliumdrm_driver_extensions;
}
#endif
static struct pipe_screen *
pipe_virgl_create_screen(int fd)
{
struct virgl_winsys *vws;
struct pipe_screen *screen;
vws = virgl_drm_winsys_create(fd);
if (!vws)
return NULL;
screen = virgl_create_screen(vws);
return screen ? debug_screen_wrap(screen) : NULL;
}
#endif
#if defined(GALLIUM_VC4)
#if defined(DRI_TARGET)
......@@ -385,6 +417,11 @@ dd_create_screen(int fd)
return pipe_freedreno_create_screen(fd);
else
#endif
#if defined(GALLIUM_VIRGL)
if ((strcmp(driver_name, "virtio_gpu") == 0))
return pipe_virgl_create_screen(fd);
else
#endif
#if defined(GALLIUM_VC4)
if (strcmp(driver_name, "vc4") == 0)
return pipe_vc4_create_screen(fd);
......@@ -474,6 +511,11 @@ dd_configuration(enum drm_conf conf)
return configuration_query(conf);
else
#endif
#if defined(GALLIUM_VIRGL)
if ((strcmp(driver_name, "virtio_gpu") == 0))
return configuration_query(conf);
else
#endif
#if defined(GALLIUM_VC4)
if (strcmp(driver_name, "vc4") == 0)
return configuration_query(conf);
......
if HAVE_GALLIUM_VIRGL
TARGET_DRIVERS += virtio_gpu
TARGET_CPPFLAGS += -DGALLIUM_VIRGL
TARGET_LIB_DEPS += \
$(top_builddir)/src/gallium/drivers/virgl/libvirgl.la \
$(top_builddir)/src/gallium/winsys/virgl/drm/libvirgldrm.la
$(LIBDRM_LIBS)
endif
# 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
# 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 $(top_srcdir)/src/gallium/Automake.inc
AM_CPPFLAGS = \
-I$(top_srcdir)/src/gallium/drivers \
-I$(top_srcdir)/src/gallium/winsys/virgl/drm \
-I$(top_srcdir)/include \
$(GALLIUM_CFLAGS) \
$(LIBDRM_CFLAGS)
noinst_LTLIBRARIES = libvirgl.la
libvirgl_la_SOURCES = \
virgl_screen.c \
virgl_resource.c \
virgl_buffer.c \
virgl_texture.c \
virgl_context.c \
virgl_encode.c \
virgl_query.c \
virgl_streamout.c \
virgl_tgsi.c
/*
* 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_H
#define VIRGL_H
#include "util/u_transfer.h"
#include "../winsys/virgl/drm/virgl_hw.h"
#include "virgl_winsys.h"
#include "pipe/p_screen.h"
struct virgl_screen {
struct pipe_screen base;
struct sw_winsys *winsys;
struct virgl_winsys *vws;
struct virgl_drm_caps caps;
uint32_t sub_ctx_id;
};
static inline struct virgl_screen *
virgl_screen( struct pipe_screen *pipe )
{
return (struct virgl_screen *)pipe;
}
#define VIRGL_MAP_BUFFER_ALIGNMENT 64
#endif
/*
* 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.
*/
#include "util/u_memory.h"
#include "virgl_context.h"
#include "virgl_resource.h"
static void virgl_buffer_destroy(struct pipe_screen *screen,
struct pipe_resource *buf)
{
struct virgl_screen *vs = virgl_screen(screen);
struct virgl_buffer *vbuf = virgl_buffer(buf);
util_range_destroy(&vbuf->valid_buffer_range);
vs->vws->resource_unref(vs->vws, vbuf->base.hw_res);
FREE(vbuf);
}
static void *virgl_buffer_transfer_map(struct pipe_context *ctx,
struct pipe_resource *resource,
unsigned level,
unsigned usage,
const struct pipe_box *box,
struct pipe_transfer **transfer)
{
struct virgl_context *vctx = (struct virgl_context *)ctx;
struct virgl_screen *vs = virgl_screen(ctx->screen);
struct virgl_buffer *vbuf = virgl_buffer(resource);
struct virgl_transfer *trans;
void *ptr;
bool readback;
uint32_t offset;
bool doflushwait = false;
if ((usage & PIPE_TRANSFER_READ) && (vbuf->on_list == TRUE))
doflushwait = true;
else
doflushwait = virgl_res_needs_flush_wait(vctx, &vbuf->base, usage);
if (doflushwait)
ctx->flush(ctx, NULL, 0);
trans = util_slab_alloc(&vctx->texture_transfer_pool);
if (trans == NULL)
return NULL;
trans->base.resource = resource;
trans->base.level = level;
trans->base.usage = usage;
trans->base.box = *box;
trans->base.stride = 0;
trans->base.layer_stride = 0;
offset = box->x;
readback = virgl_res_needs_readback(vctx, &vbuf->base, usage);
if (readback)
vs->vws->transfer_get(vs->vws, vbuf->base.hw_res, box, trans->base.stride, trans->base.layer_stride, offset, level);
if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED))
doflushwait = true;
if (doflushwait || readback)
vs->vws->resource_wait(vs->vws, vbuf->base.hw_res);
ptr = vs->vws->resource_map(vs->vws, vbuf->base.hw_res);
if (!ptr) {
return NULL;
}
trans->offset = offset;
*transfer = &trans->base;
return ptr + trans->offset;
}
static void virgl_buffer_transfer_unmap(struct pipe_context *ctx,
struct pipe_transfer *transfer)
{
struct virgl_context *vctx = (struct virgl_context *)ctx;
struct virgl_transfer *trans = (struct virgl_transfer *)transfer;
struct virgl_buffer *vbuf = virgl_buffer(transfer->resource);
if (trans->base.usage & PIPE_TRANSFER_WRITE) {
if (!(transfer->usage & PIPE_TRANSFER_FLUSH_EXPLICIT)) {
struct virgl_screen *vs = virgl_screen(ctx->screen);
vbuf->base.clean = FALSE;
vctx->num_transfers++;
vs->vws->transfer_put(vs->vws, vbuf->base.hw_res,
&transfer->box, trans->base.stride, trans->base.layer_stride, trans->offset, transfer->level);
}
}
util_slab_free(&vctx->texture_transfer_pool, trans);
}
static void virgl_buffer_transfer_flush_region(struct pipe_context *ctx,
struct pipe_transfer *transfer,
const struct pipe_box *box)
{
struct virgl_context *vctx = (struct virgl_context *)ctx;
struct virgl_buffer *vbuf = virgl_buffer(transfer->resource);
if (!vbuf->on_list) {
struct pipe_resource *res = NULL;
list_addtail(&vbuf->flush_list, &vctx->to_flush_bufs);
vbuf->on_list = TRUE;
pipe_resource_reference(&res, &vbuf->base.u.b);
}
util_range_add(&vbuf->valid_buffer_range, transfer->box.x + box->x,
transfer->box.x + box->x + box->width);
vbuf->base.clean = FALSE;
}
static const struct u_resource_vtbl virgl_buffer_vtbl =
{
u_default_resource_get_handle, /* get_handle */
virgl_buffer_destroy, /* resource_destroy */
virgl_buffer_transfer_map, /* transfer_map */
virgl_buffer_transfer_flush_region, /* transfer_flush_region */
virgl_buffer_transfer_unmap, /* transfer_unmap */
virgl_transfer_inline_write /* transfer_inline_write */
};
struct pipe_resource *virgl_buffer_create(struct virgl_screen *vs,
const struct pipe_resource *template)
{
struct virgl_buffer *buf;
uint32_t size;
uint32_t vbind;
buf = CALLOC_STRUCT(virgl_buffer);
buf->base.clean = TRUE;
buf->base.u.b = *template;
buf->base.u.b.screen = &vs->base;
buf->base.u.vtbl = &virgl_buffer_vtbl;
pipe_reference_init(&buf->base.u.b.reference, 1);
util_range_init(&buf->valid_buffer_range);
vbind = pipe_to_virgl_bind(template->bind);
size = template->width0;
buf->base.hw_res = vs->vws->resource_create(vs->vws, template->target, template->format, vbind, template->width0, 1, 1, 1, 0, 0, size);
util_range_set_empty(&buf->valid_buffer_range);
return &buf->base.u.b;
}
This diff is collapsed.
/*
* 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_CONTEXT_H
#define VIRGL_CONTEXT_H
#include "pipe/p_state.h"
#include "pipe/p_context.h"
#include "virgl_protocol.h"
#include "virgl.h"
#include "util/u_slab.h"
#include "util/list.h"
#include "indices/u_primconvert.h"
struct virgl_resource;
struct virgl_buffer;
struct virgl_sampler_view {
struct pipe_sampler_view base;
uint32_t handle;
};
struct virgl_so_target {
struct pipe_stream_output_target base;
uint32_t handle;
};
struct virgl_textures_info {
struct virgl_sampler_view *views[16];
uint32_t enabled_mask;
};
struct virgl_context {
struct pipe_context base;
struct virgl_cmd_buf *cbuf;
struct virgl_textures_info samplers[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
struct util_slab_mempool texture_transfer_pool;
struct pipe_index_buffer index_buffer;
struct u_upload_mgr *uploader;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
unsigned num_vertex_buffers;
boolean vertex_array_dirty;
struct virgl_so_target so_targets[PIPE_MAX_SO_BUFFERS];
unsigned num_so_targets;
struct pipe_resource *ubos[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
int num_transfers;
int num_draws;
struct list_head to_flush_bufs;
struct primconvert_context *primconvert;
uint32_t hw_sub_ctx_id;
};
struct pipe_context *virgl_context_create(struct pipe_screen *pscreen,
void *priv, unsigned flags);
void virgl_init_blit_functions(struct virgl_context *vctx);
void virgl_init_query_functions(struct virgl_context *vctx);
void virgl_init_so_functions(struct virgl_context *vctx);
void virgl_transfer_inline_write(struct pipe_context *ctx,
struct pipe_resource *res,
unsigned level,
unsigned usage,
const struct pipe_box *box,
const void *data,
unsigned stride,
unsigned layer_stride);
struct tgsi_token *virgl_tgsi_transform(const struct tgsi_token *tokens_in);
#endif
This diff is collapsed.
/*
* 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_ENCODE_H
#define VIRGL_ENCODE_H
#include "virgl_context.h"
struct virgl_surface {
struct pipe_surface base;
uint32_t handle;
};
static inline void virgl_encoder_write_dword(struct virgl_cmd_buf *state,
uint32_t dword)
{
state->buf[state->cdw++] = dword;
}
static inline void virgl_encoder_write_qword(struct virgl_cmd_buf *state,
uint64_t qword)
{
memcpy(state->buf + state->cdw, &qword, sizeof(uint64_t));
state->cdw += 2;
}
static inline void virgl_encoder_write_block(struct virgl_cmd_buf *state,
const uint8_t *ptr, uint32_t len)
{
int x;
memcpy(state->buf + state->cdw, ptr, len);
x = (len % 4);
// fprintf(stderr, "[%d] block %d x is %d\n", state->cdw, len, x);
if (x) {
uint8_t *mp = (uint8_t *)(state->buf + state->cdw);
mp += len;
memset(mp, 0, x);
}
state->cdw += (len + 3) / 4;
}
extern int virgl_encode_blend_state(struct virgl_context *ctx,
uint32_t handle,
const struct pipe_blend_state *blend_state);
extern int virgl_encode_rasterizer_state(struct virgl_context *ctx,
uint32_t handle,
const struct pipe_rasterizer_state *state);
extern int virgl_encode_shader_state(struct virgl_context *ctx,
uint32_t handle,
uint32_t type,
const struct pipe_stream_output_info *so_info,
const struct tgsi_token *tokens);
int virgl_encode_stream_output_info(struct virgl_context *ctx,
uint32_t handle,
uint32_t type,
const struct pipe_shader_state *shader);
int virgl_encoder_set_so_targets(struct virgl_context *ctx,
unsigned num_targets,
struct pipe_stream_output_target **targets,
unsigned append_bitmask);
int virgl_encoder_create_so_target(struct virgl_context *ctx,
uint32_t handle,
struct virgl_resource *res,
unsigned buffer_offset,
unsigned buffer_size);
int virgl_encode_clear(struct virgl_context *ctx,
unsigned buffers,
const union pipe_color_union *color,
double depth, unsigned stencil);
int virgl_encode_bind_object(struct virgl_context *ctx,
uint32_t handle, uint32_t object);
int virgl_encode_delete_object(struct virgl_context *ctx,
uint32_t handle, uint32_t object);
int virgl_encoder_set_framebuffer_state(struct virgl_context *ctx,
const struct pipe_framebuffer_state *state);
int virgl_encoder_set_viewport_states(struct virgl_context *ctx,
int start_slot,
int num_viewports,
const struct pipe_viewport_state *states);
int virgl_encoder_draw_vbo(struct virgl_context *ctx,
const struct pipe_draw_info *info);
int virgl_encoder_create_surface(struct virgl_context *ctx,
uint32_t handle,
struct virgl_resource *res,
const struct pipe_surface *templat);
int virgl_encoder_flush_frontbuffer(struct virgl_context *ctx,
struct virgl_resource *res);