import latest renderer code

macos/master
Dave Airlie 10 years ago
parent 852d0aff79
commit 03e3116a75
  1. 32
      src/Makefile.am
  2. 26
      src/gallium/auxiliary/util/u_dual_blend.h
  3. 57
      src/gallium/auxiliary/util/u_texture.h
  4. 162
      src/graw_cursor.c
  5. 24
      src/graw_cursor.h
  6. 911
      src/graw_decode.c
  7. 13
      src/graw_decode.h
  8. 22
      src/graw_iov.h
  9. 322
      src/graw_renderer.h
  10. 40
      src/graw_shader.h
  11. 426
      src/graw_virtio_lib_renderer.c
  12. 346
      src/iov.c
  13. 32
      src/virgl_egl.h
  14. 57
      src/virgl_egl_context.c
  15. 23
      src/virgl_helper.h
  16. 165
      src/virgl_hw.h
  17. 368
      src/virgl_protocol.h
  18. 282
      src/virglrenderer.c
  19. 143
      src/virglrenderer.h
  20. 563
      src/vrend_blitter.c
  21. 45
      src/vrend_blitter.h
  22. 1181
      src/vrend_decode.c
  23. 111
      src/vrend_formats.c
  24. 40
      src/vrend_iov.h
  25. 69
      src/vrend_object.c
  26. 38
      src/vrend_object.h
  27. 3427
      src/vrend_renderer.c
  28. 391
      src/vrend_renderer.h
  29. 24
      src/vrend_renderer_helper.c
  30. 1530
      src/vrend_shader.c
  31. 82
      src/vrend_shader.h

@ -13,37 +13,25 @@ AM_CFLAGS = \
$(EPOXY_CFLAGS) \
$(VISIBILITY_CFLAGS)
#graw_renderer_SOURCES = \
# graw_pipe_renderer.c \
# graw_renderer_glx.c
#graw_shm_renderer_SOURCES = \
# graw_shm_renderer.c \
# graw_renderer_glx.c \
# send_scm.c
#graw_renderer_LDADD = libgrend.la -lX11
#graw_shm_renderer_LDADD = libgrend.la -lrt -lX11
libgrend_la_SOURCES = \
graw_renderer.c \
graw_shader.c \
libvrend_la_SOURCES = \
vrend_renderer.c \
vrend_shader.c \
vrend_object.c \
graw_decode.c \
graw_cursor.c \
graw_formats.c \
vrend_decode.c \
vrend_formats.c \
vrend_blitter.c \
iov.c \
graw_renderer_helper.c \
vrend_renderer_helper.c \
virgl_egl_context.c
lib_LTLIBRARIES = libvirglrenderer.la
noinst_LTLIBRARIES = libgrend.la
noinst_LTLIBRARIES = libvrend.la
GM_LDFLAGS = -Wl,-Bsymbolic -version-number 0:1 -no-undefined
libvirglrenderer_la_SOURCES = graw_virtio_lib_renderer.c
libvirglrenderer_la_SOURCES = virglrenderer.c
libvirglrenderer_ladir = $(libdir)
libvirglrenderer_la_LIBADD = libgrend.la
libvirglrenderer_la_LIBADD = libvrend.la
libvirglrenderer_la_LDFLAGS = $(GM_LDFLAGS) $(EPOXY_LDFLAGS)
libvirglrendererincludedir = ${includedir}

@ -0,0 +1,26 @@
#ifndef U_DUAL_BLEND_H
#define U_DUAL_BLEND_H
#include "pipe/p_state.h"
static INLINE boolean util_blend_factor_is_dual_src(int factor)
{
return (factor == PIPE_BLENDFACTOR_SRC1_COLOR) ||
(factor == PIPE_BLENDFACTOR_SRC1_ALPHA) ||
(factor == PIPE_BLENDFACTOR_INV_SRC1_COLOR) ||
(factor == PIPE_BLENDFACTOR_INV_SRC1_ALPHA);
}
static INLINE boolean util_blend_state_is_dual(const struct pipe_blend_state *blend,
int index)
{
if (util_blend_factor_is_dual_src(blend->rt[index].rgb_src_factor) ||
util_blend_factor_is_dual_src(blend->rt[index].alpha_src_factor) ||
util_blend_factor_is_dual_src(blend->rt[index].rgb_dst_factor) ||
util_blend_factor_is_dual_src(blend->rt[index].alpha_dst_factor))
return true;
return false;
}
#endif

@ -0,0 +1,57 @@
/**************************************************************************
*
* Copyright 2009 Marek Olšák <maraeo@gmail.com>
*
* 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, 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 VMWARE 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 U_TEXTURE_H
#define U_TEXTURE_H
#include "pipe/p_compiler.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Convert 2D texture coordinates of 4 vertices into cubemap coordinates
* in the given face.
* Coordinates must be in the range [0,1].
*
* \param face Cubemap face.
* \param in_st 4 pairs of 2D texture coordinates to convert.
* \param in_stride Stride of in_st in floats.
* \param out_str STR cubemap texture coordinates to compute.
* \param out_stride Stride of out_str in floats.
*/
void util_map_texcoords2d_onto_cubemap(unsigned face,
const float *in_st, unsigned in_stride,
float *out_str, unsigned out_stride,
boolean allow_scale);
#ifdef __cplusplus
}
#endif
#endif

@ -1,162 +0,0 @@
#include <epoxy/gl.h>
#include <stdio.h>
#include "graw_renderer.h"
#include "vrend_object.h"
#include "graw_cursor.h"
static const GLchar *cursor_vs_shader =
"attribute vec2 position;\n"
"attribute vec2 textureCoords;\n"
"varying vec2 texCoords;\n"
"void main()\n"
"{\n"
" texCoords = textureCoords;\n"
" gl_Position = vec4(position, 0.0, 1.0);\n"
"}\n";
static const GLchar *cursor_fs_shader =
"uniform sampler2D texSampler;\n"
"varying vec2 texCoords;\n"
"void main()\n"
"{\n"
" gl_FragColor = texture2D(texSampler, texCoords);\n"
"}\n";
void graw_cursor_init(struct graw_cursor_info *cursor)
{
GLuint curs_vs_id, curs_fs_id;
cursor->prog_id = glCreateProgram();
curs_vs_id = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(curs_vs_id, 1, &cursor_vs_shader, NULL);
glCompileShader(curs_vs_id);
curs_fs_id = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(curs_fs_id, 1, &cursor_fs_shader, NULL);
glCompileShader(curs_fs_id);
glAttachShader(cursor->prog_id, curs_vs_id);
glAttachShader(cursor->prog_id, curs_fs_id);
glLinkProgram(cursor->prog_id);
glGenBuffersARB(1, &cursor->vbo_id);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, cursor->vbo_id);
glBufferData(GL_ARRAY_BUFFER_ARB, 4 * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW);
cursor->attrib_locs[0] = glGetAttribLocation(cursor->prog_id, "position");
cursor->attrib_locs[1] = glGetAttribLocation(cursor->prog_id, "textureCoords");
cursor->samp_loc = glGetUniformLocation(cursor->prog_id, "texSampler");
glGenVertexArrays(1, &cursor->vaoid);
grend_bind_va(cursor->vaoid);
glVertexAttribPointer(cursor->attrib_locs[0], 2, GL_FLOAT, GL_FALSE, 16, 0);
glVertexAttribDivisorARB(cursor->attrib_locs[0], 0);
glVertexAttribPointer(cursor->attrib_locs[1], 2, GL_FLOAT, GL_FALSE, 16, (GLvoid *)8);
glVertexAttribDivisorARB(cursor->attrib_locs[1], 0);
glEnableVertexAttribArray(cursor->attrib_locs[0]);
glEnableVertexAttribArray(cursor->attrib_locs[1]);
}
int graw_renderer_remove_cursor(struct graw_cursor_info *cursor,
struct grend_resource *dst_res)
{
struct pipe_box box;
box.x = cursor->last_x;
box.y = cursor->last_y;
box.z = 0;
box.width = 64;
box.height = 64;
box.depth = 1;
graw_renderer_flush_buffer_res(dst_res, &box);
return 0;
}
int graw_renderer_paint_cursor(struct graw_cursor_info *cursor,
struct grend_resource *dst_res)
{
GLuint fb_id;
struct grend_resource *cursor_res;
struct vertex {
GLfloat x, y, s, t;
};
struct vertex verts[4];
GLuint locs[2];
GLfloat x0, y0, x1, y1;
int s_w, s_h;
if (!cursor->res_handle)
return 0;
cursor_res = vrend_resource_lookup(cursor->res_handle, 0);
if (!cursor_res)
return 0;
s_w = dst_res->base.width0;
s_h = dst_res->base.height0;
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glDrawBuffer(GL_BACK);
grend_use_program(cursor->prog_id);
glUniform1i(cursor->samp_loc, 0);
grend_blend_enable(GL_TRUE);
grend_depth_test_enable(GL_FALSE);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glBlendEquation(GL_FUNC_ADD);
glActiveTexture(GL_TEXTURE0);
glBindTexture(cursor_res->target, cursor_res->id);
glTexParameteri(cursor_res->target, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(cursor_res->target, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameterf(cursor_res->target, GL_TEXTURE_MIN_LOD, 0);
glTexParameterf(cursor_res->target, GL_TEXTURE_MAX_LOD, 0);
glTexParameterf(cursor_res->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(cursor_res->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
grend_bind_va(cursor->vaoid);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, cursor->vbo_id);
cursor->last_x = cursor->x;
cursor->last_y = cursor->y;
x0 = ((float)cursor->x / (s_w / 2)) - 1.0;
y0 = ((float)(s_h - cursor->y - cursor_res->base.width0) / (s_h / 2)) - 1.0;
x1 = (((float)cursor->x + cursor_res->base.height0) / (s_w / 2)) - 1.0;
y1 = (((float)(s_h - cursor->y)) / (s_h / 2)) - 1.0;
verts[0].x = x0;
verts[0].y = y0;
verts[1].x = x1;
verts[1].y = y0;
verts[2].x = x1;
verts[2].y = y1;
verts[3].x = x0;
verts[3].y = y1;
verts[0].s = 0.0;
verts[0].t = 1.0;
verts[1].s = 1.0;
verts[1].t = 1.0;
verts[2].s = 1.0;
verts[2].t = 0.0;
verts[3].s = 0.0;
verts[3].t = 0.0;
glBufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts);
glDrawArrays(GL_QUADS, 0, 4);
return 0;
}

@ -1,24 +0,0 @@
#ifndef GRAW_CURSOR_H
#define GRAW_CURSOR_H
/* cursor drawing state */
struct graw_cursor_info {
GLuint prog_id;
GLuint vaoid;
GLuint vbo_id;
uint32_t res_handle;
int x, y;
GLuint attrib_locs[2];
GLuint samp_loc;
int last_x, last_y;
};
void graw_cursor_init(struct graw_cursor_info *cursor);
int graw_renderer_paint_cursor(struct graw_cursor_info *cursor,
struct grend_resource *dst_res);
int graw_renderer_remove_cursor(struct graw_cursor_info *cursor,
struct grend_resource *dst_res);
#endif

@ -1,911 +0,0 @@
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <epoxy/gl.h>
#include "util/u_memory.h"
#include "pipe/p_state.h"
#include "pipe/p_shader_tokens.h"
#include "graw_decode.h"
#include "graw_renderer.h"
#include "vrend_object.h"
#include "tgsi/tgsi_text.h"
/* decode side */
#define DECODE_MAX_TOKENS 8000
struct grend_decode_ctx {
struct graw_decoder_state ids, *ds;
struct grend_context *grctx;
};
#define GRAW_MAX_CTX 16
static struct grend_decode_ctx *dec_ctx[GRAW_MAX_CTX];
static int graw_decode_create_shader(struct grend_decode_ctx *ctx, uint32_t type,
uint32_t handle,
uint16_t length)
{
struct pipe_shader_state *state = CALLOC_STRUCT(pipe_shader_state);
struct tgsi_token *tokens;
int i;
uint32_t shader_offset;
unsigned num_tokens;
if (!state)
return NULL;
num_tokens = ctx->ds->buf[ctx->ds->buf_offset + 2];
if (num_tokens == 0)
num_tokens = 300;
tokens = calloc(num_tokens + 10, sizeof(struct tgsi_token));
if (!tokens) {
free(state);
return -1;
}
state->stream_output.num_outputs = ctx->ds->buf[ctx->ds->buf_offset + 3];
if (state->stream_output.num_outputs) {
for (i = 0; i < 4; i++)
state->stream_output.stride[i] = ctx->ds->buf[ctx->ds->buf_offset + 4 + i];
for (i = 0; i < state->stream_output.num_outputs; i++) {
uint32_t tmp = ctx->ds->buf[ctx->ds->buf_offset + 8 + i];
state->stream_output.output[i].register_index = tmp & 0xff;
state->stream_output.output[i].start_component = (tmp >> 8) & 0x3;
state->stream_output.output[i].num_components = (tmp >> 10) & 0x7;
state->stream_output.output[i].output_buffer = (tmp >> 13) & 0x7;
state->stream_output.output[i].dst_offset = (tmp >> 16) & 0xffff;
}
shader_offset = 8 + state->stream_output.num_outputs;
} else
shader_offset = 4;
if (vrend_dump_shaders)
fprintf(stderr,"shader\n%s\n", &ctx->ds->buf[ctx->ds->buf_offset + shader_offset]);
if (!tgsi_text_translate(&ctx->ds->buf[ctx->ds->buf_offset + shader_offset], tokens, num_tokens + 10)) {
fprintf(stderr,"failed to translate\n %s\n",&ctx->ds->buf[ctx->ds->buf_offset + shader_offset]);
free(tokens);
free(state);
return -1;
}
state->tokens = tokens;
if (type == VIRGL_OBJECT_FS)
grend_create_fs(ctx->grctx, handle, state);
else
grend_create_vs(ctx->grctx, handle, state);
free(tokens);
free(state);
return 0;
}
static int graw_decode_create_stream_output_target(struct grend_decode_ctx *ctx, uint32_t handle)
{
uint32_t res_handle, buffer_size, buffer_offset;
res_handle = ctx->ds->buf[ctx->ds->buf_offset + 2];
buffer_offset = ctx->ds->buf[ctx->ds->buf_offset + 3];
buffer_size = ctx->ds->buf[ctx->ds->buf_offset + 4];
grend_create_so_target(ctx->grctx, handle, res_handle, buffer_offset,
buffer_size);
}
static void graw_decode_set_framebuffer_state(struct grend_decode_ctx *ctx)
{
uint32_t nr_cbufs = ctx->ds->buf[ctx->ds->buf_offset + 1];
uint32_t zsurf_handle = ctx->ds->buf[ctx->ds->buf_offset + 2];
uint32_t surf_handle[8];
int i;
for (i = 0; i < nr_cbufs; i++)
surf_handle[i] = ctx->ds->buf[ctx->ds->buf_offset + 3 + i];
grend_set_framebuffer_state(ctx->grctx, nr_cbufs, surf_handle, zsurf_handle);
}
static void graw_decode_clear(struct grend_decode_ctx *ctx)
{
union pipe_color_union color;
double depth;
unsigned stencil, buffers;
int i;
int index = ctx->ds->buf_offset + 1;
buffers = ctx->ds->buf[index++];
for (i = 0; i < 4; i++)
color.ui[i] = ctx->ds->buf[index++];
depth = *(double *)(uint64_t *)(&ctx->ds->buf[index]);
index += 2;
stencil = ctx->ds->buf[index++];
grend_clear(ctx->grctx, buffers, &color, depth, stencil);
}
static float uif(unsigned int ui)
{
union { float f; unsigned int ui; } myuif;
myuif.ui = ui;
return myuif.f;
}
static void graw_decode_set_viewport_state(struct grend_decode_ctx *ctx)
{
struct pipe_viewport_state vps;
int i;
for (i = 0; i < 4; i++)
vps.scale[i] = uif(ctx->ds->buf[ctx->ds->buf_offset + 1 + i]);
for (i = 0; i < 4; i++)
vps.translate[i] = uif(ctx->ds->buf[ctx->ds->buf_offset + 5 + i]);
grend_set_viewport_state(ctx->grctx, &vps);
}
static void graw_decode_set_index_buffer(struct grend_decode_ctx *ctx)
{
int offset = ctx->ds->buf_offset;
grend_set_index_buffer(ctx->grctx, ctx->ds->buf[offset + 1],
ctx->ds->buf[offset + 2],
ctx->ds->buf[offset + 3]);
}
static void graw_decode_set_constant_buffer(struct grend_decode_ctx *ctx, uint16_t length)
{
int offset = ctx->ds->buf_offset;
uint32_t shader = ctx->ds->buf[offset + 1];
uint32_t index = ctx->ds->buf[offset + 2];
int nc = (length - 2);
grend_set_constants(ctx->grctx, shader, index, nc, &ctx->ds->buf[offset + 3]);
}
static void graw_decode_set_vertex_buffers(struct grend_decode_ctx *ctx, uint16_t length)
{
int num_vbo;
int i;
num_vbo = (length / 3);
for (i = 0; i < num_vbo; i++) {
int element_offset = ctx->ds->buf_offset + 1 + (i * 3);
grend_set_single_vbo(ctx->grctx, i,
ctx->ds->buf[element_offset],
ctx->ds->buf[element_offset + 1],
ctx->ds->buf[element_offset + 2]);
}
grend_set_num_vbo(ctx->grctx, num_vbo);
}
static void graw_decode_set_sampler_views(struct grend_decode_ctx *ctx, uint16_t length)
{
int num_samps;
int i;
uint32_t shader_type, start_slot;
num_samps = length - 2;
shader_type = ctx->ds->buf[ctx->ds->buf_offset + 1];
start_slot = ctx->ds->buf[ctx->ds->buf_offset + 2];
for (i = 0; i < num_samps; i++) {
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset + 3 + i];
grend_set_single_sampler_view(ctx->grctx, shader_type, i + start_slot, handle);
}
grend_set_num_sampler_views(ctx->grctx, shader_type, start_slot, num_samps);
}
static void graw_decode_resource_inline_write(struct grend_decode_ctx *ctx, uint16_t length)
{
struct pipe_box box;
uint32_t res_handle = ctx->ds->buf[ctx->ds->buf_offset + 1];
uint32_t level, usage, stride, layer_stride;
void *data;
level = ctx->ds->buf[ctx->ds->buf_offset + 2];
usage = ctx->ds->buf[ctx->ds->buf_offset + 3];
stride = ctx->ds->buf[ctx->ds->buf_offset + 4];
layer_stride = ctx->ds->buf[ctx->ds->buf_offset + 5];
box.x = ctx->ds->buf[ctx->ds->buf_offset + 6];
box.y = ctx->ds->buf[ctx->ds->buf_offset + 7];
box.z = ctx->ds->buf[ctx->ds->buf_offset + 8];
box.width = ctx->ds->buf[ctx->ds->buf_offset + 9];
box.height = ctx->ds->buf[ctx->ds->buf_offset + 10];
box.depth = ctx->ds->buf[ctx->ds->buf_offset + 11];
data = &ctx->ds->buf[ctx->ds->buf_offset + 12];
grend_transfer_inline_write(ctx->grctx, res_handle, level,
usage, &box, data, stride, layer_stride);
}
static void graw_decode_draw_vbo(struct grend_decode_ctx *ctx)
{
struct pipe_draw_info info;
memset(&info, 0, sizeof(struct pipe_draw_info));
info.start = ctx->ds->buf[ctx->ds->buf_offset + 1];
info.count = ctx->ds->buf[ctx->ds->buf_offset + 2];
info.mode = ctx->ds->buf[ctx->ds->buf_offset + 3];
info.indexed = ctx->ds->buf[ctx->ds->buf_offset + 4];
info.instance_count = ctx->ds->buf[ctx->ds->buf_offset + 5];
info.index_bias = ctx->ds->buf[ctx->ds->buf_offset + 6];
info.start_instance = ctx->ds->buf[ctx->ds->buf_offset + 7];
info.primitive_restart = ctx->ds->buf[ctx->ds->buf_offset + 8];
info.restart_index = ctx->ds->buf[ctx->ds->buf_offset + 9];
info.min_index = ctx->ds->buf[ctx->ds->buf_offset + 10];
info.max_index = ctx->ds->buf[ctx->ds->buf_offset + 11];
grend_draw_vbo(ctx->grctx, &info);
}
static void graw_decode_create_blend(struct grend_decode_ctx *ctx, uint32_t handle, uint16_t length)
{
struct pipe_blend_state *blend_state = CALLOC_STRUCT(pipe_blend_state);
uint32_t tmp;
int i;
tmp = ctx->ds->buf[ctx->ds->buf_offset + 2];
blend_state->independent_blend_enable = (tmp & 1);
blend_state->logicop_enable = (tmp >> 1) & 0x1;
blend_state->dither = (tmp >> 2) & 0x1;
blend_state->alpha_to_coverage = (tmp >> 3) & 0x1;
blend_state->alpha_to_one = (tmp >> 4) & 0x1;
tmp = ctx->ds->buf[ctx->ds->buf_offset + 3];
blend_state->logicop_func = tmp & 0xf;
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
tmp = ctx->ds->buf[ctx->ds->buf_offset + 4 + i];
blend_state->rt[i].blend_enable = tmp & 0x1;
blend_state->rt[i].rgb_func = (tmp >> 1) & 0x7;
blend_state->rt[i].rgb_src_factor = (tmp >> 4) & 0x1f;
blend_state->rt[i].rgb_dst_factor = (tmp >> 9) & 0x1f;
blend_state->rt[i].alpha_func = (tmp >> 14) & 0x7;
blend_state->rt[i].alpha_src_factor = (tmp >> 17) & 0x1f;
blend_state->rt[i].alpha_dst_factor = (tmp >> 22) & 0x1f;
blend_state->rt[i].colormask = (tmp >> 27) & 0xf;
}
graw_renderer_object_insert(ctx->grctx, blend_state, sizeof(struct pipe_blend_state), handle,
VIRGL_OBJECT_BLEND);
}
static void graw_decode_create_dsa(struct grend_decode_ctx *ctx, uint32_t handle, uint16_t length)
{
int i;
struct pipe_depth_stencil_alpha_state *dsa_state = CALLOC_STRUCT(pipe_depth_stencil_alpha_state);
uint32_t tmp;
tmp = ctx->ds->buf[ctx->ds->buf_offset + 2];
dsa_state->depth.enabled = tmp & 0x1;
dsa_state->depth.writemask = (tmp >> 1) & 0x1;
dsa_state->depth.func = (tmp >> 2) & 0x7;
dsa_state->alpha.enabled = (tmp >> 8) & 0x1;
dsa_state->alpha.func = (tmp >> 9) & 0x7;
for (i = 0; i < 2; i++) {
tmp = ctx->ds->buf[ctx->ds->buf_offset + 3 + i];
dsa_state->stencil[i].enabled = tmp & 0x1;
dsa_state->stencil[i].func = (tmp >> 1) & 0x7;
dsa_state->stencil[i].fail_op = (tmp >> 4) & 0x7;
dsa_state->stencil[i].zpass_op = (tmp >> 7) & 0x7;
dsa_state->stencil[i].zfail_op = (tmp >> 10) & 0x7;
dsa_state->stencil[i].valuemask = (tmp >> 13) & 0xff;
dsa_state->stencil[i].writemask = (tmp >> 21) & 0xff;
}
tmp = ctx->ds->buf[ctx->ds->buf_offset + 5];
dsa_state->alpha.ref_value = uif(tmp);
graw_renderer_object_insert(ctx->grctx, dsa_state, sizeof(struct pipe_depth_stencil_alpha_state), handle,
VIRGL_OBJECT_DSA);
}
static void graw_decode_create_rasterizer(struct grend_decode_ctx *ctx, uint32_t handle, uint16_t length)
{
struct pipe_rasterizer_state *rs_state = CALLOC_STRUCT(pipe_rasterizer_state);
uint32_t tmp;
tmp = ctx->ds->buf[ctx->ds->buf_offset + 2];
#define ebit(name, bit) rs_state->name = (tmp >> bit) & 0x1
#define emask(name, bit, mask) rs_state->name = (tmp >> bit) & mask
ebit(flatshade, 0);
ebit(depth_clip, 1);
ebit(clip_halfz, 2);
ebit(rasterizer_discard, 3);
ebit(flatshade_first, 4);
ebit(light_twoside, 5);
ebit(sprite_coord_mode, 6);
ebit(point_quad_rasterization, 7);
emask(cull_face, 8, 0x3);
emask(fill_front, 10, 0x3);
emask(fill_back, 12, 0x3);
ebit(scissor, 14);
ebit(front_ccw, 15);
ebit(clamp_vertex_color, 16);
ebit(clamp_fragment_color, 17);
ebit(offset_line, 18);
ebit(offset_point, 19);
ebit(offset_tri, 20);
ebit(poly_smooth, 21);
ebit(poly_stipple_enable, 22);
ebit(point_smooth, 23);
ebit(point_size_per_vertex, 24);
ebit(multisample, 25);
ebit(line_smooth, 26);
ebit(line_stipple_enable, 27);
ebit(line_last_pixel, 28);
ebit(half_pixel_center, 29);
ebit(bottom_edge_rule, 30);
rs_state->point_size = uif(ctx->ds->buf[ctx->ds->buf_offset + 3]);
rs_state->sprite_coord_enable = ctx->ds->buf[ctx->ds->buf_offset + 4];
tmp = ctx->ds->buf[ctx->ds->buf_offset + 5];
emask(line_stipple_pattern, 0, 0xffff);
emask(line_stipple_factor, 16, 0xff);
emask(clip_plane_enable, 24, 0xff);
rs_state->line_width = uif(ctx->ds->buf[ctx->ds->buf_offset + 6]);
rs_state->offset_units = uif(ctx->ds->buf[ctx->ds->buf_offset + 7]);
rs_state->offset_scale = uif(ctx->ds->buf[ctx->ds->buf_offset + 8]);
rs_state->offset_clamp = uif(ctx->ds->buf[ctx->ds->buf_offset + 9]);
graw_renderer_object_insert(ctx->grctx, rs_state, sizeof(struct pipe_rasterizer_state), handle,
VIRGL_OBJECT_RASTERIZER);
}
static void graw_decode_create_surface(struct grend_decode_ctx *ctx, uint32_t handle)
{
uint32_t res_handle, format, val0, val1;
res_handle = ctx->ds->buf[ctx->ds->buf_offset + 2];
format = ctx->ds->buf[ctx->ds->buf_offset + 3];
val0 = ctx->ds->buf[ctx->ds->buf_offset + 4];
val1 = ctx->ds->buf[ctx->ds->buf_offset + 5];
grend_create_surface(ctx->grctx, handle, res_handle, format, val0, val1);
}
static void graw_decode_create_sampler_view(struct grend_decode_ctx *ctx, uint32_t handle)
{
uint32_t res_handle, format, val0, val1, swizzle_packed;
res_handle = ctx->ds->buf[ctx->ds->buf_offset + 2];
format = ctx->ds->buf[ctx->ds->buf_offset + 3];
val0 = ctx->ds->buf[ctx->ds->buf_offset + 4];
val1 = ctx->ds->buf[ctx->ds->buf_offset + 5];
swizzle_packed = ctx->ds->buf[ctx->ds->buf_offset + 6];
grend_create_sampler_view(ctx->grctx, handle, res_handle, format, val0, val1,swizzle_packed);
}
static void graw_decode_create_sampler_state(struct grend_decode_ctx *ctx, uint32_t handle, uint16_t length)
{
struct pipe_sampler_state *state = CALLOC_STRUCT(pipe_sampler_state);
int i;
uint32_t tmp;
tmp = ctx->ds->buf[ctx->ds->buf_offset + 2];
state->wrap_s = tmp & 0x7;
state->wrap_t = (tmp >> 3) & 0x7;
state->wrap_r = (tmp >> 6) & 0x7;
state->min_img_filter = (tmp >> 9) & 0x3;
state->min_mip_filter = (tmp >> 11) & 0x3;
state->mag_img_filter = (tmp >> 13) & 0x3;
state->compare_mode = (tmp >> 15) & 0x1;
state->compare_func = (tmp >> 16) & 0x7;
state->lod_bias = uif(ctx->ds->buf[ctx->ds->buf_offset + 3]);
state->min_lod = uif(ctx->ds->buf[ctx->ds->buf_offset + 4]);
state->max_lod = uif(ctx->ds->buf[ctx->ds->buf_offset + 5]);
for (i = 0; i < 4; i++)
state->border_color.ui[i] = ctx->ds->buf[ctx->ds->buf_offset + 6 + i];
graw_renderer_object_insert(ctx->grctx, state, sizeof(struct pipe_sampler_state), handle,
VIRGL_OBJECT_SAMPLER_STATE);
}
static void graw_decode_create_ve(struct grend_decode_ctx *ctx, uint32_t handle, uint16_t length)
{
struct pipe_vertex_element *ve;
int num_elements;
int i;
num_elements = (length - 1) / 4;
ve = calloc(num_elements, sizeof(struct pipe_vertex_element));
if (!ve)
return;
for (i = 0; i < num_elements; i++) {
uint32_t element_offset = ctx->ds->buf_offset + 2 + (i * 4);
ve[i].src_offset = ctx->ds->buf[element_offset];
ve[i].instance_divisor = ctx->ds->buf[element_offset + 1];
ve[i].vertex_buffer_index = ctx->ds->buf[element_offset + 2];
ve[i].src_format = ctx->ds->buf[element_offset + 3];
}
grend_create_vertex_elements_state(ctx->grctx, handle, num_elements,
ve);
}
static void graw_decode_create_query(struct grend_decode_ctx *ctx, uint32_t handle)
{
uint32_t query_type;
uint32_t res_handle;
uint32_t offset;
query_type = ctx->ds->buf[ctx->ds->buf_offset + 2];
offset = ctx->ds->buf[ctx->ds->buf_offset + 3];
res_handle = ctx->ds->buf[ctx->ds->buf_offset + 4];
grend_create_query(ctx->grctx, handle, query_type, res_handle, offset);
}
static void graw_decode_create_object(struct grend_decode_ctx *ctx)
{
uint32_t header = ctx->ds->buf[ctx->ds->buf_offset];
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset+1];
uint16_t length;
uint8_t obj_type = (header >> 8) & 0xff;
length = header >> 16;
switch (obj_type){
case VIRGL_OBJECT_BLEND:
graw_decode_create_blend(ctx, handle, length);
break;
case VIRGL_OBJECT_DSA:
graw_decode_create_dsa(ctx, handle, length);
break;
case VIRGL_OBJECT_RASTERIZER:
graw_decode_create_rasterizer(ctx, handle, length);
break;
case VIRGL_OBJECT_VS:
case VIRGL_OBJECT_FS:
graw_decode_create_shader(ctx, obj_type, handle, length);
break;
case VIRGL_OBJECT_VERTEX_ELEMENTS:
graw_decode_create_ve(ctx, handle, length);
break;
case VIRGL_OBJECT_SURFACE:
graw_decode_create_surface(ctx, handle);
break;
case VIRGL_OBJECT_SAMPLER_VIEW:
graw_decode_create_sampler_view(ctx, handle);
break;
case VIRGL_OBJECT_SAMPLER_STATE:
graw_decode_create_sampler_state(ctx, handle, length);
break;
case VIRGL_OBJECT_QUERY:
graw_decode_create_query(ctx, handle);
break;
case VIRGL_OBJECT_STREAMOUT_TARGET:
graw_decode_create_stream_output_target(ctx, handle);
break;
}
}
static void graw_decode_bind_object(struct grend_decode_ctx *ctx)
{
uint32_t header = ctx->ds->buf[ctx->ds->buf_offset];
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset+1];
uint16_t length;
uint8_t obj_type = (header >> 8) & 0xff;
length = header >> 16;
switch (obj_type) {
case VIRGL_OBJECT_BLEND:
grend_object_bind_blend(ctx->grctx, handle);
break;
case VIRGL_OBJECT_DSA:
grend_object_bind_dsa(ctx->grctx, handle);
break;
case VIRGL_OBJECT_RASTERIZER:
grend_object_bind_rasterizer(ctx->grctx, handle);
break;
case VIRGL_OBJECT_VS:
grend_bind_vs(ctx->grctx, handle);
break;
case VIRGL_OBJECT_FS:
grend_bind_fs(ctx->grctx, handle);
break;
case VIRGL_OBJECT_VERTEX_ELEMENTS:
grend_bind_vertex_elements_state(ctx->grctx, handle);
break;
}
}
static void graw_decode_destroy_object(struct grend_decode_ctx *ctx)
{
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset+1];
graw_renderer_object_destroy(ctx->grctx, handle);
}
void graw_reset_decode(void)
{
// free(gdctx->grctx);
// gdctx->grctx = NULL;
//gdctx->ds = NULL;
}
static void graw_decode_set_stencil_ref(struct grend_decode_ctx *ctx)
{
struct pipe_stencil_ref ref;
uint32_t val = ctx->ds->buf[ctx->ds->buf_offset + 1];
ref.ref_value[0] = val & 0xff;
ref.ref_value[1] = (val >> 8) & 0xff;
grend_set_stencil_ref(ctx->grctx, &ref);
}
static void graw_decode_set_blend_color(struct grend_decode_ctx *ctx)
{
struct pipe_blend_color color;
int i;
for (i = 0; i < 4; i++)
color.color[i] = uif(ctx->ds->buf[ctx->ds->buf_offset + 1 + i]);
grend_set_blend_color(ctx->grctx, &color);
}
static void graw_decode_set_scissor_state(struct grend_decode_ctx *ctx)
{
struct pipe_scissor_state ss;
uint32_t temp;
temp = ctx->ds->buf[ctx->ds->buf_offset + 1];
ss.minx = temp & 0xffff;
ss.miny = (temp >> 16) & 0xffff;
temp = ctx->ds->buf[ctx->ds->buf_offset + 2];
ss.maxx = temp & 0xffff;
ss.maxy = (temp >> 16) & 0xffff;
grend_set_scissor_state(ctx->grctx, &ss);
}
static void graw_decode_set_polygon_stipple(struct grend_decode_ctx *ctx)
{
struct pipe_poly_stipple ps;
int i;
for (i = 0; i < 32; i++)
ps.stipple[i] = ctx->ds->buf[ctx->ds->buf_offset + 1 + i];
grend_set_polygon_stipple(ctx->grctx, &ps);
}
static void graw_decode_set_clip_state(struct grend_decode_ctx *ctx)
{
struct pipe_clip_state clip;
int i, j;
for (i = 0; i < 8; i++)
for (j = 0; j < 4; j++)
clip.ucp[i][j] = uif(ctx->ds->buf[ctx->ds->buf_offset + 1 + (i * 4) + j]);
grend_set_clip_state(ctx->grctx, &clip);
}
static void graw_decode_set_sample_mask(struct grend_decode_ctx *ctx)
{
unsigned mask;
mask = ctx->ds->buf[ctx->ds->buf_offset + 1];
grend_set_sample_mask(ctx->grctx, mask);
}
static void graw_decode_resource_copy_region(struct grend_decode_ctx *ctx)
{
struct pipe_box box;
uint32_t dst_handle, src_handle;
uint32_t dst_level, dstx, dsty, dstz;
uint32_t src_level;
dst_handle = ctx->ds->buf[ctx->ds->buf_offset + 1];
dst_level = ctx->ds->buf[ctx->ds->buf_offset + 2];
dstx = ctx->ds->buf[ctx->ds->buf_offset + 3];
dsty = ctx->ds->buf[ctx->ds->buf_offset + 4];
dstz = ctx->ds->buf[ctx->ds->buf_offset + 5];
src_handle = ctx->ds->buf[ctx->ds->buf_offset + 6];
src_level = ctx->ds->buf[ctx->ds->buf_offset + 7];
box.x = ctx->ds->buf[ctx->ds->buf_offset + 8];
box.y = ctx->ds->buf[ctx->ds->buf_offset + 9];
box.z = ctx->ds->buf[ctx->ds->buf_offset + 10];
box.width = ctx->ds->buf[ctx->ds->buf_offset + 11];
box.height = ctx->ds->buf[ctx->ds->buf_offset + 12];
box.depth = ctx->ds->buf[ctx->ds->buf_offset + 13];
graw_renderer_resource_copy_region(ctx->grctx, dst_handle,
dst_level, dstx, dsty, dstz,
src_handle, src_level,
&box);
}
static void graw_decode_blit(struct grend_decode_ctx *ctx)
{
struct pipe_blit_info info;
uint32_t dst_handle, src_handle, temp;
info.mask = ctx->ds->buf[ctx->ds->buf_offset + 1];
info.filter = ctx->ds->buf[ctx->ds->buf_offset + 2];
info.scissor_enable = ctx->ds->buf[ctx->ds->buf_offset + 3] & 1;
temp = ctx->ds->buf[ctx->ds->buf_offset + 4];
info.scissor.minx = temp & 0xffff;
info.scissor.miny = (temp >> 16) & 0xffff;
temp = ctx->ds->buf[ctx->ds->buf_offset + 5];
info.scissor.maxx = temp & 0xffff;
info.scissor.maxy = (temp >> 16) & 0xffff;
dst_handle = ctx->ds->buf[ctx->ds->buf_offset + 6];
info.dst.level = ctx->ds->buf[ctx->ds->buf_offset + 7];
info.dst.format = ctx->ds->buf[ctx->ds->buf_offset + 8];
info.dst.box.x = ctx->ds->buf[ctx->ds->buf_offset + 9];
info.dst.box.y = ctx->ds->buf[ctx->ds->buf_offset + 10];
info.dst.box.z = ctx->ds->buf[ctx->ds->buf_offset + 11];
info.dst.box.width = ctx->ds->buf[ctx->ds->buf_offset + 12];
info.dst.box.height = ctx->ds->buf[ctx->ds->buf_offset + 13];
info.dst.box.depth = ctx->ds->buf[ctx->ds->buf_offset + 14];
src_handle = ctx->ds->buf[ctx->ds->buf_offset + 15];
info.src.level = ctx->ds->buf[ctx->ds->buf_offset + 16];
info.src.format = ctx->ds->buf[ctx->ds->buf_offset + 17];
info.src.box.x = ctx->ds->buf[ctx->ds->buf_offset + 18];
info.src.box.y = ctx->ds->buf[ctx->ds->buf_offset + 19];
info.src.box.z = ctx->ds->buf[ctx->ds->buf_offset + 20];
info.src.box.width = ctx->ds->buf[ctx->ds->buf_offset + 21];
info.src.box.height = ctx->ds->buf[ctx->ds->buf_offset + 22];
info.src.box.depth = ctx->ds->buf[ctx->ds->buf_offset + 23];
graw_renderer_blit(ctx->grctx, dst_handle, src_handle, &info);
}
static void graw_decode_bind_sampler_states(struct grend_decode_ctx *ctx, int length)
{
uint32_t shader_type = ctx->ds->buf[ctx->ds->buf_offset + 1];
uint32_t start_slot = ctx->ds->buf[ctx->ds->buf_offset + 2];
uint32_t num_states = length - 1;
grend_bind_sampler_states(ctx->grctx, shader_type, start_slot, num_states,
&ctx->ds->buf[ctx->ds->buf_offset + 3]);
}
static void graw_decode_begin_query(struct grend_decode_ctx *ctx)
{
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset + 1];
grend_begin_query(ctx->grctx, handle);
}
static void graw_decode_end_query(struct grend_decode_ctx *ctx)
{
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset + 1];
grend_end_query(ctx->grctx, handle);
}
static void graw_decode_get_query_result(struct grend_decode_ctx *ctx)
{
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset + 1];
uint32_t wait = ctx->ds->buf[ctx->ds->buf_offset + 2];
grend_get_query_result(ctx->grctx, handle, wait);
}
static void graw_decode_set_render_condition(struct grend_decode_ctx *ctx)
{
uint32_t handle = ctx->ds->buf[ctx->ds->buf_offset + 1];
boolean condition = ctx->ds->buf[ctx->ds->buf_offset + 2] & 1;
uint mode = ctx->ds->buf[ctx->ds->buf_offset + 3];
grend_render_condition(ctx->grctx, handle, condition, mode);
}
static void graw_decode_set_streamout_targets(struct grend_decode_ctx *ctx,
uint16_t length)
{
uint32_t handles[16];
uint32_t num_handles = length - 1;
uint32_t append_bitmask;
int i;
append_bitmask = ctx->ds->buf[ctx->ds->buf_offset + 1];
for (i = 0; i < num_handles; i++)
handles[i] = ctx->ds->buf[ctx->ds->buf_offset + 2 + i];
grend_set_streamout_targets(ctx->grctx, append_bitmask, num_handles, handles);
}
static void graw_decode_set_query_state(struct grend_decode_ctx *ctx)
{
boolean enabled;
enabled = ctx->ds->buf[ctx->ds->buf_offset + 1] & 0x1;
grend_set_query_state(ctx->grctx, enabled);
}
void graw_renderer_context_create_internal(uint32_t handle, uint32_t nlen,
const char *debug_name)
{
struct grend_decode_ctx *dctx;
if (handle > GRAW_MAX_CTX)
return;
dctx = malloc(sizeof(struct grend_decode_ctx));
if (!dctx)
return;
dctx->grctx = grend_create_context(handle, nlen, debug_name);
if (!dctx->grctx) {
free(dctx);
return;
}
dctx->ds = &dctx->ids;
dec_ctx[handle] = dctx;
}
void graw_renderer_context_create(uint32_t handle, uint32_t nlen, const char *debug_name)
{
if (handle > GRAW_MAX_CTX)
return;
/* context 0 is always available with no guarantees */
if (handle == 0)
return;
graw_renderer_context_create_internal(handle, nlen, debug_name);
}
void graw_renderer_context_destroy(uint32_t handle)
{
struct grend_decode_ctx *ctx;
bool ret;
if (handle > GRAW_MAX_CTX)
return;
ctx = dec_ctx[handle];
dec_ctx[handle] = NULL;
ret = grend_destroy_context(ctx->grctx);
free(ctx);
/* switch to ctx 0 */
if (ret)
grend_hw_switch_context(dec_ctx[0]->grctx, TRUE);
}
struct grend_context *vrend_lookup_renderer_ctx(uint32_t ctx_id)
{
if (ctx_id > GRAW_MAX_CTX)
return NULL;
if (dec_ctx[ctx_id] == NULL)
return NULL;
return dec_ctx[ctx_id]->grctx;
}
static void graw_decode_block(uint32_t ctx_id, uint32_t *block, int ndw)
{
int i = 0;
struct grend_decode_ctx *gdctx;
boolean ret;
if (ctx_id > GRAW_MAX_CTX)
return;
if (dec_ctx[ctx_id] == NULL)
return;
gdctx = dec_ctx[ctx_id];
ret = grend_hw_switch_context(gdctx->grctx, TRUE);
if (ret == FALSE)
return;
gdctx->ds->buf = block;
gdctx->ds->buf_total = ndw;
gdctx->ds->buf_offset = 0;
while (gdctx->ds->buf_offset < gdctx->ds->buf_total) {
uint32_t header = gdctx->ds->buf[gdctx->ds->buf_offset];
// fprintf(stderr,"[%d] cmd is %d (obj %d) len %d\n", gdctx->ds->buf_offset, header & 0xff, (header >> 8 & 0xff), (header >> 16));
switch (header & 0xff) {
case VIRGL_CCMD_CREATE_OBJECT:
graw_decode_create_object(gdctx);
break;
case VIRGL_CCMD_BIND_OBJECT:
graw_decode_bind_object(gdctx);
break;
case VIRGL_CCMD_DESTROY_OBJECT:
graw_decode_destroy_object(gdctx);
break;
case VIRGL_CCMD_CLEAR:
graw_decode_clear(gdctx);
break;
case VIRGL_CCMD_DRAW_VBO:
graw_decode_draw_vbo(gdctx);
break;
case VIRGL_CCMD_SET_FRAMEBUFFER_STATE:
graw_decode_set_framebuffer_state(gdctx);
break;
case VIRGL_CCMD_SET_VERTEX_BUFFERS:
graw_decode_set_vertex_buffers(gdctx, header >> 16);
break;
case VIRGL_CCMD_RESOURCE_INLINE_WRITE:
graw_decode_resource_inline_write(gdctx, header >> 16);
break;
case VIRGL_CCMD_SET_VIEWPORT_STATE:
graw_decode_set_viewport_state(gdctx);
break;
case VIRGL_CCMD_SET_SAMPLER_VIEWS:
graw_decode_set_sampler_views(gdctx, header >> 16);
break;
case VIRGL_CCMD_SET_INDEX_BUFFER:
graw_decode_set_index_buffer(gdctx);
break;
case VIRGL_CCMD_SET_CONSTANT_BUFFER:
graw_decode_set_constant_buffer(gdctx, header >> 16);
break;
case VIRGL_CCMD_SET_STENCIL_REF:
graw_decode_set_stencil_ref(gdctx);
break;
case VIRGL_CCMD_SET_BLEND_COLOR:
graw_decode_set_blend_color(gdctx);
break;
case VIRGL_CCMD_SET_SCISSOR_STATE:
graw_decode_set_scissor_state(gdctx);
break;
case VIRGL_CCMD_BLIT:
graw_decode_blit(gdctx);
break;
case VIRGL_CCMD_RESOURCE_COPY_REGION:
graw_decode_resource_copy_region(gdctx);
break;
case VIRGL_CCMD_BIND_SAMPLER_STATES:
graw_decode_bind_sampler_states(gdctx, header >> 16);
break;
case VIRGL_CCMD_BEGIN_QUERY:
graw_decode_begin_query(gdctx);
break;
case VIRGL_CCMD_END_QUERY:
graw_decode_end_query(gdctx);
break;
case VIRGL_CCMD_GET_QUERY_RESULT:
graw_decode_get_query_result(gdctx);
break;
case VIRGL_CCMD_SET_POLYGON_STIPPLE:
graw_decode_set_polygon_stipple(gdctx);
break;
case VIRGL_CCMD_SET_CLIP_STATE:
graw_decode_set_clip_state(gdctx);
break;
case VIRGL_CCMD_SET_SAMPLE_MASK:
graw_decode_set_sample_mask(gdctx);
break;
case VIRGL_CCMD_SET_STREAMOUT_TARGETS:
graw_decode_set_streamout_targets(gdctx, header >> 16);
break;
case VIRGL_CCMD_SET_QUERY_STATE:
graw_decode_set_query_state(gdctx);
break;
case VIRGL_CCMD_SET_RENDER_CONDITION:
graw_decode_set_render_condition(gdctx);
break;
}
gdctx->ds->buf_offset += (header >> 16) + 1;
}
}
void graw_decode_block_iov(struct virgl_iovec *iov, unsigned int niovs,
uint32_t ctx_id, uint64_t offset, int ndw)
{
uint32_t *block = (uint32_t *)(iov[0].iov_base + offset);
void *data;
if (niovs > 1) {
data = malloc(ndw * 4);
graw_iov_to_buf(iov, niovs, offset, data, ndw * 4);
}
else
data = (uint32_t *)(iov[0].iov_base + offset);
graw_decode_block(ctx_id, data, ndw);
if (niovs > 1)
free(data);
}

@ -1,13 +0,0 @@
#ifndef GRAW_DECODE_H
#define GRAW_DECODE_H
struct graw_decoder_state {
uint32_t *buf;
uint32_t buf_total;
uint32_t buf_offset;
};
void graw_decode_transfer(uint32_t *data, uint32_t ndw);
void graw_decode_get_transfer(uint32_t *data, uint32_t ndw);
#endif

@ -1,22 +0,0 @@
#ifndef GRAW_IOV_H
#define GRAW_IOV_H
/* stolen from qemu for now until later integration */
struct virgl_iovec {
void *iov_base;
size_t iov_len;
};
typedef void (*IOCallback)(void *cookie, unsigned int doff, void *src, int len);
size_t graw_iov_size(const struct virgl_iovec *iov, const unsigned int iov_cnt);
size_t graw_iov_from_buf(const struct virgl_iovec *iov, unsigned int iov_cnt,
size_t offset, const void *buf, size_t bytes);
size_t graw_iov_to_buf(const struct virgl_iovec *iov, const unsigned int iov_cnt,
size_t offset, void *buf, size_t bytes);
size_t graw_iov_to_buf_cb(const struct virgl_iovec *iov, const unsigned int iov_cnt,
size_t offset, size_t bytes, IOCallback iocb, void *cookie);
#endif

@ -1,322 +0,0 @@
#ifndef GRAW_RENDERER_H
#define GRAW_RENDERER_H
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "virgl_protocol.h"
#include "graw_iov.h"
#include "virgl_hw.h"
typedef void *virgl_gl_context;
typedef void *virgl_gl_drawable;
extern int vrend_dump_shaders;
struct grend_context;
struct grend_resource {
struct pipe_resource base;
GLuint id;
GLenum target;
/* fb id if we need to readback this resource */
GLuint readback_fb_id;
GLuint readback_fb_level;
GLuint readback_fb_z;
int is_front;
GLboolean renderer_flipped;
void *ptr;
GLuint handle;
struct virgl_iovec *iov;
uint32_t num_iovs;
boolean y_0_top;
boolean scannedout;
};
/* assume every format is sampler friendly */
#define VREND_BIND_RENDER (1 << 0)
#define VREND_BIND_DEPTHSTENCIL (1 << 1)
struct grend_format_table {
enum virgl_formats format;
GLenum internalformat;
GLenum glformat;
GLenum gltype;
uint32_t bindings;
};
struct grend_if_cbs {
void (*write_fence)(unsigned fence_id);
/* inform the control layer about a new scanout */
void (*scanout_rect_info)(int scanout_id, GLuint tex_id, int x, int y,
uint32_t width, uint32_t height);
void (*scanout_resource_info)(int scanout_id, GLuint tex_id, uint32_t flags,
uint32_t stride,
uint32_t width, uint32_t height, uint32_t format);
virgl_gl_context (*create_gl_context)(int scanout);
void (*destroy_gl_context)(virgl_gl_context ctx);
int (*make_current)(int scanout, virgl_gl_context ctx);
void (*flush_scanout)(int scanout, int x, int y, uint32_t width, uint32_t height);
void (*inval_backing)(struct virgl_iovec *iov, uint32_t iov_cnt);
};
void graw_renderer_init(struct grend_if_cbs *cbs);
void grend_insert_format(struct grend_format_table *entry, uint32_t bindings);
void grend_create_vs(struct grend_context *ctx,
uint32_t handle,
const struct pipe_shader_state *vs);
void grend_create_fs(struct grend_context *ctx,
uint32_t handle,
const struct pipe_shader_state *vs);
void grend_bind_vs(struct grend_context *ctx,
uint32_t handle);
void grend_bind_fs(struct grend_context *ctx,
uint32_t handle);
void grend_bind_vs_so(struct grend_context *ctx,
uint32_t handle);
void grend_clear(struct grend_context *ctx,
unsigned buffers,
const union pipe_color_union *color,
double depth, unsigned stencil);
void grend_draw_vbo(struct grend_context *ctx,
const struct pipe_draw_info *info);
void grend_set_framebuffer_state(struct grend_context *ctx,
uint32_t nr_cbufs, uint32_t surf_handle[8],
uint32_t zsurf_handle);
void grend_flush(struct grend_context *ctx);
void grend_flush_frontbuffer(uint32_t res_handle);
struct grend_context *grend_create_context(int id, uint32_t nlen, const char *debug_name);
bool grend_destroy_context(struct grend_context *ctx);
void graw_renderer_context_create(uint32_t handle, uint32_t nlen, const char *name);
void graw_renderer_context_create_internal(uint32_t handle, uint32_t nlen, const char *name);
void graw_renderer_context_destroy(uint32_t handle);
struct graw_renderer_resource_create_args {
uint32_t handle;
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 flags;
};
void graw_renderer_resource_create(struct graw_renderer_resource_create_args *args, struct virgl_iovec *iov, uint32_t num_iovs);
void graw_renderer_resource_unref(uint32_t handle);
void grend_create_surface(struct grend_context *ctx,
uint32_t handle,
uint32_t res_handle, uint32_t format,
uint32_t val0, uint32_t val1);
void grend_create_sampler_view(struct grend_context *ctx,
uint32_t handle,
uint32_t res_handle, uint32_t format,
uint32_t val0, uint32_t val1, uint32_t swizzle_packed);
void grend_create_so_target(struct grend_context *ctx,
uint32_t handle,
uint32_t res_handle,
uint32_t buffer_offset,
uint32_t buffer_size);
void grend_set_streamout_targets(struct grend_context *ctx,
uint32_t append_bitmask,
uint32_t num_targets,
uint32_t *handles);
void grend_create_vertex_elements_state(struct grend_context *ctx,
uint32_t handle,
unsigned num_elements,
const struct pipe_vertex_element *elements);
void grend_bind_vertex_elements_state(struct grend_context *ctx,
uint32_t handle);
void grend_set_single_vbo(struct grend_context *ctx,
int index,
uint32_t stride,
uint32_t buffer_offset,
uint32_t res_handle);
void grend_set_num_vbo(struct grend_context *ctx,
int num_vbo);
void grend_transfer_inline_write(struct grend_context *ctx,
uint32_t res_handle,
unsigned level,
unsigned usage,
const struct pipe_box *box,
const void *data,
unsigned stride,
unsigned layer_stride);
void grend_set_viewport_state(struct grend_context *ctx,
const struct pipe_viewport_state *state);
void grend_set_num_sampler_views(struct grend_context *ctx,
uint32_t shader_type,
uint32_t start_slot,
int num_sampler_views);
void grend_set_single_sampler_view(struct grend_context *ctx,
uint32_t shader_type,
int index,
uint32_t res_handle);
void grend_object_bind_blend(struct grend_context *ctx,
uint32_t handle);
void grend_object_bind_dsa(struct grend_context *ctx,
uint32_t handle);
void grend_object_bind_rasterizer(struct grend_context *ctx,
uint32_t handle);
void grend_bind_sampler_states(struct grend_context *ctx,
uint32_t shader_type,
uint32_t start_slot,
uint32_t num_states,
uint32_t *handles);
void grend_set_index_buffer(struct grend_context *ctx,
uint32_t res_handle,
uint32_t index_size,
uint32_t offset);
void graw_renderer_transfer_write_iov(uint32_t handle,
uint32_t ctx_id,
int level,
uint32_t stride,
uint32_t layer_stride,
struct pipe_box *box,
uint64_t offset,
struct virgl_iovec *iovec,
unsigned int iovec_cnt);
void graw_renderer_resource_copy_region(struct grend_context *ctx,
uint32_t dst_handle, uint32_t dst_level,
uint32_t dstx, uint32_t dsty, uint32_t dstz,
uint32_t src_handle, uint32_t src_level,
const struct pipe_box *src_box);
void graw_renderer_blit(struct grend_context *ctx,
uint32_t dst_handle, uint32_t src_handle,
const struct pipe_blit_info *info);
void graw_renderer_transfer_send_iov(uint32_t handle, uint32_t ctx_id,
uint32_t level, uint32_t stride,
uint32_t layer_stride,
struct pipe_box *box,
uint64_t offset, struct virgl_iovec *iov,
int iovec_cnt);
void grend_set_stencil_ref(struct grend_context *ctx, struct pipe_stencil_ref *ref);
void grend_set_blend_color(struct grend_context *ctx, struct pipe_blend_color *color);
void grend_set_scissor_state(struct grend_context *ctx, struct pipe_scissor_state *ss);
void grend_set_polygon_stipple(struct grend_context *ctx, struct pipe_poly_stipple *ps);
void grend_set_clip_state(struct grend_context *ctx, struct pipe_clip_state *ucp);
void grend_set_sample_mask(struct grend_context *ctx, unsigned sample_mask);
void grend_set_constants(struct grend_context *ctx,
uint32_t shader,
uint32_t index,
uint32_t num_constant,
float *data);
void graw_transfer_write_return(void *data, uint32_t bytes, uint64_t offset,
struct virgl_iovec *iov, int iovec_cnt);
void graw_transfer_write_tex_return(struct pipe_resource *res,
struct pipe_box *box,
uint32_t level,
uint32_t dst_stride,
uint64_t offset,
struct virgl_iovec *iov,
int num_iovs,
void *myptr, int size, int invert);
int graw_renderer_set_scanout(uint32_t res_handle,
uint32_t scanout_id,
uint32_t ctx_id,
struct pipe_box *box);
int graw_renderer_flush_buffer(uint32_t res_handle,
uint32_t ctx_id,
struct pipe_box *box);
void graw_renderer_fini(void);
void graw_reset_decode(void);
void graw_decode_block_iov(struct virgl_iovec *iov, uint32_t niovs, uint32_t ctx_id, uint64_t offset, int ndw);
struct grend_context *vrend_lookup_renderer_ctx(uint32_t ctx_id);
int graw_renderer_create_fence(int client_fence_id, uint32_t ctx_id);
void graw_renderer_check_fences(void);
void graw_renderer_check_queries(void);
void grend_stop_current_queries(void);
boolean grend_hw_switch_context(struct grend_context *ctx, boolean now);
void graw_renderer_object_insert(struct grend_context *ctx, void *data,
uint32_t size, uint32_t handle, enum virgl_object_type type);
void graw_renderer_object_destroy(struct grend_context *ctx, uint32_t handle);
void grend_create_query(struct grend_context *ctx, uint32_t handle,
uint32_t query_type, uint32_t res_handle,
uint32_t offset);
void grend_begin_query(struct grend_context *ctx, uint32_t handle);
void grend_end_query(struct grend_context *ctx, uint32_t handle);
void grend_get_query_result(struct grend_context *ctx, uint32_t handle,
uint32_t wait);
void grend_set_query_state(struct grend_context *ctx,
boolean enabled);
void grend_render_condition(struct grend_context *ctx,
uint32_t handle,
boolean condtion,
uint mode);
void grend_set_cursor_info(uint32_t cursor_handle, int x, int y);
void *graw_renderer_get_cursor_contents(uint32_t res_handle, uint32_t *width, uint32_t *height);
void grend_use_program(GLuint program_id);
void grend_blend_enable(GLboolean blend_enable);
void grend_depth_test_enable(GLboolean depth_test_enable);
void grend_bind_va(GLuint vaoid);
int graw_renderer_flush_buffer_res(struct grend_resource *res,
struct pipe_box *box);
void graw_renderer_fill_caps(uint32_t set, uint32_t version,
union virgl_caps *caps);
GLint64 graw_renderer_get_timestamp(void);
/* formats */
void vrend_build_format_list(void);
int graw_renderer_resource_attach_iov(int res_handle, struct virgl_iovec *iov,
int num_iovs);
void graw_renderer_resource_invalid_iov(int res_handle);
void graw_renderer_resource_destroy(struct grend_resource *res);
static INLINE void
grend_resource_reference(struct grend_resource **ptr, struct grend_resource *tex)
{
struct grend_resource *old_tex = *ptr;
if (pipe_reference(&(*ptr)->base.reference, &tex->base.reference))
graw_renderer_resource_destroy(old_tex);
*ptr = tex;
}
void graw_renderer_force_ctx_0(void);
void graw_renderer_get_rect(int idx, struct virgl_iovec *iov, unsigned int num_iovs,
uint32_t offset, int x, int y, int width, int height);
#endif

@ -1,40 +0,0 @@
#ifndef GRAW_SHADER_H
#define GRAW_SHADER_H
#include "pipe/p_state.h"
#define SHADER_FLAG_FS_INVERT 1
/* need to store patching info for interpolation */
struct vrend_interp_info {
int semantic_name;
int semantic_index;
int interpolate;
};
struct vrend_shader_info {
uint32_t samplers_used_mask;
int num_consts;
int num_inputs;
int num_interps;
int num_outputs;
uint32_t shadow_samp_mask;
struct pipe_stream_output_info so_info;
struct vrend_interp_info *interpinfo;
};
struct vrend_shader_key {
uint32_t coord_replace;
boolean invert_fs_origin;
};
boolean vrend_patch_vertex_shader_interpolants(char *program,
struct vrend_shader_info *vs_info,
struct vrend_shader_info *fs_info);
char *tgsi_convert(const struct tgsi_token *tokens,
struct vrend_shader_key *key,
struct vrend_shader_info *sinfo);
#endif

@ -1,426 +0,0 @@
#include <stdio.h>
#include <time.h>
#include <epoxy/gl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/eventfd.h>
#include "virtgpu_hw.h"
#include "pipe/p_state.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "graw_renderer.h"
#include "virglrenderer.h"
#include "virgl_egl.h"
static struct virgl_renderer_callbacks *rcbs;
static void *dev_cookie;
extern int localrender;
static int use_egl_context;
struct virgl_egl *egl_info;
static struct grend_if_cbs virgl_cbs;
static int graw_process_cmd(struct virtgpu_command *cmd, struct virgl_iovec *iov,
unsigned int niovs);
int virgl_renderer_process_vcmd(void *cmd, struct virgl_iovec *iov, unsigned int niovs)
{
struct virtgpu_command *qcmd = cmd;
int ret;
ret = graw_process_cmd(qcmd, iov, niovs);
graw_renderer_check_fences();
return ret;
}
static void virgl_cmd_create_resource_2d(struct virtgpu_command *cmd)
{
struct graw_renderer_resource_create_args args;
args.handle = cmd->u.resource_create_2d.resource_id;
args.target = 2;
args.format = cmd->u.resource_create_2d.format;
args.bind = (1 << 1);
args.width = cmd->u.resource_create_2d.width;
args.height = cmd->u.resource_create_2d.height;
args.depth = 1;
args.array_size = 1;
args.last_level = 0;
args.nr_samples = 0;
args.flags = VIRGL_RESOURCE_Y_0_TOP;
graw_renderer_resource_create(&args, NULL, 0);
}
static void virgl_cmd_create_resource_3d(struct virtgpu_command *cmd)
{
struct graw_renderer_resource_create_args args;
args.handle = cmd->u.resource_create_3d.resource_id;
args.target = cmd->u.resource_create_3d.target;
args.format = cmd->u.resource_create_3d.format;
args.bind = cmd->u.resource_create_3d.bind;
args.width = cmd->u.resource_create_3d.width;
args.height = cmd->u.resource_create_3d.height;
args.depth = cmd->u.resource_create_3d.depth;
args.array_size = cmd->u.resource_create_3d.array_size;
args.last_level = cmd->u.resource_create_3d.last_level;
args.nr_samples = cmd->u.resource_create_3d.nr_samples;
args.flags = cmd->u.resource_create_3d.flags;
graw_renderer_resource_create(&args, NULL, 0);
}
static void virgl_resource_attach_backing(struct virtgpu_resource_attach_backing *att_rb,
struct iovec *iov,
unsigned int iov_cnt)
{
uint32_t gsize = graw_iov_size(iov, iov_cnt);
struct virgl_iovec *res_iovs;
int i;
void *data;
int ret;
res_iovs = malloc(att_rb->nr_entries * sizeof(struct virgl_iovec));
if (!res_iovs)
return;
if (iov_cnt > 1) {
data = malloc(gsize);
graw_iov_to_buf(iov, iov_cnt, 0, data, gsize);
} else
data = iov[0].iov_base;
for (i = 0; i < att_rb->nr_entries; i++) {
struct virtgpu_mem_entry *ent = ((struct virtgpu_mem_entry *)data) + i;
res_iovs[i].iov_len = ent->length;
ret = rcbs->map_iov(&res_iovs[i], ent->addr);
if (ret) {
fprintf(stderr, "failed to attach backing %d\n", att_rb->resource_id);
free(res_iovs);
res_iovs = NULL;
goto fail_free;
}
}
ret = graw_renderer_resource_attach_iov(att_rb->resource_id, res_iovs,
att_rb->nr_entries);
goto out;
fail_free:
free(res_iovs);
out:
if (iov_cnt > 1)
free(data);
}
static void virgl_resource_inval_backing_iov(struct virgl_iovec *iov, uint32_t iov_cnt)
{
int i;
for (i = 0; i < iov_cnt; i++) {
rcbs->unmap_iov(&iov[i]);
}
free(iov);
}
static void virgl_resource_inval_backing(int resource_id)
{
graw_renderer_resource_invalid_iov(resource_id);
}
static int graw_process_cmd(struct virtgpu_command *cmd, struct virgl_iovec *iov,
unsigned int niovs)
{
static int inited;
int fence_ctx_id = 0;
graw_renderer_force_ctx_0();
switch (cmd->type) {
case VIRTGPU_CMD_CTX_CREATE:
graw_renderer_context_create(cmd->u.ctx_create.ctx_id, cmd->u.ctx_create.nlen,
cmd->u.ctx_create.debug_name);
break;
case VIRTGPU_CMD_CTX_DESTROY:
graw_renderer_context_destroy(cmd->u.ctx_destroy.ctx_id);
break;
case VIRTGPU_CMD_RESOURCE_CREATE_2D:
virgl_cmd_create_resource_2d(cmd);
break;
case VIRTGPU_CMD_RESOURCE_CREATE_3D:
virgl_cmd_create_resource_3d(cmd);
break;
case VIRTGPU_CMD_SUBMIT_3D:
// fprintf(stderr,"cmd submit %lx %d\n", cmd->u.cmd_submit.data, cmd->u.cmd_submit.size);
{
graw_decode_block_iov(iov, niovs, cmd->u.cmd_submit.ctx_id, cmd->u.cmd_submit.phy_addr, cmd->u.cmd_submit.size / 4);
fence_ctx_id = cmd->u.cmd_submit.ctx_id;
}
break;
case VIRTGPU_CMD_TRANSFER_TO_HOST_2D: {
struct pipe_box box;
box.x = cmd->u.transfer_to_host_2d.x;
box.y = cmd->u.transfer_to_host_2d.y;
box.z = 0;
box.width = cmd->u.transfer_to_host_2d.width;
box.height = cmd->u.transfer_to_host_2d.height;
box.depth = 1;
// fprintf(stderr,"got transfer get %d\n", cmd->u.transfer_to_host_3d.res_handle);
graw_renderer_transfer_write_iov(cmd->u.transfer_to_host_2d.resource_id,
0,
0,
0,
0,
(struct pipe_box *)&box,
cmd->u.transfer_to_host_2d.offset, NULL, 0);
break;
}
case VIRTGPU_CMD_TRANSFER_TO_HOST_3D:
// fprintf(stderr,"got transfer get %d\n", cmd->u.transfer_to_host_3d.res_handle);
graw_renderer_transfer_write_iov(cmd->u.transfer_to_host_3d.resource_id,
cmd->u.transfer_to_host_3d.ctx_id,
cmd->u.transfer_to_host_3d.level,
cmd->u.transfer_to_host_3d.stride,
cmd->u.transfer_to_host_3d.layer_stride,
(struct pipe_box *)&cmd->u.transfer_to_host_3d.box,
cmd->u.transfer_to_host_3d.data, NULL, 0);
fence_ctx_id = cmd->u.transfer_to_host_3d.ctx_id;
break;
case VIRTGPU_CMD_TRANSFER_FROM_HOST_3D:
graw_renderer_transfer_send_iov(cmd->u.transfer_from_host_3d.resource_id,
cmd->u.transfer_from_host_3d.ctx_id,
cmd->u.transfer_from_host_3d.level,
cmd->u.transfer_from_host_3d.stride,
cmd->u.transfer_from_host_3d.layer_stride,
(struct pipe_box *)&cmd->u.transfer_from_host_3d.box,
cmd->u.transfer_from_host_3d.data, NULL, 0);
fence_ctx_id = cmd->u.transfer_from_host_3d.ctx_id;
break;
case VIRTGPU_CMD_RESOURCE_ATTACH_BACKING:
virgl_resource_attach_backing(&cmd->u.resource_attach_backing, iov, niovs);
break;
case VIRTGPU_CMD_RESOURCE_INVAL_BACKING:
virgl_resource_inval_backing(cmd->u.resource_inval_backing.resource_id);
break;
case VIRTGPU_CMD_SET_SCANOUT: {
struct pipe_box box;
box.x = cmd->u.set_scanout.x;
box.y = cmd->u.set_scanout.y;
box.z = 0;
box.width = cmd->u.set_scanout.width;
box.height = cmd->u.set_scanout.height;
box.depth = 1;
graw_renderer_set_scanout(cmd->u.set_scanout.resource_id, cmd->u.set_scanout.scanout_id,
0, &box);
break;
}
case VIRTGPU_CMD_RESOURCE_FLUSH:
{
struct pipe_box box;
box.x = cmd->u.resource_flush.x;
box.y = cmd->u.resource_flush.y;
box.z = 0;
box.width = cmd->u.resource_flush.width;
box.height = cmd->u.resource_flush.height;
box.depth = 1;
graw_renderer_flush_buffer(cmd->u.resource_flush.resource_id,
0, &box);
break;
}
case VIRTGPU_CMD_RESOURCE_UNREF:
graw_renderer_resource_unref(cmd->u.resource_unref.resource_id);
break;
case VIRTGPU_CMD_CTX_ATTACH_RESOURCE:
/* TODO add security */
break;
case VIRTGPU_CMD_CTX_DETACH_RESOURCE:
/* TODO add security */
break;
case VIRTGPU_CMD_GET_CAPS:
if (!niovs)
return 0;
{
struct virtgpu_response resp;
graw_renderer_fill_caps(cmd->u.get_cap.cap_set,
cmd->u.get_cap.cap_set_version,
(union virgl_caps *)&resp.u.caps);
resp.flags = 0;
resp.type = VIRTGPU_CMD_GET_CAPS;
graw_iov_from_buf(iov, niovs, 0, &resp, sizeof(struct virtgpu_response));
}
break;
case VIRTGPU_CMD_GET_DISPLAY_INFO:
return -1;
case 0xdeadbeef:
if (inited) {
graw_renderer_fini();
}
graw_renderer_init(&virgl_cbs);
inited = 1;
break;
}
if (cmd->flags & VIRGL_COMMAND_EMIT_FENCE)
graw_renderer_create_fence(cmd->fence_id, fence_ctx_id);
return 0;
}
void graw_transfer_write_return(void *data, uint32_t bytes, uint64_t offset,
struct virgl_iovec *iov, int num_iovs)
{
graw_iov_from_buf(iov, num_iovs, offset, data, bytes);
}
void graw_transfer_write_tex_return(struct pipe_resource *res,
struct pipe_box *box,
uint32_t level,
uint32_t dst_stride,
uint64_t offset,
struct virgl_iovec *iov,
int num_iovs,
void *myptr, int size, int invert)
{
int elsize = util_format_get_blocksize(res->format);
int h;
uint32_t myoffset = offset;
uint32_t stride = dst_stride ? dst_stride : util_format_get_nblocksx(res->format, u_minify(res->width0, level)) * elsize;
// uint32_t stride = dst_stride ? dst_stride : util_format_get_nblocksx(res->format, box->width) * elsize;
if (!invert && (stride == util_format_get_nblocksx(res->format, box->width) * elsize))
graw_iov_from_buf(iov, num_iovs, offset, myptr, size);
else if (invert) {
for (h = box->height - 1; h >= 0; h--) {
void *sptr = myptr + (h * elsize * box->width);
graw_iov_from_buf(iov, num_iovs, myoffset, sptr, box->width * elsize);
myoffset += stride;
}
} else {
for (h = 0; h < box->height; h++) {
void *sptr = myptr + (h * elsize * box->width);
graw_iov_from_buf(iov, num_iovs, myoffset, sptr, box->width * elsize);
myoffset += stride;
}
}
}
static void virgl_write_fence(uint32_t fence_id)
{
rcbs->write_fence(dev_cookie, fence_id);
}
static virgl_gl_context create_gl_context(int scanout_idx)
{
if (use_egl_context)
return virgl_egl_create_context(egl_info);
return rcbs->create_gl_context(dev_cookie, scanout_idx);
}
static void destroy_gl_context(virgl_gl_context ctx)
{
if (use_egl_context)
return virgl_egl_destroy_context(egl_info, ctx);
return rcbs->destroy_gl_context(dev_cookie, ctx);
}
static int make_current(int scanout_idx, virgl_gl_context ctx)
{
if (use_egl_context)
return virgl_egl_make_context_current(egl_info, ctx);
return rcbs->make_current(dev_cookie, scanout_idx, ctx);
}
static void flush_scanout(int scanout_id, int x, int y, uint32_t width, uint32_t height)
{
if (rcbs->rect_update)
rcbs->rect_update(dev_cookie, scanout_id, x, y, width, height);
}
static void scanout_rect_info(int scanout_id, GLuint tex_id,
int x, int y, uint32_t width,
uint32_t height)
{
if (rcbs->scanout_rect_info)
rcbs->scanout_rect_info(dev_cookie, scanout_id, tex_id,
x, y, width, height);
}
static void scanout_resource_info(int scanout_id, GLuint tex_id, uint32_t flags,
uint32_t stride, uint32_t width,
uint32_t height, uint32_t format)
{
if (rcbs->scanout_resource_info)
rcbs->scanout_resource_info(dev_cookie, scanout_id, tex_id, flags,
stride, width, height, virgl_egl_get_gbm_format(format));
}
static struct grend_if_cbs virgl_cbs = {
virgl_write_fence,
scanout_rect_info,
scanout_resource_info,
create_gl_context,
destroy_gl_context,
make_current,
flush_scanout,
virgl_resource_inval_backing_iov,
};
void *virgl_get_cursor_data(uint32_t resource_id, uint32_t *width, uint32_t *height)
{
return graw_renderer_get_cursor_contents(resource_id, width, height);
}
void virgl_renderer_set_cursor_info(uint32_t cursor_handle, int x, int y)
{
grend_set_cursor_info(cursor_handle, x, y);
}
void virgl_renderer_poll(void)
{
graw_renderer_check_queries();
graw_renderer_check_fences();
}
void virgl_renderer_get_rect(int idx, struct virgl_iovec *iov, unsigned int num_iovs,
uint32_t offset, int x, int y, int width, int height)
{
graw_renderer_get_rect(idx, iov, num_iovs, offset, x, y, width, height);
}
int virgl_renderer_init(void *cookie, int flags, struct virgl_renderer_callbacks *cbs)
{
dev_cookie = cookie;
rcbs = cbs;
localrender = 1;
fprintf(stderr,"initied renderer %d\n", flags);
if (flags & VIRGL_RENDERER_USE_EGL) {
egl_info = virgl_egl_init();
if (!egl_info)
return -1;
use_egl_context = 1;
}
if (cbs->version != 1)
return -1;
graw_renderer_init(&virgl_cbs);
return 0;
}
int virgl_renderer_get_fd_for_texture(uint32_t tex_id, int *fd)
{
return virgl_egl_get_fd_for_texture(egl_info, tex_id, fd);
}

@ -1,256 +1,142 @@
/*
* Helpers for getting linearized buffers from iov / filling buffers into iovs
*
* Copyright IBM, Corp. 2007, 2008
* Copyright (C) 2010 Red Hat, Inc.
*
* Author(s):
* Anthony Liguori <aliguori@us.ibm.com>
* Amit Shah <amit.shah@redhat.com>
* Michael Tokarev <mjt@tls.msk.ru>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
*
* Contributions after 2012-01-13 are licensed under the terms of the
* GNU GPL, version 2 or (at your option) any later version.
* this code is taken from Michael - the qemu code is GPLv2 so I don't want
* to reuse it.
* I've adapted it to handle offsets and callback
*/
#include <string.h>
#include <assert.h>
#include <sys/types.h>
//
// iovec.c
//
// Scatter/gather utility routines
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of the project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include <assert.h>
#include <string.h>
#include "vrend_iov.h"
#include "graw_iov.h"
#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
size_t vrend_get_iovec_size(const struct iovec *iov, int iovlen) {
size_t size = 0;
while (iovlen > 0) {
size += iov->iov_len;
iov++;
iovlen--;
}
size_t graw_iov_from_buf(const struct virgl_iovec *iov, unsigned int iov_cnt,
size_t offset, const void *buf, size_t bytes)
{
size_t done;
unsigned int i;
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) {
if (offset < iov[i].iov_len) {
size_t len = MIN(iov[i].iov_len - offset, bytes - done);
memcpy(iov[i].iov_base + offset, buf + done, len);
done += len;
offset = 0;
} else {
offset -= iov[i].iov_len;
}
}
assert(offset == 0);
return done;
return size;
}
size_t graw_iov_to_buf(const struct virgl_iovec *iov, const unsigned int iov_cnt,
size_t offset, void *buf, size_t bytes)
size_t vrend_read_from_iovec(const struct iovec *iov, int iovlen,
size_t offset,
char *buf, size_t count)
{
size_t done;
unsigned int i;
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) {
if (offset < iov[i].iov_len) {
size_t len = MIN(iov[i].iov_len - offset, bytes - done);
memcpy(buf + done, iov[i].iov_base + offset, len);
done += len;
offset = 0;
} else {
offset -= iov[i].iov_len;
}
size_t read = 0;
size_t len;
while (count > 0 && iovlen > 0) {
if (iov->iov_len > offset) {
len = iov->iov_len - offset;
if (count < iov->iov_len - offset) len = count;
memcpy(buf, iov->iov_base + offset, len);
read += len;
buf += len;
count -= len;
offset = 0;
} else {
offset -= iov->iov_len;
}
assert(offset == 0);
return done;
}
size_t graw_iov_to_buf_cb(const struct virgl_iovec *iov, const unsigned int iov_cnt,
size_t offset, size_t bytes, IOCallback iovcb,
void *cookie)
{
size_t done;
unsigned int i;
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) {
if (offset < iov[i].iov_len) {
size_t len = MIN(iov[i].iov_len - offset, bytes - done);
(*iovcb)(cookie, done, iov[i].iov_base + offset, len);
done += len;
offset = 0;
} else {
offset -= iov[i].iov_len;
}
}
iov++;
iovlen--;
}
assert(offset == 0);
return done;
return read;
}
#if 0
size_t iov_memset(const struct virgl_iovec *iov, const unsigned int iov_cnt,
size_t offset, int fillc, size_t bytes)
{
size_t done;
unsigned int i;
for (i = 0, done = 0; (offset || done < bytes) && i < iov_cnt; i++) {
if (offset < iov[i].iov_len) {
size_t len = MIN(iov[i].iov_len - offset, bytes - done);
memset(iov[i].iov_base + offset, fillc, len);
done += len;
offset = 0;
} else {
offset -= iov[i].iov_len;
}
}
assert(offset == 0);
return done;
}
#endif
size_t graw_iov_size(const struct virgl_iovec *iov, const unsigned int iov_cnt)
size_t vrend_write_to_iovec(const struct iovec *iov, int iovlen,
size_t offset, const char *buf, size_t count)
{
size_t len;
unsigned int i;
size_t written = 0;
size_t len;
len = 0;
for (i = 0; i < iov_cnt; i++) {
len += iov[i].iov_len;
}
return len;
}
while (count > 0 && iovlen > 0) {
if (iov->iov_len > offset) {
len = iov->iov_len - offset;
#if 0
/* helper function for iov_send_recv() */
static ssize_t
do_send_recv(int sockfd, struct virgl_iovec *iov, unsigned iov_cnt, bool do_send)
{
#if defined CONFIG_IOVEC && defined CONFIG_POSIX
ssize_t ret;
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = iov;
msg.msg_iovlen = iov_cnt;
do {
ret = do_send
? sendmsg(sockfd, &msg, 0)
: recvmsg(sockfd, &msg, 0);
} while (ret < 0 && errno == EINTR);
return ret;
#else
/* else send piece-by-piece */
/*XXX Note: windows has WSASend() and WSARecv() */
unsigned i = 0;
ssize_t ret = 0;
while (i < iov_cnt) {
ssize_t r = do_send
? send(sockfd, iov[i].iov_base, iov[i].iov_len, 0)
: recv(sockfd, iov[i].iov_base, iov[i].iov_len, 0);
if (r > 0) {
ret += r;
} else if (!r) {
break;
} else if (errno == EINTR) {
continue;
} else {
/* else it is some "other" error,
* only return if there was no data processed. */
if (ret == 0) {
ret = -1;
}
break;
}
i++;
}
return ret;
#endif
}
ssize_t iov_send_recv(int sockfd, struct virgl_iovec *iov, unsigned iov_cnt,
size_t offset, size_t bytes,
bool do_send)
{
ssize_t ret;
unsigned si, ei; /* start and end indexes */
if (bytes == 0) {
/* Catch the do-nothing case early, as otherwise we will pass an
* empty virgl_iovec to sendmsg/recvmsg(), and not all implementations
* accept this.
*/
return 0;
}
/* Find the start position, skipping `offset' bytes:
* first, skip all full-sized vector elements, */
for (si = 0; si < iov_cnt && offset >= iov[si].iov_len; ++si) {
offset -= iov[si].iov_len;
}
if (offset) {
assert(si < iov_cnt);
/* second, skip `offset' bytes from the (now) first element,
* undo it on exit */
iov[si].iov_base += offset;
iov[si].iov_len -= offset;
}
/* Find the end position skipping `bytes' bytes: */
/* first, skip all full-sized elements */
for (ei = si; ei < iov_cnt && iov[ei].iov_len <= bytes; ++ei) {
bytes -= iov[ei].iov_len;
}
if (bytes) {
/* second, fixup the last element, and remember
* the length we've cut from the end of it in `bytes' */
size_t tail;
assert(ei < iov_cnt);
assert(iov[ei].iov_len > bytes);
tail = iov[ei].iov_len - bytes;
iov[ei].iov_len = bytes;
bytes = tail; /* bytes is now equal to the tail size */
++ei;
}
if (count < iov->iov_len - offset) len = count;
ret = do_send_recv(sockfd, iov + si, ei - si, do_send);
memcpy(iov->iov_base + offset, buf, len);
written += len;
/* Undo the changes above */
if (offset) {
iov[si].iov_base -= offset;
iov[si].iov_len += offset;
offset = 0;
buf += len;
count -= len;
} else {
offset -= iov->iov_len;
}
if (bytes) {
iov[ei-1].iov_len += bytes;
}
return ret;
iov++;
iovlen--;
}
assert(offset == 0);
return written;
}
void iov_hexdump(const struct virgl_iovec *iov, const unsigned int iov_cnt,
FILE *fp, const char *prefix, size_t limit)
size_t vrend_read_from_iovec_cb(const struct iovec *iov, int iovlen,
size_t offset, size_t count,
iov_cb iocb, void *cookie)
{
unsigned int i, v, b;
uint8_t *c;
c = iov[0].iov_base;
for (i = 0, v = 0, b = 0; b < limit; i++, b++) {
if (i == iov[v].iov_len) {
i = 0; v++;
if (v == iov_cnt) {
break;
}
c = iov[v].iov_base;
}
if ((b % 16) == 0) {
fprintf(fp, "%s: %04x:", prefix, b);
}
if ((b % 4) == 0) {
fprintf(fp, " ");
}
fprintf(fp, " %02x", c[i]);
if ((b % 16) == 15) {
fprintf(fp, "\n");
}
}
if ((b % 16) != 0) {
fprintf(fp, "\n");
size_t read = 0;
size_t len;
while (count > 0 && iovlen > 0) {
if (iov->iov_len > offset) {
len = iov->iov_len;
if (count < iov->iov_len - offset) len = count;
(*iocb)(cookie, count, iov->iov_base + offset, len);
read += len;
count -= len;
offset = 0;
} else {
offset -= iov->iov_len;
}
iov++;
iovlen--;
}
assert(offset == 0);
return read;
}
#endif

@ -1,15 +1,39 @@
/**************************************************************************
*
* Copyright (C) 2014 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 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.
*
**************************************************************************/
#ifndef VIRGL_EGL_H
#define VIRGL_EGL_H
#include "vrend_renderer.h"
struct virgl_egl;
struct virgl_egl *virgl_egl_init(void);
void virgl_egl_destroy(struct virgl_egl *ve);
virgl_gl_context virgl_egl_create_context(struct virgl_egl *ve);
void virgl_egl_destroy_context(struct virgl_egl *ve, virgl_gl_context virglctx);
int virgl_egl_make_context_current(struct virgl_egl *ve, virgl_gl_context virglctx);
virgl_gl_context virgl_egl_get_current_context(struct virgl_egl *ve);
virgl_renderer_gl_context virgl_egl_create_context(struct virgl_egl *ve, struct virgl_gl_ctx_param *vparams);
void virgl_egl_destroy_context(struct virgl_egl *ve, virgl_renderer_gl_context virglctx);
int virgl_egl_make_context_current(struct virgl_egl *ve, virgl_renderer_gl_context virglctx);
virgl_renderer_gl_context virgl_egl_get_current_context(struct virgl_egl *ve);
int virgl_egl_get_fd_for_texture(struct virgl_egl *ve, uint32_t tex_id, int *fd);
uint32_t virgl_egl_get_gbm_format(uint32_t format);

@ -1,12 +1,32 @@
/**************************************************************************
*
* Copyright (C) 2014 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 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.
*
**************************************************************************/
/* create our own EGL offscreen rendering context via gbm and rendernodes */
/* if we are using EGL and rendernodes then we talk via file descriptors to the remote
node */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define EGL_EGLEXT_PROTOTYPES
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
@ -55,7 +75,6 @@ static int egl_rendernode_open(void)
r = open(p, O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK);
if (r < 0){
fprintf(stderr, "failed to open render node %s\n", p);
free(p);
continue;
}
@ -120,7 +139,6 @@ struct virgl_egl *virgl_egl_init(void)
const char *extension_list;
struct virgl_egl *d;
fprintf(stderr,"egl init\n");
d = malloc(sizeof(struct virgl_egl));
if (!d)
return NULL;
@ -150,8 +168,8 @@ fprintf(stderr,"egl init\n");
if (!virgl_egl_has_extension_in_string(extension_list, "EGL_KHR_surfaceless_context"))
goto fail;
d->have_mesa_drm_image = false;
d->have_mesa_dma_buf_img_export = false;
d->have_mesa_drm_image = false;
d->have_mesa_dma_buf_img_export = false;
if (virgl_egl_has_extension_in_string(extension_list, "EGL_MESA_drm_image"))
d->have_mesa_drm_image = true;
@ -186,8 +204,6 @@ d->have_mesa_dma_buf_img_export = false;
d->egl_ctx);
return d;
fail:
fprintf(stderr,"fail\n");
free(d);
return NULL;
}
@ -203,27 +219,28 @@ void virgl_egl_destroy(struct virgl_egl *d)
free(d);
}
virgl_gl_context virgl_egl_create_context(struct virgl_egl *ve)
virgl_renderer_gl_context virgl_egl_create_context(struct virgl_egl *ve, struct virgl_gl_ctx_param *vparams)
{
EGLContext eglctx;
static const EGLint ctx_att[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGLint ctx_att[] = {
EGL_CONTEXT_CLIENT_VERSION, vparams->major_ver,
EGL_CONTEXT_MINOR_VERSION_KHR, vparams->minor_ver,
EGL_NONE
};
eglctx = eglCreateContext(ve->egl_display,
ve->egl_conf,
ve->egl_ctx,
vparams->shared ? eglGetCurrentContext() : EGL_NO_CONTEXT,
ctx_att);
return (virgl_gl_context)eglctx;
return (virgl_renderer_gl_context)eglctx;
}
void virgl_egl_destroy_context(struct virgl_egl *ve, virgl_gl_context virglctx)
void virgl_egl_destroy_context(struct virgl_egl *ve, virgl_renderer_gl_context virglctx)
{
EGLContext eglctx = (EGLContext)virglctx;
eglDestroyContext(ve->egl_display, eglctx);
}
int virgl_egl_make_context_current(struct virgl_egl *ve, virgl_gl_context virglctx)
int virgl_egl_make_context_current(struct virgl_egl *ve, virgl_renderer_gl_context virglctx)
{
EGLContext eglctx = (EGLContext)virglctx;
@ -231,10 +248,10 @@ int virgl_egl_make_context_current(struct virgl_egl *ve, virgl_gl_context virglc
eglctx);
}
virgl_gl_context virgl_egl_get_current_context(struct virgl_egl *ve)
virgl_renderer_gl_context virgl_egl_get_current_context(struct virgl_egl *ve)
{
EGLContext eglctx = eglGetCurrentContext();
return (virgl_gl_context)eglctx;
return (virgl_renderer_gl_context)eglctx;
}
int virgl_egl_get_fd_for_texture(struct virgl_egl *ve, uint32_t tex_id, int *fd)
@ -243,7 +260,7 @@ int virgl_egl_get_fd_for_texture(struct virgl_egl *ve, uint32_t tex_id, int *fd)
EGLint stride;
EGLBoolean b;
image = eglCreateImageKHR(ve->egl_display, ve->egl_ctx, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(unsigned long)tex_id, NULL);
image = eglCreateImageKHR(ve->egl_display, eglGetCurrentContext(), EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(unsigned long)tex_id, NULL);
if (!image)
return -1;

@ -1,3 +1,26 @@
/**************************************************************************
*
* Copyright (C) 2014 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 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.
*
**************************************************************************/
#ifndef VIRGL_HELPER_H
#define VIRGL_HELPER_H

@ -1,163 +1,11 @@
#ifndef VIRGL_HW_H
#define VIRGL_HW_H
typedef uint64_t VIRGLPHYSICAL;
/* specification for the HW command processor */
struct virgl_box {
uint32_t x, y, z;
uint32_t w, h, d;
};
enum virgl_cmd_type {
VIRGL_CMD_NOP,
VIRGL_CMD_CREATE_CONTEXT,
VIRGL_CMD_CREATE_RESOURCE,
VIRGL_CMD_SUBMIT,
VIRGL_CMD_DESTROY_CONTEXT,
VIRGL_CMD_TRANSFER_GET,
VIRGL_CMD_TRANSFER_PUT,
VIRGL_CMD_SET_SCANOUT,
VIRGL_CMD_FLUSH_BUFFER,
VIRGL_CMD_RESOURCE_UNREF,
VIRGL_CMD_ATTACH_RES_CTX,
VIRGL_CMD_DETACH_RES_CTX,
VIRGL_CMD_RESOURCE_ATTACH_SG_LIST,
VIRGL_CMD_RESOURCE_INVALIDATE_SG_LIST,
VIRGL_CMD_GET_3D_CAPABILITIES,
VIRGL_CMD_TIMESTAMP_GET,
};
/* put a box of data from a BO into a tex/buffer resource */
struct virgl_transfer_put {
VIRGLPHYSICAL data;
uint32_t res_handle;
struct virgl_box box;
uint32_t level;
uint32_t stride;
uint32_t layer_stride;
uint32_t ctx_id;
};
struct virgl_transfer_get {
VIRGLPHYSICAL data;
uint32_t res_handle;
struct virgl_box box;
int level;
uint32_t stride;
uint32_t layer_stride;
uint32_t ctx_id;
};
struct virgl_flush_buffer {
uint32_t res_handle;
uint32_t ctx_id;
struct virgl_box box;
};
struct virgl_set_scanout {
uint32_t res_handle;
uint32_t ctx_id;
struct virgl_box box;
};
/* is 0,0 for this resource at the top or the bottom?
kernel console and X want this, 3D driver doesn't.
this flag should only be used with formats that are
renderable. otherwise the context will get locked up.
*/
#define VIRGL_RESOURCE_Y_0_TOP (1 << 0)
struct virgl_resource_create {
uint32_t handle;
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 nr_sg_entries;
uint32_t flags;
};
struct virgl_resource_unref {
uint32_t res_handle;
};
struct virgl_cmd_submit {
uint64_t phy_addr;
uint32_t size;
uint32_t ctx_id;
};
struct virgl_cmd_context {
uint32_t handle;
uint32_t pad;
};
struct virgl_cmd_context_create {
uint32_t handle;
uint32_t nlen;
char debug_name[64];
};
struct virgl_cmd_resource_context {
uint32_t resource;
uint32_t ctx_id;
};
struct virgl_cmd_resource_attach_sg {
uint32_t resource;
uint32_t num_sg_entries;
};
struct virgl_cmd_resource_invalidate_sg {
uint32_t resource;
};
struct virgl_cmd_get_cap {
uint32_t cap_set;
uint32_t cap_set_version;
VIRGLPHYSICAL offset;
};
struct virgl_iov_entry {
VIRGLPHYSICAL addr;
uint32_t length;
uint32_t pad;
};
struct virgl_cmd_timestamp_get {
uint64_t timestamp;
};
#define VIRGL_COMMAND_EMIT_FENCE (1 << 0)
struct virgl_command {
uint32_t type;
uint32_t flags;
uint64_t fence_id;
union virgl_cmds {
struct virgl_cmd_context ctx;
struct virgl_cmd_context_create ctx_create;
struct virgl_resource_create res_create;
struct virgl_transfer_put transfer_put;
struct virgl_transfer_get transfer_get;
struct virgl_cmd_submit cmd_submit;
struct virgl_set_scanout set_scanout;
struct virgl_flush_buffer flush_buffer;
struct virgl_resource_unref res_unref;
struct virgl_cmd_resource_context res_ctx;
struct virgl_cmd_resource_attach_sg attach_sg;
struct virgl_cmd_resource_invalidate_sg inval_sg;
struct virgl_cmd_get_cap get_cap;
struct virgl_cmd_timestamp_get get_timestamp;
} u;
};
/* formats known by the HW device - based on gallium subset */
enum virgl_formats {
VIRGL_FORMAT_B8G8R8A8_UNORM = 1,
@ -341,9 +189,14 @@ struct virgl_caps_bool_set1 {
unsigned occlusion_query:1;
unsigned timer_query:1;
unsigned streamout_pause_resume:1;
unsigned texture_buffer_object: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;
};
/* endless expansion capabilites - current gallium has 252 formats */
@ -364,6 +217,9 @@ struct virgl_caps_v1 {
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;
};
union virgl_caps {
@ -385,6 +241,9 @@ enum virgl_ctx_errors {
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

@ -1,5 +1,5 @@
#ifndef GRAW_PROTOCOL_H
#define GRAW_PROTOCOL_H
#ifndef VIRGL_PROTOCOL_H
#define VIRGL_PROTOCOL_H
#define VIRGL_QUERY_STATE_NEW 0
#define VIRGL_QUERY_STATE_DONE 1
@ -24,6 +24,7 @@ enum virgl_object_type {
VIRGL_OBJECT_SURFACE,
VIRGL_OBJECT_QUERY,
VIRGL_OBJECT_STREAMOUT_TARGET,
VIRGL_OBJECT_GS,
VIRGL_MAX_OBJECTS,
};
@ -55,8 +56,13 @@ enum virgl_context_cmd {
VIRGL_CCMD_SET_CLIP_STATE,
VIRGL_CCMD_SET_SAMPLE_MASK,
VIRGL_CCMD_SET_STREAMOUT_TARGETS,
VIRGL_CCMD_SET_QUERY_STATE,
VIRGL_CCMD_SET_RENDER_CONDITION,
VIRGL_CCMD_SET_UNIFORM_BUFFER,
VIRGL_CCMD_SET_SUB_CTX,
VIRGL_CCMD_CREATE_SUB_CTX,
VIRGL_CCMD_DESTROY_SUB_CTX,
};
/*
@ -67,4 +73,360 @@ enum virgl_context_cmd {
#define VIRGL_CMD0(cmd, obj, len) ((cmd) | ((obj) << 8) | ((len) << 16))
/* hw specification */
#define VIRGL_MAX_COLOR_BUFS 8
#define VIRGL_MAX_CLIP_PLANES 8
#define VIRGL_OBJ_CREATE_HEADER 0
#define VIRGL_OBJ_CREATE_HANDLE 1
#define VIRGL_OBJ_BIND_HEADER 0
#define VIRGL_OBJ_BIND_HANDLE 1
#define VIRGL_OBJ_DESTROY_HANDLE 1
/* some of these defines are a specification - not used in the code */
/* bit offsets for blend state object */
#define VIRGL_OBJ_BLEND_SIZE (VIRGL_MAX_COLOR_BUFS + 3)
#define VIRGL_OBJ_BLEND_HANDLE 1
#define VIRGL_OBJ_BLEND_S0 2
#define VIRGL_OBJ_BLEND_S0_INDEPENDENT_BLEND_ENABLE(x) ((x) & 0x1 << 0)
#define VIRGL_OBJ_BLEND_S0_LOGICOP_ENABLE(x) (((x) & 0x1) << 1)
#define VIRGL_OBJ_BLEND_S0_DITHER(x) (((x) & 0x1) << 2)
#define VIRGL_OBJ_BLEND_S0_ALPHA_TO_COVERAGE(x) (((x) & 0x1) << 3)
#define VIRGL_OBJ_BLEND_S0_ALPHA_TO_ONE(x) (((x) & 0x1) << 4)
#define VIRGL_OBJ_BLEND_S1 3
#define VIRGL_OBJ_BLEND_S1_LOGICOP_FUNC(x) (((x) & 0xf) << 0)
/* repeated once per number of cbufs */
#define VIRGL_OBJ_BLEND_S2(cbuf) (4 + (cbuf))
#define VIRGL_OBJ_BLEND_S2_RT_BLEND_ENABLE(x) (((x) & 0x1) << 0)
#define VIRGL_OBJ_BLEND_S2_RT_RGB_FUNC(x) (((x) & 0x7) << 1)
#define VIRGL_OBJ_BLEND_S2_RT_RGB_SRC_FACTOR(x) (((x) & 0x1f) << 4)
#define VIRGL_OBJ_BLEND_S2_RT_RGB_DST_FACTOR(x) (((x) & 0x1f) << 9)
#define VIRGL_OBJ_BLEND_S2_RT_ALPHA_FUNC(x) (((x) & 0x7) << 14)
#define VIRGL_OBJ_BLEND_S2_RT_ALPHA_SRC_FACTOR(x) (((x) & 0x1f) << 17)
#define VIRGL_OBJ_BLEND_S2_RT_ALPHA_DST_FACTOR(x) (((x) & 0x1f) << 22)
#define VIRGL_OBJ_BLEND_S2_RT_COLORMASK(x) (((x) & 0xf) << 27)
/* bit offsets for DSA state */
#define VIRGL_OBJ_DSA_SIZE 5
#define VIRGL_OBJ_DSA_HANDLE 1
#define VIRGL_OBJ_DSA_S0 2
#define VIRGL_OBJ_DSA_S0_DEPTH_ENABLE(x) (((x) & 0x1) << 0)
#define VIRGL_OBJ_DSA_S0_DEPTH_WRITEMASK(x) (((x) & 0x1) << 1)
#define VIRGL_OBJ_DSA_S0_DEPTH_FUNC(x) (((x) & 0x7) << 2)
#define VIRGL_OBJ_DSA_S0_ALPHA_ENABLED(x) (((x) & 0x1) << 8)
#define VIRGL_OBJ_DSA_S0_ALPHA_FUNC(x) (((x) & 0x7) << 9)
#define VIRGL_OBJ_DSA_S1 3
#define VIRGL_OBJ_DSA_S2 4
#define VIRGL_OBJ_DSA_S1_STENCIL_ENABLED(x) (((x) & 0x1) << 0)
#define VIRGL_OBJ_DSA_S1_STENCIL_FUNC(x) (((x) & 0x7) << 1)
#define VIRGL_OBJ_DSA_S1_STENCIL_FAIL_OP(x) (((x) & 0x7) << 4)
#define VIRGL_OBJ_DSA_S1_STENCIL_ZPASS_OP(x) (((x) & 0x7) << 7)
#define VIRGL_OBJ_DSA_S1_STENCIL_ZFAIL_OP(x) (((x) & 0x7) << 10)
#define VIRGL_OBJ_DSA_S1_STENCIL_VALUEMASK(x) (((x) & 0xff) << 13)
#define VIRGL_OBJ_DSA_S1_STENCIL_WRITEMASK(x) (((x) & 0xff) << 21)
#define VIRGL_OBJ_DSA_ALPHA_REF 5
/* offsets for rasterizer state */
#define VIRGL_OBJ_RS_SIZE 9
#define VIRGL_OBJ_RS_HANDLE 1
#define VIRGL_OBJ_RS_S0 2
#define VIRGL_OBJ_RS_S0_FLATSHADE(x) (((x) & 0x1) << 0)
#define VIRGL_OBJ_RS_S0_DEPTH_CLIP(x) (((x) & 0x1) << 1)
#define VIRGL_OBJ_RS_S0_CLIP_HALFZ(x) (((x) & 0x1) << 2)
#define VIRGL_OBJ_RS_S0_RASTERIZER_DISCARD(x) (((x) & 0x1) << 3)
#define VIRGL_OBJ_RS_S0_FLATSHADE_FIRST(x) (((x) & 0x1) << 4)
#define VIRGL_OBJ_RS_S0_LIGHT_TWOSIZE(x) (((x) & 0x1) << 5)
#define VIRGL_OBJ_RS_S0_SPRITE_COORD_MODE(x) (((x) & 0x1) << 6)
#define VIRGL_OBJ_RS_S0_POINT_QUAD_RASTERIZATION(x) (((x) & 0x1) << 7)
#define VIRGL_OBJ_RS_S0_CULL_FACE(x) (((x) & 0x3) << 8)
#define VIRGL_OBJ_RS_S0_FILL_FRONT(x) (((x) & 0x3) << 10)
#define VIRGL_OBJ_RS_S0_FILL_BACK(x) (((x) & 0x3) << 12)
#define VIRGL_OBJ_RS_S0_SCISSOR(x) (((x) & 0x1) << 14)
#define VIRGL_OBJ_RS_S0_FRONT_CCW(x) (((x) & 0x1) << 15)
#define VIRGL_OBJ_RS_S0_CLAMP_VERTEX_COLOR(x) (((x) & 0x1) << 16)
#define VIRGL_OBJ_RS_S0_CLAMP_FRAGMENT_COLOR(x) (((x) & 0x1) << 17)
#define VIRGL_OBJ_RS_S0_OFFSET_LINE(x) (((x) & 0x1) << 18)
#define VIRGL_OBJ_RS_S0_OFFSET_POINT(x) (((x) & 0x1) << 19)
#define VIRGL_OBJ_RS_S0_OFFSET_TRI(x) (((x) & 0x1) << 20)
#define VIRGL_OBJ_RS_S0_POLY_SMOOTH(x) (((x) & 0x1) << 21)
#define VIRGL_OBJ_RS_S0_POLY_STIPPLE_ENABLE(x) (((x) & 0x1) << 22)
#define VIRGL_OBJ_RS_S0_POINT_SMOOTH(x) (((x) & 0x1) << 23)
#define VIRGL_OBJ_RS_S0_POINT_SIZE_PER_VERTEX(x) (((x) & 0x1) << 24)
#define VIRGL_OBJ_RS_S0_MULTISAMPLE(x) (((x) & 0x1) << 25)
#define VIRGL_OBJ_RS_S0_LINE_SMOOTH(x) (((x) & 0x1) << 26)
#define VIRGL_OBJ_RS_S0_LINE_STIPPLE_ENABLE(x) (((x) & 0x1) << 27)
#define VIRGL_OBJ_RS_S0_LINE_LAST_PIXEL(x) (((x) & 0x1) << 28)
#define VIRGL_OBJ_RS_S0_HALF_PIXEL_CENTER(x) (((x) & 0x1) << 29)
#define VIRGL_OBJ_RS_S0_BOTTOM_EDGE_RULE(x) (((x) & 0x1) << 30)
#define VIRGL_OBJ_RS_POINT_SIZE 3
#define VIRGL_OBJ_RS_SPRITE_COORD_ENABLE 4
#define VIRGL_OBJ_RS_S3 5
#define VIRGL_OBJ_RS_S3_LINE_STIPPLE_PATTERN(x) (((x) & 0xffff) << 0)
#define VIRGL_OBJ_RS_S3_LINE_STIPPLE_FACTOR(x) (((x) & 0xff) << 16)
#define VIRGL_OBJ_RS_S3_CLIP_PLANE_ENABLE(x) (((x) & 0xff) << 24)
#define VIRGL_OBJ_RS_LINE_WIDTH 6
#define VIRGL_OBJ_RS_OFFSET_UNITS 7
#define VIRGL_OBJ_RS_OFFSET_SCALE 8
#define VIRGL_OBJ_RS_OFFSET_CLAMP 9
#define VIRGL_OBJ_CLEAR_SIZE 8
#define VIRGL_OBJ_CLEAR_BUFFERS 1
#define VIRGL_OBJ_CLEAR_COLOR_0 2 /* color is 4 * u32/f32/i32 */
#define VIRGL_OBJ_CLEAR_COLOR_1 3
#define VIRGL_OBJ_CLEAR_COLOR_2 4
#define VIRGL_OBJ_CLEAR_COLOR_3 5
#define VIRGL_OBJ_CLEAR_DEPTH_0 6 /* depth is a double precision float */
#define VIRGL_OBJ_CLEAR_DEPTH_1 7
#define VIRGL_OBJ_CLEAR_STENCIL 8
/* shader object */
#define VIRGL_OBJ_SHADER_HDR_SIZE(nso) (3 + ((nso) ? (nso) + 4 : 0))
#define VIRGL_OBJ_SHADER_HANDLE 1
#define VIRGL_OBJ_SHADER_NUM_TOKENS 2
#define VIRGL_OBJ_SHADER_SO_NUM_OUTPUTS 3
#define VIRGL_OBJ_SHADER_SO_STRIDE(x) (4 + (x))
#define VIRGL_OBJ_SHADER_SO_OUTPUT0(x) (8 + (x))
#define VIRGL_OBJ_SHADER_SO_OUTPUT_REGISTER_INDEX(x) (((x) & 0xff) << 0)
#define VIRGL_OBJ_SHADER_SO_OUTPUT_START_COMPONENT(x) (((x) & 0x3) << 8)
#define VIRGL_OBJ_SHADER_SO_OUTPUT_NUM_COMPONENTS(x) (((x) & 0x7) << 10)
#define VIRGL_OBJ_SHADER_SO_OUTPUT_BUFFER(x) (((x) & 0x7) << 1)
#define VIRGL_OBJ_SHADER_SO_OUTPUT_DST_OFFSET(x) (((x) & 0xffff) << 16)
/* viewport state */
#define VIRGL_SET_VIEWPORT_STATE_SIZE 8
#define VIRGL_SET_VIEWPORT_STATE_SCALE_0 1
#define VIRGL_SET_VIEWPORT_STATE_SCALE_1 2
#define VIRGL_SET_VIEWPORT_STATE_SCALE_2 3
#define VIRGL_SET_VIEWPORT_STATE_SCALE_3 4
#define VIRGL_SET_VIEWPORT_STATE_TRANSLATE_0 5
#define VIRGL_SET_VIEWPORT_STATE_TRANSLATE_1 6
#define VIRGL_SET_VIEWPORT_STATE_TRANSLATE_2 7
#define VIRGL_SET_VIEWPORT_STATE_TRANSLATE_3 8
/* framebuffer state */
#define VIRGL_SET_FRAMEBUFFER_STATE_SIZE(nr_cbufs) (nr_cbufs + 2)
#define VIRGL_SET_FRAMEBUFFER_STATE_NR_CBUFS 1
#define VIRGL_SET_FRAMEBUFFER_STATE_NR_ZSURF_HANDLE 2
#define VIRGL_SET_FRAMEBUFFER_STATE_CBUF_HANDLE(x) ((x) + 3)
/* vertex elements object */
#define VIRGL_OBJ_VERTEX_ELEMENTS_SIZE(num_elements) (((num_elements) * 4) + 1)
#define VIRGL_OBJ_VERTEX_ELEMENTS_HANDLE 1
#define VIRGL_OBJ_VERTEX_ELEMENTS_V0_SRC_OFFSET(x) (((x) * 4) + 2) /* repeated per VE */
#define VIRGL_OBJ_VERTEX_ELEMENTS_V0_INSTANCE_DIVISOR(x) (((x) * 4) + 3)
#define VIRGL_OBJ_VERTEX_ELEMENTS_V0_VERTEX_BUFFER_INDEX(x) (((x) * 4) + 4)
#define VIRGL_OBJ_VERTEX_ELEMENTS_V0_SRC_FORMAT(x) (((x) * 4) + 5)
/* vertex buffers */
#define VIRGL_SET_VERTEX_BUFFERS_SIZE(num_buffers) ((num_buffers) * 3)
#define VIRGL_SET_VERTEX_BUFFER_STRIDE(x) (((x) * 3) + 1)
#define VIRGL_SET_VERTEX_BUFFER_OFFSET(x) (((x) * 3) + 2)
#define VIRGL_SET_VERTEX_BUFFER_HANDLE(x) (((x) * 3) + 3)
/* index buffer */
#define VIRGL_SET_INDEX_BUFFER_SIZE(ib) (((ib) ? 2 : 0) + 1)
#define VIRGL_SET_INDEX_BUFFER_HANDLE 1
#define VIRGL_SET_INDEX_BUFFER_INDEX_SIZE 2 /* only if sending an IB handle */
#define VIRGL_SET_INDEX_BUFFER_OFFSET 3 /* only if sending an IB handle */
/* constant buffer */
#define VIRGL_SET_CONSTANT_BUFFER_SHADER_TYPE 1
#define VIRGL_SET_CONSTANT_BUFFER_INDEX 2
#define VIRGL_SET_CONSTANT_BUFFER_DATA_START 3
#define VIRGL_SET_UNIFORM_BUFFER_SIZE 5
#define VIRGL_SET_UNIFORM_BUFFER_SHADER_TYPE 1
#define VIRGL_SET_UNIFORM_BUFFER_INDEX 2
#define VIRGL_SET_UNIFORM_BUFFER_OFFSET 3
#define VIRGL_SET_UNIFORM_BUFFER_LENGTH 4
#define VIRGL_SET_UNIFORM_BUFFER_RES_HANDLE 5
/* draw VBO */
#define VIRGL_DRAW_VBO_SIZE 11
#define VIRGL_DRAW_VBO_START 1
#define VIRGL_DRAW_VBO_COUNT 2
#define VIRGL_DRAW_VBO_MODE 3
#define VIRGL_DRAW_VBO_INDEXED 4
#define VIRGL_DRAW_VBO_INSTANCE_COUNT 5
#define VIRGL_DRAW_VBO_INDEX_BIAS 6
#define VIRGL_DRAW_VBO_START_INSTANCE 7
#define VIRGL_DRAW_VBO_PRIMITIVE_RESTART 8
#define VIRGL_DRAW_VBO_RESTART_INDEX 9
#define VIRGL_DRAW_VBO_MIN_INDEX 10
#define VIRGL_DRAW_VBO_MAX_INDEX 11
/* create surface */
#define VIRGL_OBJ_SURFACE_SIZE 5
#define VIRGL_OBJ_SURFACE_HANDLE 1
#define VIRGL_OBJ_SURFACE_RES_HANDLE 2
#define VIRGL_OBJ_SURFACE_FORMAT 3
#define VIRGL_OBJ_SURFACE_BUFFER_FIRST_ELEMENT 4
#define VIRGL_OBJ_SURFACE_BUFFER_LAST_ELEMENT 5
#define VIRGL_OBJ_SURFACE_TEXTURE_LEVEL 4
#define VIRGL_OBJ_SURFACE_TEXTURE_LAYERS 5
/* create streamout target */
#define VIRGL_OBJ_STREAMOUT_SIZE 4
#define VIRGL_OBJ_STREAMOUT_HANDLE 1
#define VIRGL_OBJ_STREAMOUT_RES_HANDLE 2
#define VIRGL_OBJ_STREAMOUT_BUFFER_OFFSET 3
#define VIRGL_OBJ_STREAMOUT_BUFFER_SIZE 4
/* sampler state */
#define VIRGL_OBJ_SAMPLER_STATE_SIZE 9
#define VIRGL_OBJ_SAMPLER_STATE_HANDLE 1
#define VIRGL_OBJ_SAMPLER_STATE_S0 2
#define VIRGL_OBJ_SAMPLE_STATE_S0_WRAP_S(x) (((x) & 0x7) << 0)
#define VIRGL_OBJ_SAMPLE_STATE_S0_WRAP_T(x) (((x) & 0x7) << 3)
#define VIRGL_OBJ_SAMPLE_STATE_S0_WRAP_R(x) (((x) & 0x7) << 6)
#define VIRGL_OBJ_SAMPLE_STATE_S0_MIN_IMG_FILTER(x) (((x) & 0x3) << 9)
#define VIRGL_OBJ_SAMPLE_STATE_S0_MIN_MIP_FILTER(x) (((x) & 0x3) << 11)
#define VIRGL_OBJ_SAMPLE_STATE_S0_MAG_IMG_FILTER(x) (((x) & 0x3) << 13)
#define VIRGL_OBJ_SAMPLE_STATE_S0_COMPARE_MODE(x) (((x) & 0x1) << 15)
#define VIRGL_OBJ_SAMPLE_STATE_S0_COMPARE_FUNC(x) (((x) & 0x7) << 16)
#define VIRGL_OBJ_SAMPLER_STATE_LOD_BIAS 3
#define VIRGL_OBJ_SAMPLER_STATE_MIN_LOD 4
#define VIRGL_OBJ_SAMPLER_STATE_MAX_LOD 5
#define VIRGL_OBJ_SAMPLER_STATE_BORDER_COLOR(x) ((x) + 6) /* 6 - 9 */
/* sampler view */
#define VIRGL_OBJ_SAMPLER_VIEW_SIZE 6
#define VIRGL_OBJ_SAMPLER_VIEW_HANDLE 1
#define VIRGL_OBJ_SAMPLER_VIEW_RES_HANDLE 2
#define VIRGL_OBJ_SAMPLER_VIEW_FORMAT 3
#define VIRGL_OBJ_SAMPLER_VIEW_BUFFER_FIRST_ELEMENT 4
#define VIRGL_OBJ_SAMPLER_VIEW_BUFFER_LAST_ELEMENT 5
#define VIRGL_OBJ_SAMPLER_VIEW_TEXTURE_LAYER 4
#define VIRGL_OBJ_SAMPLER_VIEW_TEXTURE_LEVEL 5
#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE 6
#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_R(x) (((x) & 0x7) << 0)
#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_G(x) (((x) & 0x7) << 3)
#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_B(x) (((x) & 0x7) << 6)
#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_A(x) (((x) & 0x7) << 9)
/* set sampler views */
#define VIRGL_SET_SAMPLER_VIEWS_SIZE(num_views) ((num_views) + 2)
#define VIRGL_SET_SAMPLER_VIEWS_SHADER_TYPE 1
#define VIRGL_SET_SAMPLER_VIEWS_START_SLOT 2
#define VIRGL_SET_SAMPLER_VIEWS_V0_HANDLE 3
/* bind sampler states */
#define VIRGL_BIND_SAMPLER_STATES(num_states) ((num_states) + 2)
#define VIRGL_BIND_SAMPLER_STATES_SHADER_TYPE 1
#define VIRGL_BIND_SAMPLER_STATES_START_SLOT 2
#define VIRGL_BIND_SAMPLER_STATES_S0_HANDLE 3
/* set stencil reference */
#define VIRGL_SET_STENCIL_REF_SIZE 1
#define VIRGL_SET_STENCIL_REF 1
#define VIRGL_STENCIL_REF_VAL(f, s) ((f & 0xff) | (((s & 0xff) << 8)))
/* set blend color */
#define VIRGL_SET_BLEND_COLOR_SIZE 4
#define VIRGL_SET_BLEND_COLOR(x) ((x) + 1)
/* set scissor state */
#define VIRGL_SET_SCISSOR_STATE_SIZE 2
#define VIRGL_SET_SCISSOR_MINX_MINY 1
#define VIRGL_SET_SCISSOR_MAXX_MAXY 2
/* resource copy region */
#define VIRGL_CMD_RESOURCE_COPY_REGION_SIZE 13
#define VIRGL_CMD_RCR_DST_RES_HANDLE 1
#define VIRGL_CMD_RCR_DST_LEVEL 2
#define VIRGL_CMD_RCR_DST_X 3
#define VIRGL_CMD_RCR_DST_Y 4
#define VIRGL_CMD_RCR_DST_Z 5
#define VIRGL_CMD_RCR_SRC_RES_HANDLE 6
#define VIRGL_CMD_RCR_SRC_LEVEL 7
#define VIRGL_CMD_RCR_SRC_X 8
#define VIRGL_CMD_RCR_SRC_Y 9
#define VIRGL_CMD_RCR_SRC_Z 10
#define VIRGL_CMD_RCR_SRC_W 11
#define VIRGL_CMD_RCR_SRC_H 12
#define VIRGL_CMD_RCR_SRC_D 13
/* blit */
#define VIRGL_CMD_BLIT_SIZE 21
#define VIRGL_CMD_BLIT_S0 1
#define VIRGL_CMD_BLIT_S0_MASK(x) (((x) & 0xff) << 0)
#define VIRGL_CMD_BLIT_S0_FILTER(x) (((x) & 0x3) << 8)
#define VIRGL_CMD_BLIT_S0_SCISSOR_ENABLE(x) (((x) & 0x1) << 10)
#define VIRGL_CMD_BLIT_SCISSOR_MINX_MINY 2
#define VIRGL_CMD_BLIT_SCISSOR_MAXX_MAXY 3
#define VIRGL_CMD_BLIT_DST_RES_HANDLE 4
#define VIRGL_CMD_BLIT_DST_LEVEL 5
#define VIRGL_CMD_BLIT_DST_FORMAT 6
#define VIRGL_CMD_BLIT_DST_X 7
#define VIRGL_CMD_BLIT_DST_Y 8
#define VIRGL_CMD_BLIT_DST_Z 9
#define VIRGL_CMD_BLIT_DST_W 10
#define VIRGL_CMD_BLIT_DST_H 11
#define VIRGL_CMD_BLIT_DST_D 12
#define VIRGL_CMD_BLIT_SRC_RES_HANDLE 13
#define VIRGL_CMD_BLIT_SRC_LEVEL 14
#define VIRGL_CMD_BLIT_SRC_FORMAT 15
#define VIRGL_CMD_BLIT_SRC_X 16
#define VIRGL_CMD_BLIT_SRC_Y 17
#define VIRGL_CMD_BLIT_SRC_Z 18
#define VIRGL_CMD_BLIT_SRC_W 19
#define VIRGL_CMD_BLIT_SRC_H 20
#define VIRGL_CMD_BLIT_SRC_D 21
/* query object */
#define VIRGL_OBJ_QUERY_SIZE 4
#define VIRGL_OBJ_QUERY_HANDLE 1
#define VIRGL_OBJ_QUERY_TYPE 2
#define VIRGL_OBJ_QUERY_OFFSET 3
#define VIRGL_OBJ_QUERY_RES_HANDLE 4
#define VIRGL_QUERY_BEGIN_HANDLE 1
#define VIRGL_QUERY_END_HANDLE 1
#define VIRGL_QUERY_RESULT_HANDLE 1
#define VIRGL_QUERY_RESULT_WAIT 2
/* render condition */
#define VIRGL_RENDER_CONDITION_SIZE 3
#define VIRGL_RENDER_CONDITION_HANDLE 1
#define VIRGL_RENDER_CONDITION_CONDITION 2
#define VIRGL_RENDER_CONDITION_MODE 3
/* resource inline write */
#define VIRGL_RESOURCE_IW_RES_HANDLE 1
#define VIRGL_RESOURCE_IW_LEVEL 2
#define VIRGL_RESOURCE_IW_USAGE 3
#define VIRGL_RESOURCE_IW_STRIDE 4
#define VIRGL_RESOURCE_IW_LAYER_STRIDE 5
#define VIRGL_RESOURCE_IW_X 6
#define VIRGL_RESOURCE_IW_Y 7
#define VIRGL_RESOURCE_IW_Z 8
#define VIRGL_RESOURCE_IW_W 9
#define VIRGL_RESOURCE_IW_H 10
#define VIRGL_RESOURCE_IW_D 11
#define VIRGL_RESOURCE_IW_DATA_START 12
/* set streamout targets */
#define VIRGL_SET_STREAMOUT_TARGETS_APPEND_BITMASK 1
#define VIRGL_SET_STREAMOUT_TARGETS_H0 2
/* set sample mask */
#define VIRGL_SET_SAMPLE_MASK_SIZE 1
#define VIRGL_SET_SAMPLE_MASK_MASK 1
/* set clip state */
#define VIRGL_SET_CLIP_STATE_SIZE 32
#define VIRGL_SET_CLIP_STATE_C0 1
/* polygon stipple */
#define VIRGL_POLYGON_STIPPLE_SIZE 32
#define VIRGL_POLYGON_STIPPLE_P0 1
#endif

@ -0,0 +1,282 @@
/**************************************************************************
*
* Copyright (C) 2014 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 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 <stdio.h>
#include <time.h>
#include <epoxy/gl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/eventfd.h>
#include "pipe/p_state.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "vrend_renderer.h"
#include "virglrenderer.h"
#include "virgl_egl.h"
/* new API - just wrap internal API for now */
int virgl_renderer_resource_create(struct virgl_renderer_resource_create_args *args, struct iovec *iov, uint32_t num_iovs)
{
return vrend_renderer_resource_create((struct vrend_renderer_resource_create_args *)args, iov, num_iovs);
}
void virgl_renderer_resource_unref(uint32_t res_handle)
{
vrend_renderer_resource_unref(res_handle);
}
void virgl_renderer_fill_caps(uint32_t set, uint32_t version,
void *caps)
{
vrend_renderer_fill_caps(set, version, (union virgl_caps *)caps);
}
int virgl_renderer_context_create(uint32_t handle, uint32_t nlen, const char *name)
{
vrend_renderer_context_create(handle, nlen, name);
return 0;
}
void virgl_renderer_context_destroy(uint32_t handle)
{
vrend_renderer_context_destroy(handle);
}
void virgl_renderer_submit_cmd(void *buffer,
int ctx_id,
int ndw)
{
vrend_decode_block(ctx_id, buffer, ndw);
}
void virgl_renderer_transfer_write_iov(uint32_t handle,
uint32_t ctx_id,
int level,
uint32_t stride,
uint32_t layer_stride,
struct virgl_box *box,
uint64_t offset,
struct iovec *iovec,
unsigned int iovec_cnt)
{
vrend_renderer_transfer_write_iov(handle, ctx_id, level,
stride, layer_stride, (struct pipe_box *)box,
offset, iovec, iovec_cnt);
}
void virgl_renderer_transfer_read_iov(uint32_t handle, uint32_t ctx_id,
uint32_t level, uint32_t stride,
uint32_t layer_stride,
struct virgl_box *box,
uint64_t offset, struct iovec *iov,
int iovec_cnt)
{
vrend_renderer_transfer_send_iov(handle, ctx_id, level, stride,
layer_stride, (struct pipe_box *)box,
offset, iov, iovec_cnt);
}
int virgl_renderer_resource_attach_iov(int res_handle, struct iovec *iov,
int num_iovs)
{
return vrend_renderer_resource_attach_iov(res_handle, iov, num_iovs);
}
void virgl_renderer_resource_detach_iov(int res_handle, struct iovec **iov_p, int *num_iovs_p)
{
return vrend_renderer_resource_detach_iov(res_handle, iov_p, num_iovs_p);
}
int virgl_renderer_create_fence(int client_fence_id, uint32_t ctx_id)
{
return vrend_renderer_create_fence(client_fence_id, ctx_id);
}
void virgl_renderer_force_ctx_0(void)
{
vrend_renderer_force_ctx_0();
}
void virgl_renderer_ctx_attach_resource(int ctx_id, int res_handle)
{
vrend_renderer_attach_res_ctx(ctx_id, res_handle);
}
void virgl_renderer_ctx_detach_resource(int ctx_id, int res_handle)
{
vrend_renderer_detach_res_ctx(ctx_id, res_handle);
}
int virgl_renderer_resource_get_info(int res_handle,
struct virgl_renderer_resource_info *info)
{
int ret;
ret = vrend_renderer_resource_get_info(res_handle, (struct vrend_renderer_resource_info *)info);
info->format = virgl_egl_get_gbm_format(info->format);
return ret;
}
void virgl_renderer_get_cap_set(uint32_t cap_set, uint32_t *max_ver,
uint32_t *max_size)
{
vrend_renderer_get_cap_set(cap_set, max_ver, max_size);
}
void virgl_renderer_get_rect(int resource_id, struct iovec *iov, unsigned int num_iovs,
uint32_t offset, int x, int y, int width, int height)
{
vrend_renderer_get_rect(resource_id, iov, num_iovs, offset, x, y, width, height);
}
static struct virgl_renderer_callbacks *rcbs;
static void *dev_cookie;
static int use_egl_context;
struct virgl_egl *egl_info;
static struct vrend_if_cbs virgl_cbs;
void vrend_transfer_write_return(void *data, uint32_t bytes, uint64_t offset,
struct iovec *iov, int num_iovs)
{
vrend_write_to_iovec(iov, num_iovs, offset, data, bytes);
}
void vrend_transfer_write_tex_return(struct pipe_resource *res,
struct pipe_box *box,
uint32_t level,
uint32_t dst_stride,
uint64_t offset,
struct iovec *iov,
int num_iovs,
void *myptr, int size, int invert)
{
int elsize = util_format_get_blocksize(res->format);
int h;
uint32_t myoffset = offset;
uint32_t stride = dst_stride ? dst_stride : util_format_get_nblocksx(res->format, u_minify(res->width0, level)) * elsize;
// uint32_t stride = dst_stride ? dst_stride : util_format_get_nblocksx(res->format, box->width) * elsize;
if (!invert && (stride == util_format_get_nblocksx(res->format, box->width) * elsize))
vrend_write_to_iovec(iov, num_iovs, offset, myptr, size);
else if (invert) {
for (h = box->height - 1; h >= 0; h--) {
void *sptr = myptr + (h * elsize * box->width);
vrend_write_to_iovec(iov, num_iovs, myoffset, sptr, box->width * elsize);
myoffset += stride;
}
} else {
for (h = 0; h < box->height; h++) {
void *sptr = myptr + (h * elsize * box->width);
vrend_write_to_iovec(iov, num_iovs, myoffset, sptr, box->width * elsize);
myoffset += stride;
}
}
}
static void virgl_write_fence(uint32_t fence_id)
{
rcbs->write_fence(dev_cookie, fence_id);
}
static virgl_renderer_gl_context create_gl_context(int scanout_idx, struct virgl_gl_ctx_param *param)
{
struct virgl_renderer_gl_ctx_param vparam;
if (use_egl_context)
return virgl_egl_create_context(egl_info, param);
vparam.version = 1;
vparam.shared = param->shared;
vparam.major_ver = param->major_ver;
vparam.minor_ver = param->minor_ver;
return rcbs->create_gl_context(dev_cookie, scanout_idx, &vparam);
}
static void destroy_gl_context(virgl_renderer_gl_context ctx)
{
if (use_egl_context)
return virgl_egl_destroy_context(egl_info, ctx);
return rcbs->destroy_gl_context(dev_cookie, ctx);
}
static int make_current(int scanout_idx, virgl_renderer_gl_context ctx)
{
if (use_egl_context)
return virgl_egl_make_context_current(egl_info, ctx);
return rcbs->make_current(dev_cookie, scanout_idx, ctx);
}
static struct vrend_if_cbs virgl_cbs = {
virgl_write_fence,
create_gl_context,
destroy_gl_context,
make_current,
};
void *virgl_renderer_get_cursor_data(uint32_t resource_id, uint32_t *width, uint32_t *height)
{
return vrend_renderer_get_cursor_contents(resource_id, width, height);
}
void virgl_renderer_poll(void)
{
virgl_renderer_force_ctx_0();
vrend_renderer_check_queries();
vrend_renderer_check_fences();
}
int virgl_renderer_init(void *cookie, int flags, struct virgl_renderer_callbacks *cbs)
{
dev_cookie = cookie;
rcbs = cbs;
if (flags & VIRGL_RENDERER_USE_EGL) {
egl_info = virgl_egl_init();
if (!egl_info)
return -1;
use_egl_context = 1;
}
if (cbs->version != 1)
return -1;
vrend_renderer_init(&virgl_cbs);
return 0;
}
int virgl_renderer_get_fd_for_texture(uint32_t tex_id, int *fd)
{
return virgl_egl_get_fd_for_texture(egl_info, tex_id, fd);
}
void virgl_renderer_reset(void)
{
vrend_renderer_reset();
}

@ -1,35 +1,57 @@
/**************************************************************************
*
* Copyright (C) 2014 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 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.
*
**************************************************************************/
/* library interface from QEMU to virglrenderer */
#ifndef VIRGLRENDERER_H
#define VIRGLRENDERER_H
#include <stdint.h>
#include <stdbool.h>
struct virgl_iovec;
struct virgl_box;
struct iovec;
#define VIRGL_EXPORT __attribute__((visibility("default")))
typedef void *virgl_gl_context;
typedef void *virgl_renderer_gl_context;
struct virgl_renderer_gl_ctx_param {
int version;
bool shared;
int major_ver;
int minor_ver;
};
struct virgl_renderer_callbacks {
int version;
void (*write_fence)(void *cookie, uint32_t fence);
int (*map_iov)(struct virgl_iovec *iov, uint64_t addr);
void (*unmap_iov)(struct virgl_iovec *iov);
/* interact with GL implementation */
virgl_gl_context (*create_gl_context)(void *cookie, int scanout_idx);
void (*destroy_gl_context)(void *cookie, virgl_gl_context ctx);
int (*make_current)(void *cookie, int scanout_idx, virgl_gl_context ctx);
/* */
void (*rect_update)(void *cookie, int idx, int x, int y, int width, int height);
void (*scanout_resource_info)(void *cookie, int idx, uint32_t tex_id, uint32_t flags,
uint32_t stride, uint32_t width, uint32_t height, uint32_t format);
void (*scanout_rect_info)(void *cookie, int idx, uint32_t tex_id,
int x, int y,
uint32_t width, uint32_t height);
virgl_renderer_gl_context (*create_gl_context)(void *cookie, int scanout_idx, struct virgl_renderer_gl_ctx_param *param);
void (*destroy_gl_context)(void *cookie, virgl_renderer_gl_context ctx);
int (*make_current)(void *cookie, int scanout_idx, virgl_renderer_gl_context ctx);
};
/* virtio-gpu compatible interface */
@ -38,15 +60,92 @@ struct virgl_renderer_callbacks {
VIRGL_EXPORT int virgl_renderer_init(void *cookie, int flags, struct virgl_renderer_callbacks *cb);
VIRGL_EXPORT void virgl_renderer_poll(void); /* force fences */
VIRGL_EXPORT int virgl_renderer_process_vcmd(void *cmd, struct virgl_iovec *iov, unsigned int num_iovs);
VIRGL_EXPORT void virgl_renderer_set_cursor_info(uint32_t cursor_handle, int x, int y);
/* we need to give qemu the cursor resource contents */
VIRGL_EXPORT void *virgl_get_cursor_data(uint32_t resource_id, uint32_t *width, uint32_t *height);
VIRGL_EXPORT void *virgl_renderer_get_cursor_data(uint32_t resource_id, uint32_t *width, uint32_t *height);
VIRGL_EXPORT void virgl_renderer_get_rect(int idx, struct virgl_iovec *iov, unsigned int num_iovs,
VIRGL_EXPORT void virgl_renderer_get_rect(int resource_id, struct iovec *iov, unsigned int num_iovs,
uint32_t offset, int x, int y, int width, int height);
VIRGL_EXPORT int virgl_renderer_get_fd_for_texture(uint32_t tex_id, int *fd);
struct virgl_resource;
struct virgl_renderer_resource_create_args {
uint32_t handle;
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;
};
/* new API */
VIRGL_EXPORT int virgl_renderer_resource_create(struct virgl_renderer_resource_create_args *args, struct iovec *iov, uint32_t num_iovs);
VIRGL_EXPORT void virgl_renderer_resource_unref(uint32_t res_handle);
VIRGL_EXPORT int virgl_renderer_context_create(uint32_t handle, uint32_t nlen, const char *name);
VIRGL_EXPORT void virgl_renderer_context_destroy(uint32_t handle);
VIRGL_EXPORT void virgl_renderer_submit_cmd(void *buffer,
int ctx_id,
int ndw);
VIRGL_EXPORT void virgl_renderer_transfer_read_iov(uint32_t handle, uint32_t ctx_id,
uint32_t level, uint32_t stride,
uint32_t layer_stride,
struct virgl_box *box,
uint64_t offset, struct iovec *iov,
int iovec_cnt);
VIRGL_EXPORT void virgl_renderer_transfer_write_iov(uint32_t handle,
uint32_t ctx_id,
int level,
uint32_t stride,
uint32_t layer_stride,
struct virgl_box *box,
uint64_t offset,
struct iovec *iovec,
unsigned int iovec_cnt);
VIRGL_EXPORT void virgl_renderer_get_cap_set(uint32_t set, uint32_t *max_ver,
uint32_t *max_size);
VIRGL_EXPORT void virgl_renderer_fill_caps(uint32_t set, uint32_t version,
void *caps);
VIRGL_EXPORT int virgl_renderer_resource_attach_iov(int res_handle, struct iovec *iov,
int num_iovs);
VIRGL_EXPORT void virgl_renderer_resource_detach_iov(int res_handle, struct iovec **iov, int *num_iovs);
VIRGL_EXPORT int virgl_renderer_create_fence(int client_fence_id, uint32_t ctx_id);
VIRGL_EXPORT void virgl_renderer_force_ctx_0(void);
VIRGL_EXPORT void virgl_renderer_ctx_attach_resource(int ctx_id, int res_handle);
VIRGL_EXPORT void virgl_renderer_ctx_detach_resource(int ctx_id, int res_handle);
/* return information about a resource */
struct virgl_renderer_resource_info {
uint32_t handle;
uint32_t format;
uint32_t width;
uint32_t height;
uint32_t depth;
uint32_t flags;
uint32_t tex_id;
uint32_t stride;
};
VIRGL_EXPORT int virgl_renderer_resource_get_info(int res_handle,
struct virgl_renderer_resource_info *info);
/* reset the rendererer - destroy all contexts and resource */
VIRGL_EXPORT void virgl_renderer_reset(void);
#endif

@ -0,0 +1,563 @@
/**************************************************************************
*
* Copyright (C) 2014 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 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.
*
**************************************************************************/
/* gallium blitter implementation in GL */
/* for when we can't use glBlitFramebuffer */
#include <epoxy/gl.h>
#include <stdio.h>
#include "pipe/p_shader_tokens.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
#include "util/u_dual_blend.h"
#include "util/u_double_list.h"
#include "util/u_format.h"
#include "util/u_texture.h"
#include "tgsi/tgsi_parse.h"
#include "vrend_object.h"
#include "vrend_shader.h"
#include "vrend_renderer.h"
#include "vrend_blitter.h"
struct vrend_blitter_ctx {
virgl_gl_context gl_context;
bool initialised;
GLuint vaoid;
GLuint vs;
GLuint vs_pos_only;
GLuint fs_texfetch_col[PIPE_MAX_TEXTURE_TYPES];
GLuint fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES];
GLuint fs_texfetch_depth_msaa[PIPE_MAX_TEXTURE_TYPES];
GLuint fb_id;
unsigned dst_width;
unsigned dst_height;
GLuint vbo_id;
GLfloat vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */
};
static struct vrend_blitter_ctx vrend_blit_ctx;
static bool build_and_check(GLuint id, const char *buf)
{
GLint param;
glShaderSource(id, 1, (const char **)&buf, NULL);
glCompileShader(id);
glGetShaderiv(id, GL_COMPILE_STATUS, &param);
if (param == GL_FALSE) {
char infolog[65536];
int len;
glGetShaderInfoLog(id, 65536, &len, infolog);
fprintf(stderr,"shader failed to compile\n%s\n", infolog);
fprintf(stderr,"GLSL:\n%s\n", buf);
return false;
}
return true;
}
static bool blit_build_vs_passthrough(struct vrend_blitter_ctx *blit_ctx)
{
blit_ctx->vs = glCreateShader(GL_VERTEX_SHADER);
if (!build_and_check(blit_ctx->vs, vs_passthrough)) {
glDeleteShader(blit_ctx->vs);
blit_ctx->vs = 0;
return false;
}
return true;
}
static GLuint blit_build_frag_tex_col(struct vrend_blitter_ctx *blit_ctx, int tgsi_tex_target)
{
GLuint fs_id;
char shader_buf[4096];
int is_shad;
const char *twm;
switch (tgsi_tex_target) {
case TGSI_TEXTURE_1D:
case TGSI_TEXTURE_BUFFER:
twm = ".x";
break;
case TGSI_TEXTURE_1D_ARRAY:
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
case TGSI_TEXTURE_2D_MSAA:
default:
twm = ".xy";
break;
case TGSI_TEXTURE_SHADOW1D:
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOW1D_ARRAY:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
case TGSI_TEXTURE_2D_ARRAY:
case TGSI_TEXTURE_2D_ARRAY_MSAA:
twm = ".xyz";
break;
case TGSI_TEXTURE_SHADOWCUBE:
case TGSI_TEXTURE_SHADOW2D_ARRAY:
case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
case TGSI_TEXTURE_CUBE_ARRAY:
twm = "";
break;
}
snprintf(shader_buf, 4096, fs_texfetch_col, vrend_shader_samplertypeconv(tgsi_tex_target, &is_shad), twm, "");
fs_id = glCreateShader(GL_FRAGMENT_SHADER);
if (!build_and_check(fs_id, shader_buf)) {
glDeleteShader(fs_id);
return 0;
}
return fs_id;
}
static GLuint blit_build_frag_tex_writedepth(struct vrend_blitter_ctx *blit_ctx, int tgsi_tex_target)
{
GLuint fs_id;
char shader_buf[4096];
int is_shad;
const char *twm;
switch (tgsi_tex_target) {
case TGSI_TEXTURE_1D:
case TGSI_TEXTURE_BUFFER:
twm = ".x";
break;
case TGSI_TEXTURE_1D_ARRAY:
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
case TGSI_TEXTURE_2D_MSAA:
default:
twm = ".xy";
break;
case TGSI_TEXTURE_SHADOW1D:
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOW1D_ARRAY:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
case TGSI_TEXTURE_2D_ARRAY:
case TGSI_TEXTURE_2D_ARRAY_MSAA:
twm = ".xyz";
break;
case TGSI_TEXTURE_SHADOWCUBE:
case TGSI_TEXTURE_SHADOW2D_ARRAY:
case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
case TGSI_TEXTURE_CUBE_ARRAY:
twm = "";
break;
}
snprintf(shader_buf, 4096, fs_texfetch_ds, vrend_shader_samplertypeconv(tgsi_tex_target, &is_shad), twm);
fs_id = glCreateShader(GL_FRAGMENT_SHADER);
if (!build_and_check(fs_id, shader_buf)) {
glDeleteShader(fs_id);
return 0;
}
return fs_id;
}
static GLuint blit_build_frag_blit_msaa_depth(struct vrend_blitter_ctx *blit_ctx, int tgsi_tex_target)
{
GLuint fs_id;
char shader_buf[4096];
int is_shad;
const char *twm;
switch (tgsi_tex_target) {
case TGSI_TEXTURE_2D_MSAA:
twm = ".xy";
break;
case TGSI_TEXTURE_2D_ARRAY_MSAA:
twm = ".xyz";
break;
default:
return 0;
}
snprintf(shader_buf, 4096, fs_texfetch_ds_msaa, vrend_shader_samplertypeconv(tgsi_tex_target, &is_shad), twm);
fs_id = glCreateShader(GL_FRAGMENT_SHADER);
if (!build_and_check(fs_id, shader_buf)) {
glDeleteShader(fs_id);
return 0;
}
return fs_id;
}
static GLuint blit_get_frag_tex_writedepth(struct vrend_blitter_ctx *blit_ctx, int pipe_tex_target, unsigned nr_samples)
{
assert(pipe_tex_target < PIPE_MAX_TEXTURE_TYPES);
if (nr_samples > 1) {
GLuint *shader = &blit_ctx->fs_texfetch_depth_msaa[pipe_tex_target];
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex_target, nr_samples);
*shader = blit_build_frag_blit_msaa_depth(blit_ctx, tgsi_tex);
}
return *shader;
} else {
GLuint *shader = &blit_ctx->fs_texfetch_depth[pipe_tex_target];
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex_target, 0);
*shader = blit_build_frag_tex_writedepth(blit_ctx, tgsi_tex);
}
return *shader;
}
}
static GLuint blit_get_frag_tex_col(struct vrend_blitter_ctx *blit_ctx, int pipe_tex_target, unsigned nr_samples)
{
assert(pipe_tex_target < PIPE_MAX_TEXTURE_TYPES);
if (nr_samples > 1) {
return 0;
} else {
GLuint *shader = &blit_ctx->fs_texfetch_col[pipe_tex_target];
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex_target, 0);
*shader = blit_build_frag_tex_col(blit_ctx, tgsi_tex);
}
return *shader;
}
}
static void vrend_renderer_init_blit_ctx(struct vrend_blitter_ctx *blit_ctx)
{
struct virgl_gl_ctx_param ctx_params;
int i;
if (blit_ctx->initialised) {
vrend_clicbs->make_current(0, blit_ctx->gl_context);
return;
}
ctx_params.shared = true;
ctx_params.major_ver = VREND_GL_VER_MAJOR;
ctx_params.minor_ver = VREND_GL_VER_MINOR;
blit_ctx->gl_context = vrend_clicbs->create_gl_context(0, &ctx_params);
vrend_clicbs->make_current(0, blit_ctx->gl_context);
glGenVertexArrays(1, &blit_ctx->vaoid);
glGenFramebuffers(1, &blit_ctx->fb_id);
glGenBuffers(1, &blit_ctx->vbo_id);
blit_build_vs_passthrough(blit_ctx);
for (i = 0; i < 4; i++)
blit_ctx->vertices[i][0][3] = 1; /*v.w*/
glBindVertexArray(blit_ctx->vaoid);
glBindBuffer(GL_ARRAY_BUFFER, blit_ctx->vbo_id);
}
static inline GLenum convert_mag_filter(unsigned int filter)
{
if (filter == PIPE_TEX_FILTER_NEAREST)
return GL_NEAREST;
return GL_LINEAR;
}
static void blitter_set_dst_dim(struct vrend_blitter_ctx *blit_ctx,
unsigned width, unsigned height)
{
blit_ctx->dst_width = width;
blit_ctx->dst_height = height;
}
static void blitter_set_rectangle(struct vrend_blitter_ctx *blit_ctx,
int x1, int y1, int x2, int y2,
float depth)
{
int i;
/* set vertex positions */
blit_ctx->vertices[0][0][0] = (float)x1 / blit_ctx->dst_width * 2.0f - 1.0f; /*v0.x*/
blit_ctx->vertices[0][0][1] = (float)y1 / blit_ctx->dst_height * 2.0f - 1.0f; /*v0.y*/
blit_ctx->vertices[1][0][0] = (float)x2 / blit_ctx->dst_width * 2.0f - 1.0f; /*v1.x*/
blit_ctx->vertices[1][0][1] = (float)y1 / blit_ctx->dst_height * 2.0f - 1.0f; /*v1.y*/
blit_ctx->vertices[2][0][0] = (float)x2 / blit_ctx->dst_width * 2.0f - 1.0f; /*v2.x*/
blit_ctx->vertices[2][0][1] = (float)y2 / blit_ctx->dst_height * 2.0f - 1.0f; /*v2.y*/
blit_ctx->vertices[3][0][0] = (float)x1 / blit_ctx->dst_width * 2.0f - 1.0f; /*v3.x*/
blit_ctx->vertices[3][0][1] = (float)y2 / blit_ctx->dst_height * 2.0f - 1.0f; /*v3.y*/
for (i = 0; i < 4; i++)
blit_ctx->vertices[i][0][2] = depth; /*z*/
glViewport(0, 0, blit_ctx->dst_width, blit_ctx->dst_height);
}
static void get_texcoords(struct vrend_resource *src_res,
int src_level,
int x1, int y1, int x2, int y2,
float out[4])
{
boolean normalized = src_res->base.target != PIPE_TEXTURE_RECT &&
src_res->base.nr_samples <= 1;
if (normalized) {
out[0] = x1 / (float)u_minify(src_res->base.width0, src_level);
out[1] = y1 / (float)u_minify(src_res->base.height0, src_level);
out[2] = x2 / (float)u_minify(src_res->base.width0, src_level);
out[3] = y2 / (float)u_minify(src_res->base.height0, src_level);
} else {
out[0] = (float) x1;
out[1] = (float) y1;
out[2] = (float) x2;
out[3] = (float) y2;
}
}
static void set_texcoords_in_vertices(const float coord[4],
float *out, unsigned stride)
{
out[0] = coord[0]; /*t0.s*/
out[1] = coord[1]; /*t0.t*/
out += stride;
out[0] = coord[2]; /*t1.s*/
out[1] = coord[1]; /*t1.t*/
out += stride;
out[0] = coord[2]; /*t2.s*/
out[1] = coord[3]; /*t2.t*/
out += stride;
out[0] = coord[0]; /*t3.s*/
out[1] = coord[3]; /*t3.t*/
}
static void blitter_set_texcoords(struct vrend_blitter_ctx *blit_ctx,
struct vrend_resource *src_res,
int level,
float layer, unsigned sample,
int x1, int y1, int x2, int y2)
{
float coord[4];
float face_coord[4][2];
int i;
get_texcoords(src_res, level, x1, y1, x2, y2, coord);
if (src_res->base.target == PIPE_TEXTURE_CUBE ||
src_res->base.target == PIPE_TEXTURE_CUBE_ARRAY) {
set_texcoords_in_vertices(coord, &face_coord[0][0], 2);
util_map_texcoords2d_onto_cubemap((unsigned)layer % 6,
/* pointer, stride in floats */
&face_coord[0][0], 2,
&blit_ctx->vertices[0][1][0], 8,
FALSE);
} else {
set_texcoords_in_vertices(coord, &blit_ctx->vertices[0][1][0], 8);
}
switch (src_res->base.target) {
case PIPE_TEXTURE_3D:
{
float r = layer / (float)u_minify(src_res->base.depth0,
level);
for (i = 0; i < 4; i++)
blit_ctx->vertices[i][1][2] = r; /*r*/
}
break;
case PIPE_TEXTURE_1D_ARRAY:
for (i = 0; i < 4; i++)
blit_ctx->vertices[i][1][1] = (float) layer; /*t*/
break;
case PIPE_TEXTURE_2D_ARRAY:
for (i = 0; i < 4; i++) {
blit_ctx->vertices[i][1][2] = (float) layer; /*r*/
blit_ctx->vertices[i][1][3] = (float) sample; /*q*/
}
break;
case PIPE_TEXTURE_CUBE_ARRAY:
for (i = 0; i < 4; i++)
blit_ctx->vertices[i][1][3] = (float) ((unsigned)layer / 6); /*w*/
break;
case PIPE_TEXTURE_2D:
for (i = 0; i < 4; i++) {
blit_ctx->vertices[i][1][3] = (float) sample; /*r*/
}
break;
default:;
}
}
#if 0
static void set_dsa_keep_depth_stencil(void)
{
glDisable(GL_STENCIL_TEST);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
}
#endif
static void set_dsa_write_depth_keep_stencil(void)
{
glDisable(GL_STENCIL_TEST);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glDepthMask(GL_TRUE);
}
/* implement blitting using OpenGL. */
void vrend_renderer_blit_gl(struct vrend_context *ctx,
struct vrend_resource *src_res,
struct vrend_resource *dst_res,
const struct pipe_blit_info *info)
{
struct vrend_blitter_ctx *blit_ctx = &vrend_blit_ctx;
GLuint prog_id;
GLuint fs_id;
GLint lret;
GLenum filter;
GLuint pos_loc, tc_loc;
GLuint samp_loc;
boolean has_depth, has_stencil;
bool blit_stencil, blit_depth;
int dst_z;
const struct util_format_description *src_desc =
util_format_description(src_res->base.format);
const struct util_format_description *dst_desc =
util_format_description(dst_res->base.format);
has_depth = util_format_has_depth(src_desc) &&
util_format_has_depth(dst_desc);
has_stencil = util_format_has_stencil(src_desc) &&
util_format_has_stencil(dst_desc);
blit_depth = has_depth && (info->mask & PIPE_MASK_Z);
blit_stencil = has_stencil && (info->mask & PIPE_MASK_S) & 0;
filter = convert_mag_filter(info->filter);
vrend_renderer_init_blit_ctx(blit_ctx);
blitter_set_dst_dim(blit_ctx,
u_minify(dst_res->base.width0, info->dst.level),
u_minify(dst_res->base.height0, info->dst.level));
blitter_set_rectangle(blit_ctx, info->dst.box.x, info->dst.box.y,
info->dst.box.x + info->dst.box.width,
info->dst.box.y + info->dst.box.height, 0);
prog_id = glCreateProgram();
glAttachShader(prog_id, blit_ctx->vs);
if (blit_depth || blit_stencil)
fs_id = blit_get_frag_tex_writedepth(blit_ctx, src_res->base.target, src_res->base.nr_samples);
else
fs_id = blit_get_frag_tex_col(blit_ctx, src_res->base.target, src_res->base.nr_samples);
glAttachShader(prog_id, fs_id);
glLinkProgram(prog_id);
glGetProgramiv(prog_id, GL_LINK_STATUS, &lret);
if (lret == GL_FALSE) {
char infolog[65536];
int len;
glGetProgramInfoLog(prog_id, 65536, &len, infolog);
fprintf(stderr,"got error linking\n%s\n", infolog);
/* dump shaders */
glDeleteProgram(prog_id);
return;
}
glUseProgram(prog_id);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, blit_ctx->fb_id);
vrend_fb_bind_texture(dst_res, 0, info->dst.level, info->dst.box.z);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glBindTexture(src_res->target, src_res->id);
glTexParameteri(src_res->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(src_res->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(src_res->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glTexParameteri(src_res->target, GL_TEXTURE_BASE_LEVEL, info->src.level);
glTexParameteri(src_res->target, GL_TEXTURE_MAX_LEVEL, info->src.level);
glTexParameterf(src_res->target, GL_TEXTURE_MAG_FILTER, filter);
glTexParameterf(src_res->target, GL_TEXTURE_MIN_FILTER, filter);
pos_loc = glGetAttribLocation(prog_id, "arg0");
tc_loc = glGetAttribLocation(prog_id, "arg1");
samp_loc = glGetUniformLocation(prog_id, "samp");
glUniform1i(samp_loc, 0);
glVertexAttribPointer(pos_loc, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(float), 0);
glVertexAttribPointer(tc_loc, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(4 * sizeof(float)));
glEnableVertexAttribArray(pos_loc);
glEnableVertexAttribArray(tc_loc);
set_dsa_write_depth_keep_stencil();
for (dst_z = 0; dst_z < info->dst.box.depth; dst_z++) {
float dst2src_scale = info->src.box.depth / (float)info->dst.box.depth;
float dst_offset = ((info->src.box.depth - 1) -
(info->dst.box.depth - 1) * dst2src_scale) * 0.5;
float src_z = (dst_z + dst_offset) * dst2src_scale;
glBindFramebuffer(GL_FRAMEBUFFER_EXT, blit_ctx->fb_id);
vrend_fb_bind_texture(dst_res, 0, info->dst.level, dst_z);
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
blitter_set_texcoords(blit_ctx, src_res, info->src.level,
info->src.box.z + src_z, 0,
info->src.box.x, info->src.box.y,
info->src.box.x + info->src.box.width,
info->src.box.y + info->src.box.height);
glBufferData(GL_ARRAY_BUFFER, sizeof(blit_ctx->vertices), blit_ctx->vertices, GL_STATIC_DRAW);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
}

@ -0,0 +1,45 @@
#ifndef VREND_BLITTER
#define VREND_BLITTER
/* shaders for blitting */
static const char *vs_passthrough = {
"#version 130\n"
"in vec4 arg0;\n"
"in vec4 arg1;\n"
"out vec4 tc;\n"
"void main() {\n"
" gl_Position = arg0;\n"
" tc = arg1;\n"
"}\n"
};
static const char *fs_texfetch_col = {
"#version 130\n"
"uniform sampler%s samp;\n"
"in vec4 tc;\n"
"void main() {\n"
" gl_FragColor = texture(samp, tc%s)%s;\n"
"}\n"
};
static const char *fs_texfetch_ds = {
"#version 130\n"
"uniform sampler%s samp;\n"
"in vec4 tc;\n"
"void main() {\n"
" gl_FragDepth = float(texture(samp, tc%s).x);\n"
"}\n"
};
static const char *fs_texfetch_ds_msaa = {
"#version 130\n"
"#extension GL_ARB_texture_multisample : enable\n"
"uniform sampler%s samp;\n"
"in vec4 tc;\n"
"void main() {\n"
" gl_FragDepth = float(texelFetch(samp, tc%s, tc.z).x);\n"
"}\n"
};
#endif

File diff suppressed because it is too large Load Diff

@ -1,10 +1,33 @@
/**************************************************************************
*
* Copyright (C) 2014 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 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 <epoxy/gl.h>
#include "graw_renderer.h"
#include "vrend_renderer.h"
#include "util/u_memory.h"
#include "util/u_format.h"
/* fill the format table */
static struct grend_format_table base_rgba_formats[] =
static struct vrend_format_table base_rgba_formats[] =
{
{ VIRGL_FORMAT_B8G8R8X8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, 0 },
{ VIRGL_FORMAT_B8G8R8A8_UNORM, GL_RGBA8, GL_BGRA, GL_UNSIGNED_BYTE, 0 },
@ -30,7 +53,7 @@ static struct grend_format_table base_rgba_formats[] =
{ VIRGL_FORMAT_R16G16B16A16_UNORM, GL_RGBA16, GL_RGBA, GL_UNSIGNED_SHORT },
};
static struct grend_format_table base_depth_formats[] =
static struct vrend_format_table base_depth_formats[] =
{
{ VIRGL_FORMAT_Z16_UNORM, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0 },
{ VIRGL_FORMAT_Z32_UNORM, GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0 },
@ -41,7 +64,7 @@ static struct grend_format_table base_depth_formats[] =
{ VIRGL_FORMAT_Z32_FLOAT_S8X24_UINT, GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV},
};
static struct grend_format_table base_la_formats[] = {
static struct vrend_format_table base_la_formats[] = {
{ VIRGL_FORMAT_A8_UNORM, GL_ALPHA8, GL_ALPHA, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_L8_UNORM, GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_L8A8_UNORM, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
@ -50,14 +73,14 @@ static struct grend_format_table base_la_formats[] = {
{ VIRGL_FORMAT_L16A16_UNORM, GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, GL_UNSIGNED_SHORT },
};
static struct grend_format_table rg_base_formats[] = {
{ VIRGL_FORMAT_R8_UNORM, GL_RED, GL_RED, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_R8G8_UNORM, GL_RG, GL_RG, GL_UNSIGNED_BYTE },
static struct vrend_format_table rg_base_formats[] = {
{ VIRGL_FORMAT_R8_UNORM, GL_R8, GL_RED, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_R8G8_UNORM, GL_RG8, GL_RG, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_R16_UNORM, GL_R16, GL_RED, GL_UNSIGNED_SHORT },
{ VIRGL_FORMAT_R16G16_UNORM, GL_RG16, GL_RG, GL_UNSIGNED_SHORT },
};
static struct grend_format_table integer_base_formats[] = {
static struct vrend_format_table integer_base_formats[] = {
{ VIRGL_FORMAT_R8G8B8A8_UINT, GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_R8G8B8A8_SINT, GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE },
@ -68,7 +91,7 @@ static struct grend_format_table integer_base_formats[] = {
{ VIRGL_FORMAT_R32G32B32A32_SINT, GL_RGBA32I, GL_RGBA_INTEGER, GL_INT },
};
static struct grend_format_table integer_3comp_formats[] = {
static struct vrend_format_table integer_3comp_formats[] = {
{ VIRGL_FORMAT_R8G8B8_UINT, GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_R8G8B8_SINT, GL_RGB8I, GL_RGB_INTEGER, GL_BYTE },
{ VIRGL_FORMAT_R16G16B16_UINT, GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT },
@ -77,12 +100,12 @@ static struct grend_format_table integer_3comp_formats[] = {
{ VIRGL_FORMAT_R32G32B32_SINT, GL_RGB32I, GL_RGB_INTEGER, GL_INT },
};
static struct grend_format_table float_base_formats[] = {
static struct vrend_format_table float_base_formats[] = {
{ VIRGL_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT },
{ VIRGL_FORMAT_R32G32B32A32_FLOAT, GL_RGBA32F, GL_RGBA, GL_FLOAT },
};
static struct grend_format_table float_la_formats[] = {
static struct vrend_format_table float_la_formats[] = {
{ VIRGL_FORMAT_A16_FLOAT, GL_ALPHA16F_ARB, GL_ALPHA, GL_HALF_FLOAT },
{ VIRGL_FORMAT_L16_FLOAT, GL_LUMINANCE16F_ARB, GL_LUMINANCE, GL_HALF_FLOAT },
{ VIRGL_FORMAT_L16A16_FLOAT, GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT },
@ -92,7 +115,7 @@ static struct grend_format_table float_la_formats[] = {
{ VIRGL_FORMAT_L32A32_FLOAT, GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE_ALPHA, GL_FLOAT },
};
static struct grend_format_table integer_rg_formats[] = {
static struct vrend_format_table integer_rg_formats[] = {
{ VIRGL_FORMAT_R8_UINT, GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_R8G8_UINT, GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_R8_SINT, GL_R8I, GL_RED_INTEGER, GL_BYTE },
@ -109,20 +132,20 @@ static struct grend_format_table integer_rg_formats[] = {
{ VIRGL_FORMAT_R32G32_SINT, GL_RG32I, GL_RG_INTEGER, GL_INT },
};
static struct grend_format_table float_rg_formats[] = {
static struct vrend_format_table float_rg_formats[] = {
{ VIRGL_FORMAT_R16_FLOAT, GL_R16F, GL_RED, GL_HALF_FLOAT },
{ VIRGL_FORMAT_R16G16_FLOAT, GL_RG16F, GL_RG, GL_HALF_FLOAT },
{ VIRGL_FORMAT_R32_FLOAT, GL_R32F, GL_RED, GL_FLOAT },
{ VIRGL_FORMAT_R32G32_FLOAT, GL_RG32F, GL_RG, GL_FLOAT },
};
static struct grend_format_table float_3comp_formats[] = {
static struct vrend_format_table float_3comp_formats[] = {
{ VIRGL_FORMAT_R16G16B16_FLOAT, GL_RGB16F, GL_RGB, GL_HALF_FLOAT },
{ VIRGL_FORMAT_R32G32B32_FLOAT, GL_RGB32F, GL_RGB, GL_FLOAT },
};
static struct grend_format_table integer_la_formats[] = {
static struct vrend_format_table integer_la_formats[] = {
{ VIRGL_FORMAT_A8_UINT, GL_ALPHA8UI_EXT, GL_ALPHA_INTEGER, GL_UNSIGNED_BYTE},
{ VIRGL_FORMAT_L8_UINT, GL_LUMINANCE8UI_EXT, GL_LUMINANCE_INTEGER_EXT, GL_UNSIGNED_BYTE},
{ VIRGL_FORMAT_L8A8_UINT, GL_LUMINANCE_ALPHA8UI_EXT, GL_LUMINANCE_ALPHA_INTEGER_EXT, GL_UNSIGNED_BYTE},
@ -149,12 +172,12 @@ static struct grend_format_table integer_la_formats[] = {
};
static struct grend_format_table snorm_formats[] = {
static struct vrend_format_table snorm_formats[] = {
{ VIRGL_FORMAT_R8_SNORM, GL_R8_SNORM, GL_RED, GL_BYTE },
{ VIRGL_FORMAT_R8G8_SNORM, GL_RG8_SNORM, GL_RG, GL_BYTE },
{ VIRGL_FORMAT_R8G8B8A8_SNORM, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE },
{ VIRGL_FORMAT_R8G8B8X8_SNORM, GL_RGBA8_SNORM, GL_RGB, GL_BYTE },
{ VIRGL_FORMAT_R8G8B8X8_SNORM, GL_RGBA8_SNORM, GL_RGBA, GL_BYTE },
{ VIRGL_FORMAT_R16_SNORM, GL_R16_SNORM, GL_RED, GL_SHORT },
{ VIRGL_FORMAT_R16G16_SNORM, GL_RG16_SNORM, GL_RG, GL_SHORT },
@ -163,7 +186,7 @@ static struct grend_format_table snorm_formats[] = {
{ VIRGL_FORMAT_R16G16B16X16_SNORM, GL_RGBA16_SNORM, GL_RGBA, GL_SHORT },
};
static struct grend_format_table snorm_la_formats[] = {
static struct vrend_format_table snorm_la_formats[] = {
{ VIRGL_FORMAT_A8_SNORM, GL_ALPHA8_SNORM, GL_ALPHA, GL_BYTE },
{ VIRGL_FORMAT_L8_SNORM, GL_LUMINANCE8_SNORM, GL_LUMINANCE, GL_BYTE },
{ VIRGL_FORMAT_L8A8_SNORM, GL_LUMINANCE8_ALPHA8_SNORM, GL_LUMINANCE_ALPHA, GL_BYTE },
@ -172,21 +195,21 @@ static struct grend_format_table snorm_la_formats[] = {
{ VIRGL_FORMAT_L16A16_SNORM, GL_LUMINANCE16_ALPHA16_SNORM, GL_LUMINANCE_ALPHA, GL_SHORT },
};
static struct grend_format_table dxtn_formats[] = {
static struct vrend_format_table dxtn_formats[] = {
{ VIRGL_FORMAT_DXT1_RGB, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_DXT1_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_DXT3_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_DXT5_RGBA, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE },
};
static struct grend_format_table dxtn_srgb_formats[] = {
static struct vrend_format_table dxtn_srgb_formats[] = {
{ VIRGL_FORMAT_DXT1_SRGB, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_RGB, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_DXT1_SRGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_DXT3_SRGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_DXT5_SRGBA, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE },
};
static struct grend_format_table rgtc_formats[] = {
static struct vrend_format_table rgtc_formats[] = {
{ VIRGL_FORMAT_RGTC1_UNORM, GL_COMPRESSED_RED_RGTC1, GL_RED, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_RGTC1_SNORM, GL_COMPRESSED_SIGNED_RED_RGTC1, GL_RED, GL_BYTE },
@ -194,7 +217,7 @@ static struct grend_format_table rgtc_formats[] = {
{ VIRGL_FORMAT_RGTC2_SNORM, GL_COMPRESSED_SIGNED_RG_RGTC2, GL_RG, GL_BYTE },
};
static struct grend_format_table srgb_formats[] = {
static struct vrend_format_table srgb_formats[] = {
{ VIRGL_FORMAT_B8G8R8X8_SRGB, GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE },
{ VIRGL_FORMAT_B8G8R8A8_SRGB, GL_SRGB8_ALPHA8, GL_BGRA, GL_UNSIGNED_BYTE },
@ -204,21 +227,21 @@ static struct grend_format_table srgb_formats[] = {
{ VIRGL_FORMAT_L8A8_SRGB, GL_SLUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
};
static struct grend_format_table bit10_formats[] = {
static struct vrend_format_table bit10_formats[] = {
{ VIRGL_FORMAT_B10G10R10X2_UNORM, GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV },
{ VIRGL_FORMAT_B10G10R10A2_UNORM, GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV },
{ VIRGL_FORMAT_B10G10R10A2_UINT, GL_RGB10_A2UI, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV },
{ VIRGL_FORMAT_B10G10R10A2_UINT, GL_RGB10_A2UI, GL_BGRA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV },
};
static struct grend_format_table packed_float_formats[] = {
static struct vrend_format_table packed_float_formats[] = {
{ VIRGL_FORMAT_R11G11B10_FLOAT, GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV},
};
static struct grend_format_table exponent_float_formats[] = {
static struct vrend_format_table exponent_float_formats[] = {
{ VIRGL_FORMAT_R9G9B9E5_FLOAT, GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV},
};
static void vrend_add_formats(struct grend_format_table *table, int num_entries)
static void vrend_add_formats(struct vrend_format_table *table, int num_entries)
{
int i;
uint32_t binding = 0;
@ -234,11 +257,39 @@ static void vrend_add_formats(struct grend_format_table *table, int num_entries)
glBindFramebuffer(GL_FRAMEBUFFER, fb_id);
glTexImage2D(GL_TEXTURE_2D, 0, table[i].internalformat, 32, 32, 0, table[i].glformat, table[i].gltype, NULL);
status = glGetError();
if (status == GL_INVALID_VALUE) {
struct vrend_format_table *entry = NULL;
uint8_t swizzle[4];
binding = VREND_BIND_SAMPLER | VREND_BIND_NEED_SWIZZLE;
switch (table[i].format) {
case PIPE_FORMAT_A8_UNORM:
entry = &rg_base_formats[0];
swizzle[0] = swizzle[1] = swizzle[2] = PIPE_SWIZZLE_ZERO;
swizzle[3] = PIPE_SWIZZLE_RED;
break;
case PIPE_FORMAT_A16_UNORM:
entry = &rg_base_formats[2];
swizzle[0] = swizzle[1] = swizzle[2] = PIPE_SWIZZLE_ZERO;
swizzle[3] = PIPE_SWIZZLE_RED;
break;
default:
break;
}
if (entry) {
vrend_insert_format_swizzle(table[i].format, entry, binding, swizzle);
}
glDeleteTextures(1, &tex_id);
glDeleteFramebuffers(1, &fb_id);
continue;
}
if (util_format_is_depth_or_stencil(table[i].format)) {
GLenum attachment;
if (table[i].format == PIPE_FORMAT_Z24X8_UNORM || table[i].format == PIPE_FORMAT_Z32_UNORM || table[i].format == PIPE_FORMAT_Z16_UNORM || table[i].format == PIPE_FORMAT_Z32_FLOAT)
if (table[i].format == VIRGL_FORMAT_Z24X8_UNORM || table[i].format == VIRGL_FORMAT_Z32_UNORM || table[i].format == VIRGL_FORMAT_Z16_UNORM || table[i].format == VIRGL_FORMAT_Z32_FLOAT)
attachment = GL_DEPTH_ATTACHMENT;
else
attachment = GL_DEPTH_STENCIL_ATTACHMENT;
@ -253,13 +304,13 @@ static void vrend_add_formats(struct grend_format_table *table, int num_entries)
}
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
binding = 0;
binding = VREND_BIND_SAMPLER;
if (status == GL_FRAMEBUFFER_COMPLETE)
binding |= (is_depth ? VREND_BIND_DEPTHSTENCIL : VREND_BIND_RENDER);
glDeleteTextures(1, &tex_id);
glDeleteFramebuffers(1, &fb_id);
grend_insert_format(&table[i], binding);
vrend_insert_format(&table[i], binding);
}
}

@ -0,0 +1,40 @@
/**************************************************************************
*
* Copyright (C) 2014 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 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.
*
**************************************************************************/
#ifndef VREND_IOV_H
#define VREND_IOV_H
#include <sys/uio.h>
typedef void (*iov_cb)(void *cookie, unsigned int doff, void *src, int len);
size_t vrend_get_iovec_size(const struct iovec *iov, int iovlen);
size_t vrend_read_from_iovec(const struct iovec *iov, int iov_cnt,
size_t offset, char *buf, size_t bytes);
size_t vrend_write_to_iovec(const struct iovec *iov, int iov_cnt,
size_t offset, const char *buf, size_t bytes);
size_t vrend_read_from_iovec_cb(const struct iovec *iov, int iov_cnt,
size_t offset, size_t bytes, iov_cb iocb, void *cookie);
#endif

@ -1,4 +1,27 @@
#include <stdio.h>
/**************************************************************************
*
* Copyright (C) 2014 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 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 "util/u_pointer.h"
#include "util/u_memory.h"
#include "util/u_hash_table.h"
@ -38,6 +61,7 @@ struct vrend_object {
enum virgl_object_type type;
uint32_t handle;
void *data;
bool free_data;
};
struct util_hash_table *vrend_object_init_ctx_table(void)
@ -49,11 +73,13 @@ struct util_hash_table *vrend_object_init_ctx_table(void)
static void vrend_object_free(struct vrend_object *obj)
{
if (obj_types[obj->type].unref)
obj_types[obj->type].unref(obj->data);
else {
/* for objects with no callback just free them */
free(obj->data);
if (obj->free_data) {
if (obj_types[obj->type].unref)
obj_types[obj->type].unref(obj->data);
else {
/* for objects with no callback just free them */
free(obj->data);
}
}
free(obj);
}
@ -89,8 +115,8 @@ void vrend_object_fini_resource_table(void)
}
uint32_t
vrend_object_insert(struct util_hash_table *handle_hash,
void *data, uint32_t length, uint32_t handle, enum virgl_object_type type)
vrend_object_insert_nofree(struct util_hash_table *handle_hash,
void *data, uint32_t length, uint32_t handle, enum virgl_object_type type, bool free_data)
{
struct vrend_object *obj = CALLOC_STRUCT(vrend_object);
@ -99,10 +125,19 @@ vrend_object_insert(struct util_hash_table *handle_hash,
obj->handle = handle;
obj->data = data;
obj->type = type;
obj->free_data = free_data;
util_hash_table_set(handle_hash, intptr_to_pointer(obj->handle), obj);
return obj->handle;
}
uint32_t
vrend_object_insert(struct util_hash_table *handle_hash,
void *data, uint32_t length, uint32_t handle, enum virgl_object_type type)
{
return vrend_object_insert_nofree(handle_hash, data, length,
handle, type, true);
}
void
vrend_object_remove(struct util_hash_table *handle_hash,
uint32_t handle, enum virgl_object_type type)
@ -133,7 +168,7 @@ void *vrend_object_lookup(struct util_hash_table *handle_hash,
return obj->data;
}
void *vrend_resource_insert(void *data, uint32_t length, uint32_t handle)
int vrend_resource_insert(void *data, uint32_t length, uint32_t handle)
{
struct vrend_object *obj = CALLOC_STRUCT(vrend_object);
@ -164,19 +199,3 @@ void *vrend_resource_lookup(uint32_t handle, uint32_t ctx_id)
return NULL;
return obj->data;
}
static enum pipe_error dump_cb(void *key, void *value, void *data)
{
struct vrend_object *obj = value;
fprintf(stderr, "%p: %d %d\n", key, obj->type, obj->handle);
graw_renderer_dump_resource(obj->data);
return PIPE_OK;
}
void vrend_object_dumb_ctx_table(struct util_hash_table *ctx_hash)
{
if (!ctx_hash)
return;
util_hash_table_foreach(ctx_hash, dump_cb, NULL);
}

@ -1,3 +1,27 @@
/**************************************************************************
*
* Copyright (C) 2014 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 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.
*
**************************************************************************/
#ifndef VREND_OBJECT_H
#define VREND_OBJECT_H
@ -6,22 +30,22 @@
void vrend_object_init_resource_table(void);
void vrend_object_fini_resource_table(void);
struct grend_context;
struct util_hash_table *vrend_object_init_ctx_table(void);
void vrend_object_fini_ctx_table(struct util_hash_table *ctx_hash);
void vrend_object_remove(struct util_hash_table *handle_hash, uint32_t handle, enum virgl_object_type obj);
void *vrend_object_lookup(struct util_hash_table *handle_hash, uint32_t handle, enum virgl_object_type obj);
uint32_t vrend_object_insert(struct util_hash_table *handle_hash, void *data, uint32_t length, uint32_t handle, enum virgl_object_type type);
uint32_t vrend_object_insert_nofree(struct util_hash_table *handle_hash,
void *data, uint32_t length,
uint32_t handle,
enum virgl_object_type type,
bool free_data);
/* resources are global */
void *vrend_resource_insert(void *data, uint32_t length, uint32_t handle);
int vrend_resource_insert(void *data, uint32_t length, uint32_t handle);
void vrend_resource_remove(uint32_t handle);
void *vrend_resource_lookup(uint32_t handle, uint32_t ctx_id);
void vrend_object_set_destroy_callback(int type, void (*cb)(void *));
void vrend_object_dumb_ctx_table(struct util_hash_table *ctx_hash);
void graw_renderer_dump_resource(void *data);
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,391 @@
/**************************************************************************
*
* Copyright (C) 2014 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 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.
*
**************************************************************************/
#ifndef VREND_RENDERER_H
#define VREND_RENDERER_H
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "virgl_protocol.h"
#include "vrend_iov.h"
#include "virgl_hw.h"
typedef void *virgl_gl_context;
typedef void *virgl_gl_drawable;
struct virgl_gl_ctx_param {
bool shared;
int major_ver;
int minor_ver;
};
extern int vrend_dump_shaders;
struct vrend_context;
struct vrend_resource {
struct pipe_resource base;
GLuint id;
GLenum target;
/* fb id if we need to readback this resource */
GLuint readback_fb_id;
GLuint readback_fb_level;
GLuint readback_fb_z;
void *ptr;
GLuint handle;
struct iovec *iov;
uint32_t num_iovs;
boolean y_0_top;
boolean scannedout;
GLuint tbo_tex_id;/* tbos have two ids to track */
};
/* assume every format is sampler friendly */
#define VREND_BIND_SAMPLER (1 << 0)
#define VREND_BIND_RENDER (1 << 1)
#define VREND_BIND_DEPTHSTENCIL (1 << 2)
#define VREND_BIND_NEED_SWIZZLE (1 << 28)
struct vrend_format_table {
enum virgl_formats format;
GLenum internalformat;
GLenum glformat;
GLenum gltype;
uint32_t bindings;
int flags;
uint8_t swizzle[4];
};
struct vrend_if_cbs {
void (*write_fence)(unsigned fence_id);
virgl_gl_context (*create_gl_context)(int scanout, struct virgl_gl_ctx_param *params);
void (*destroy_gl_context)(virgl_gl_context ctx);
int (*make_current)(int scanout, virgl_gl_context ctx);
};
void vrend_renderer_init(struct vrend_if_cbs *cbs);
void vrend_insert_format(struct vrend_format_table *entry, uint32_t bindings);
void vrend_insert_format_swizzle(int override_format, struct vrend_format_table *entry, uint32_t bindings, uint8_t swizzle[4]);
int vrend_create_shader(struct vrend_context *ctx,
uint32_t handle,
const struct pipe_shader_state *vs,
int type);
void vrend_bind_vs(struct vrend_context *ctx,
uint32_t handle);
void vrend_bind_gs(struct vrend_context *ctx,
uint32_t handle);
void vrend_bind_fs(struct vrend_context *ctx,
uint32_t handle);
void vrend_bind_vs_so(struct vrend_context *ctx,
uint32_t handle);
void vrend_clear(struct vrend_context *ctx,
unsigned buffers,
const union pipe_color_union *color,
double depth, unsigned stencil);
void vrend_draw_vbo(struct vrend_context *ctx,
const struct pipe_draw_info *info);
void vrend_set_framebuffer_state(struct vrend_context *ctx,
uint32_t nr_cbufs, uint32_t surf_handle[8],
uint32_t zsurf_handle);
void vrend_flush(struct vrend_context *ctx);
void vrend_flush_frontbuffer(uint32_t res_handle);
struct vrend_context *vrend_create_context(int id, uint32_t nlen, const char *debug_name);
bool vrend_destroy_context(struct vrend_context *ctx);
void vrend_renderer_context_create(uint32_t handle, uint32_t nlen, const char *name);
void vrend_renderer_context_create_internal(uint32_t handle, uint32_t nlen, const char *name);
void vrend_renderer_context_destroy(uint32_t handle);
struct vrend_renderer_resource_create_args {
uint32_t handle;
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 flags;
};
int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *args, struct iovec *iov, uint32_t num_iovs);
void vrend_renderer_resource_unref(uint32_t handle);
int vrend_create_surface(struct vrend_context *ctx,
uint32_t handle,
uint32_t res_handle, uint32_t format,
uint32_t val0, uint32_t val1);
int vrend_create_sampler_view(struct vrend_context *ctx,
uint32_t handle,
uint32_t res_handle, uint32_t format,
uint32_t val0, uint32_t val1, uint32_t swizzle_packed);
int vrend_create_sampler_state(struct vrend_context *ctx,
uint32_t handle,
struct pipe_sampler_state *templ);
int vrend_create_so_target(struct vrend_context *ctx,
uint32_t handle,
uint32_t res_handle,
uint32_t buffer_offset,
uint32_t buffer_size);
void vrend_set_streamout_targets(struct vrend_context *ctx,
uint32_t append_bitmask,
uint32_t num_targets,
uint32_t *handles);
int vrend_create_vertex_elements_state(struct vrend_context *ctx,
uint32_t handle,
unsigned num_elements,
const struct pipe_vertex_element *elements);
void vrend_bind_vertex_elements_state(struct vrend_context *ctx,
uint32_t handle);
void vrend_set_single_vbo(struct vrend_context *ctx,
int index,
uint32_t stride,
uint32_t buffer_offset,
uint32_t res_handle);
void vrend_set_num_vbo(struct vrend_context *ctx,
int num_vbo);
void vrend_transfer_inline_write(struct vrend_context *ctx,
uint32_t res_handle,
unsigned level,
unsigned usage,
const struct pipe_box *box,
const void *data,
unsigned stride,
unsigned layer_stride);
void vrend_set_viewport_state(struct vrend_context *ctx,
const struct pipe_viewport_state *state);
void vrend_set_num_sampler_views(struct vrend_context *ctx,
uint32_t shader_type,
uint32_t start_slot,
int num_sampler_views);
void vrend_set_single_sampler_view(struct vrend_context *ctx,
uint32_t shader_type,
int index,
uint32_t res_handle);
void vrend_object_bind_blend(struct vrend_context *ctx,
uint32_t handle);
void vrend_object_bind_dsa(struct vrend_context *ctx,
uint32_t handle);
void vrend_object_bind_rasterizer(struct vrend_context *ctx,
uint32_t handle);
void vrend_bind_sampler_states(struct vrend_context *ctx,
uint32_t shader_type,
uint32_t start_slot,
uint32_t num_states,
uint32_t *handles);
void vrend_set_index_buffer(struct vrend_context *ctx,
uint32_t res_handle,
uint32_t index_size,
uint32_t offset);
void vrend_renderer_transfer_write_iov(uint32_t handle,
uint32_t ctx_id,
int level,
uint32_t stride,
uint32_t layer_stride,
struct pipe_box *box,
uint64_t offset,
struct iovec *iovec,
unsigned int iovec_cnt);
void vrend_renderer_resource_copy_region(struct vrend_context *ctx,
uint32_t dst_handle, uint32_t dst_level,
uint32_t dstx, uint32_t dsty, uint32_t dstz,
uint32_t src_handle, uint32_t src_level,
const struct pipe_box *src_box);
void vrend_renderer_blit(struct vrend_context *ctx,
uint32_t dst_handle, uint32_t src_handle,
const struct pipe_blit_info *info);
void vrend_renderer_transfer_send_iov(uint32_t handle, uint32_t ctx_id,
uint32_t level, uint32_t stride,
uint32_t layer_stride,
struct pipe_box *box,
uint64_t offset, struct iovec *iov,
int iovec_cnt);
void vrend_set_stencil_ref(struct vrend_context *ctx, struct pipe_stencil_ref *ref);
void vrend_set_blend_color(struct vrend_context *ctx, struct pipe_blend_color *color);
void vrend_set_scissor_state(struct vrend_context *ctx, struct pipe_scissor_state *ss);
void vrend_set_polygon_stipple(struct vrend_context *ctx, struct pipe_poly_stipple *ps);
void vrend_set_clip_state(struct vrend_context *ctx, struct pipe_clip_state *ucp);
void vrend_set_sample_mask(struct vrend_context *ctx, unsigned sample_mask);
void vrend_set_constants(struct vrend_context *ctx,
uint32_t shader,
uint32_t index,
uint32_t num_constant,
float *data);
void vrend_set_uniform_buffer(struct vrend_context *ctx, uint32_t shader,
uint32_t index, uint32_t offset, uint32_t length,
uint32_t res_handle);
void vrend_transfer_write_return(void *data, uint32_t bytes, uint64_t offset,
struct iovec *iov, int iovec_cnt);
void vrend_transfer_write_tex_return(struct pipe_resource *res,
struct pipe_box *box,
uint32_t level,
uint32_t dst_stride,
uint64_t offset,
struct iovec *iov,
int num_iovs,
void *myptr, int size, int invert);
void vrend_renderer_fini(void);
void vrend_decode_block(uint32_t ctx_id, uint32_t *block, int ndw);
struct vrend_context *vrend_lookup_renderer_ctx(uint32_t ctx_id);
int vrend_renderer_create_fence(int client_fence_id, uint32_t ctx_id);
void vrend_renderer_check_fences(void);
void vrend_renderer_check_queries(void);
void vrend_stop_current_queries(void);
boolean vrend_hw_switch_context(struct vrend_context *ctx, boolean now);
uint32_t vrend_renderer_object_insert(struct vrend_context *ctx, void *data,
uint32_t size, uint32_t handle, enum virgl_object_type type);
void vrend_renderer_object_destroy(struct vrend_context *ctx, uint32_t handle);
int vrend_create_query(struct vrend_context *ctx, uint32_t handle,
uint32_t query_type, uint32_t res_handle,
uint32_t offset);
void vrend_begin_query(struct vrend_context *ctx, uint32_t handle);
void vrend_end_query(struct vrend_context *ctx, uint32_t handle);
void vrend_get_query_result(struct vrend_context *ctx, uint32_t handle,
uint32_t wait);
void vrend_render_condition(struct vrend_context *ctx,
uint32_t handle,
boolean condtion,
uint mode);
void *vrend_renderer_get_cursor_contents(uint32_t res_handle, uint32_t *width, uint32_t *height);
void vrend_use_program(GLuint program_id);
void vrend_blend_enable(GLboolean blend_enable);
void vrend_depth_test_enable(GLboolean depth_test_enable);
void vrend_bind_va(GLuint vaoid);
int vrend_renderer_flush_buffer_res(struct vrend_resource *res,
struct pipe_box *box);
void vrend_renderer_fill_caps(uint32_t set, uint32_t version,
union virgl_caps *caps);
GLint64 vrend_renderer_get_timestamp(void);
/* formats */
void vrend_build_format_list(void);
int vrend_renderer_resource_attach_iov(int res_handle, struct iovec *iov,
int num_iovs);
void vrend_renderer_resource_detach_iov(int res_handle,
struct iovec **iov_p,
int *num_iovs_p);
void vrend_renderer_resource_destroy(struct vrend_resource *res);
static INLINE void
vrend_resource_reference(struct vrend_resource **ptr, struct vrend_resource *tex)
{
struct vrend_resource *old_tex = *ptr;
if (pipe_reference(&(*ptr)->base.reference, &tex->base.reference))
vrend_renderer_resource_destroy(old_tex);
*ptr = tex;
}
void vrend_renderer_force_ctx_0(void);
void vrend_renderer_get_rect(int resource_id, struct iovec *iov, unsigned int num_iovs,
uint32_t offset, int x, int y, int width, int height);
void vrend_renderer_attach_res_ctx(int ctx_id, int resource_id);
void vrend_renderer_detach_res_ctx(int ctx_id, int resource_id);
struct vrend_renderer_resource_info {
uint32_t handle;
uint32_t format;
uint32_t width;
uint32_t height;
uint32_t depth;
uint32_t flags;
uint32_t tex_id;
uint32_t stride;
};
int vrend_renderer_resource_get_info(int res_handle,
struct vrend_renderer_resource_info *info);
#define VREND_CAP_SET 1
void vrend_renderer_get_cap_set(uint32_t cap_set, uint32_t *max_ver,
uint32_t *max_size);
void vrend_renderer_create_sub_ctx(struct vrend_context *ctx, int sub_ctx_id);
void vrend_renderer_destroy_sub_ctx(struct vrend_context *ctx, int sub_ctx_id);
void vrend_renderer_set_sub_ctx(struct vrend_context *ctx, int sub_ctx_id);
void vrend_report_buffer_error(struct vrend_context *ctx, int cmd);
void vrend_fb_bind_texture(struct vrend_resource *res,
int idx,
uint32_t level, uint32_t layer);
bool vrend_is_ds_format(enum virgl_formats format);
const char *vrend_shader_samplertypeconv(int sampler_type, int *is_shad);
/* blitter interface */
void vrend_renderer_blit_gl(struct vrend_context *ctx,
struct vrend_resource *src_res,
struct vrend_resource *dst_res,
const struct pipe_blit_info *info);
void vrend_renderer_reset(void);
void vrend_decode_reset(void);
#define VREND_GL_VER_MAJOR 3
#define VREND_GL_VER_MINOR 1
extern struct vrend_if_cbs *vrend_clicbs;
#endif

@ -1,3 +1,26 @@
/**************************************************************************
*
* Copyright (C) 2014 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 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.
*
**************************************************************************/
/* helper library for qemu local renderers like SDL / GTK
flushes the given texture to the frontbuffer */
#include <epoxy/gl.h>
@ -31,6 +54,7 @@ void virgl_helper_scanout_info(int idx,
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
GL_TEXTURE_2D, 0, 0);
glDeleteFramebuffers(1, &frontbuf[idx].fb_id);
frontbuf[idx].fb_id = 0;
}
return;
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,82 @@
/**************************************************************************
*
* Copyright (C) 2014 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 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.
*
**************************************************************************/
#ifndef VREND_SHADER_H
#define VREND_SHADER_H
#include "pipe/p_state.h"
/* need to store patching info for interpolation */
struct vrend_interp_info {
int semantic_name;
int semantic_index;
int interpolate;
};
struct vrend_shader_info {
uint32_t samplers_used_mask;
int num_consts;
int num_inputs;
int num_interps;
int num_outputs;
int num_ubos;
int num_ucp;
int glsl_ver;
uint32_t shadow_samp_mask;
struct pipe_stream_output_info so_info;
struct vrend_interp_info *interpinfo;
int gs_out_prim;
char **so_names;
};
struct vrend_shader_key {
uint32_t coord_replace;
boolean invert_fs_origin;
boolean pstipple_tex;
boolean add_alpha_test;
boolean color_two_side;
uint8_t alpha_test;
uint8_t clip_plane_enable;
float alpha_ref_val;
boolean gs_present;
boolean flatshade;
};
struct vrend_shader_cfg {
int glsl_version;
bool use_core_profile;
};
boolean vrend_patch_vertex_shader_interpolants(char *program,
struct vrend_shader_info *vs_info,
struct vrend_shader_info *fs_info,
bool is_gs, bool flatshade);
char *vrend_convert_shader(struct vrend_shader_cfg *cfg,
const struct tgsi_token *tokens,
struct vrend_shader_key *key,
struct vrend_shader_info *sinfo);
const char *vrend_shader_samplertypeconv(int sampler_type, int *is_shad);
#endif
Loading…
Cancel
Save