vrend: extract functions from vrend_renderer_resource_create

Two functions are extracted from vrend_renderer_resource_create to
make it possible to allocate a texture resource without adding too much
code duplication:

vrend_renderer_resource_copy_args:
   copies all required arguments from the args struct into the
   already allocated resource

vrend_renderer_resource_allocate_texture:
   Allocate a texture using the parameters in the given resource struct

v2: * instead of extracting the complete allocation also including buffers,
      only extract the parts that copy the parameters and allocate the texture
    * use latest upstream that also includes texture storage objects

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Tested-by: Jakob Bornecrantz <jakob@collabora.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
macos/master
Gert Wollny 7 years ago committed by Dave Airlie
parent 041c6f5473
commit 167e3ccbb9
  1. 226
      src/vrend_renderer.c

@ -4772,23 +4772,14 @@ static void vrend_create_buffer(struct vrend_resource *gr, uint32_t width)
gr->is_buffer = true;
}
int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *args, struct iovec *iov, uint32_t num_iovs)
static inline void
vrend_renderer_resource_copy_args(struct vrend_renderer_resource_create_args *args,
struct vrend_resource *gr)
{
struct vrend_resource *gr;
uint32_t level;
int ret;
ret = check_resource_valid(args);
if (ret)
return EINVAL;
gr = (struct vrend_resource *)CALLOC_STRUCT(vrend_texture);
if (!gr)
return ENOMEM;
assert(gr);
assert(args);
gr->handle = args->handle;
gr->iov = iov;
gr->num_iovs = num_iovs;
gr->base.width0 = args->width;
gr->base.height0 = args->height;
gr->base.depth0 = args->depth;
@ -4797,59 +4788,22 @@ int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *a
gr->base.last_level = args->last_level;
gr->base.nr_samples = args->nr_samples;
gr->base.array_size = args->array_size;
}
if (args->flags & VIRGL_RESOURCE_Y_0_TOP)
gr->y_0_top = true;
pipe_reference_init(&gr->base.reference, 1);
if (args->bind == VREND_RES_BIND_CUSTOM) {
/* custom should only be for buffers */
gr->ptr = malloc(args->width);
if (!gr->ptr) {
FREE(gr);
return ENOMEM;
}
} else if (args->bind == VREND_RES_BIND_INDEX_BUFFER) {
gr->target = GL_ELEMENT_ARRAY_BUFFER_ARB;
vrend_create_buffer(gr, args->width);
} else if (args->bind == VREND_RES_BIND_STREAM_OUTPUT) {
gr->target = GL_TRANSFORM_FEEDBACK_BUFFER;
vrend_create_buffer(gr, args->width);
} else if (args->bind == VREND_RES_BIND_VERTEX_BUFFER) {
gr->target = GL_ARRAY_BUFFER_ARB;
vrend_create_buffer(gr, args->width);
} else if (args->bind == VREND_RES_BIND_CONSTANT_BUFFER) {
gr->target = GL_UNIFORM_BUFFER;
vrend_create_buffer(gr, args->width);
} else if (args->target == PIPE_BUFFER && args->bind == 0) {
gr->target = GL_ARRAY_BUFFER_ARB;
vrend_create_buffer(gr, args->width);
} else if (args->target == PIPE_BUFFER && (args->bind & VREND_RES_BIND_SAMPLER_VIEW)) {
/*
* On Desktop we use GL_ARB_texture_buffer_object on GLES we use
* GL_EXT_texture_buffer (it is in the ANDRIOD extension pack).
*/
#if GL_TEXTURE_BUFFER != GL_TEXTURE_BUFFER_EXT
#error "GL_TEXTURE_BUFFER enums differ, they shouldn't."
#endif
/* need to check GL version here */
if (vrend_state.have_arb_or_gles_ext_texture_buffer) {
gr->target = GL_TEXTURE_BUFFER;
} else {
gr->target = GL_PIXEL_PACK_BUFFER_ARB;
}
vrend_create_buffer(gr, args->width);
} else {
struct vrend_texture *gt = (struct vrend_texture *)gr;
static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr)
{
uint level;
GLenum internalformat, glformat, gltype;
gr->target = tgsitargettogltarget(args->target, args->nr_samples);
struct vrend_texture *gt = (struct vrend_texture *)gr;
struct pipe_resource *pr = &gr->base;
assert(pr->width0 > 0);
gr->target = tgsitargettogltarget(pr->target, pr->nr_samples);
/* ugly workaround for texture rectangle missing on GLES */
if (vrend_state.use_gles && gr->target == GL_TEXTURE_RECTANGLE_NV) {
/* for some guests this is the only usage of rect */
if (args->width != 1 || args->height != 1) {
if (pr->width0 != 1 || pr->height0 != 1) {
report_gles_warn(NULL, GLES_WARN_TEXTURE_RECT, 0);
}
gr->target = GL_TEXTURE_2D;
@ -4868,48 +4822,48 @@ int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *a
glGenTextures(1, &gr->id);
glBindTexture(gr->target, gr->id);
internalformat = tex_conv_table[args->format].internalformat;
glformat = tex_conv_table[args->format].glformat;
gltype = tex_conv_table[args->format].gltype;
internalformat = tex_conv_table[pr->format].internalformat;
glformat = tex_conv_table[pr->format].glformat;
gltype = tex_conv_table[pr->format].gltype;
if (internalformat == 0) {
fprintf(stderr,"unknown format is %d\n", args->format);
FREE(gr);
fprintf(stderr,"unknown format is %d\n", pr->format);
FREE(gt);
return EINVAL;
}
if (args->nr_samples > 1) {
if (vrend_state.use_gles || vrend_state.have_texture_storage) {
if (pr->nr_samples > 1) {
if (vrend_state.use_gles) {
if (gr->target == GL_TEXTURE_2D_MULTISAMPLE) {
glTexStorage2DMultisample(gr->target, args->nr_samples,
internalformat, args->width, args->height,
glTexStorage2DMultisample(gr->target, pr->nr_samples,
internalformat, pr->width0, pr->height0,
GL_TRUE);
} else {
glTexStorage3DMultisample(gr->target, args->nr_samples,
internalformat, args->width, args->height, args->array_size,
glTexStorage3DMultisample(gr->target, pr->nr_samples,
internalformat, pr->width0, pr->height0, pr->array_size,
GL_TRUE);
}
} else {
if (gr->target == GL_TEXTURE_2D_MULTISAMPLE) {
glTexImage2DMultisample(gr->target, args->nr_samples,
internalformat, args->width, args->height,
glTexImage2DMultisample(gr->target, pr->nr_samples,
internalformat, pr->width0, pr->height0,
GL_TRUE);
} else {
glTexImage3DMultisample(gr->target, args->nr_samples,
internalformat, args->width, args->height, args->array_size,
glTexImage3DMultisample(gr->target, pr->nr_samples,
internalformat, pr->width0, pr->height0, pr->array_size,
GL_TRUE);
}
}
} else if (gr->target == GL_TEXTURE_CUBE_MAP) {
int i;
if (vrend_state.have_texture_storage)
glTexStorage2D(GL_TEXTURE_CUBE_MAP, args->last_level + 1, internalformat, args->width, args->height);
glTexStorage2D(GL_TEXTURE_CUBE_MAP, pr->last_level + 1, internalformat, pr->width0, pr->height0);
else {
for (i = 0; i < 6; i++) {
GLenum ctarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
for (level = 0; level <= args->last_level; level++) {
unsigned mwidth = u_minify(args->width, level);
unsigned mheight = u_minify(args->height, level);
for (level = 0; level <= pr->last_level; level++) {
unsigned mwidth = u_minify(pr->width0, level);
unsigned mheight = u_minify(pr->height0, level);
glTexImage2D(ctarget, level, internalformat, mwidth, mheight, 0, glformat,
gltype, NULL);
@ -4920,47 +4874,115 @@ int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *a
gr->target == GL_TEXTURE_2D_ARRAY ||
gr->target == GL_TEXTURE_CUBE_MAP_ARRAY) {
if (vrend_state.have_texture_storage) {
unsigned depth_param = (gr->target == GL_TEXTURE_2D_ARRAY || gr->target == GL_TEXTURE_CUBE_MAP_ARRAY) ? args->array_size : args->depth;
glTexStorage3D(gr->target, args->last_level + 1, internalformat, args->width, args->height, depth_param);
unsigned depth_param = (gr->target == GL_TEXTURE_2D_ARRAY || gr->target == GL_TEXTURE_CUBE_MAP_ARRAY) ?
pr->array_size : pr->depth0;
glTexStorage3D(gr->target, pr->last_level + 1, internalformat, pr->width0, pr->height0, depth_param);
} else {
for (level = 0; level <= args->last_level; level++) {
unsigned depth_param = (gr->target == GL_TEXTURE_2D_ARRAY || gr->target == GL_TEXTURE_CUBE_MAP_ARRAY) ? args->array_size : u_minify(args->depth, level);
unsigned mwidth = u_minify(args->width, level);
unsigned mheight = u_minify(args->height, level);
glTexImage3D(gr->target, level, internalformat, mwidth, mheight, depth_param, 0,
glformat,
gltype, NULL);
for (level = 0; level <= pr->last_level; level++) {
unsigned depth_param = (gr->target == GL_TEXTURE_2D_ARRAY || gr->target == GL_TEXTURE_CUBE_MAP_ARRAY) ?
pr->array_size : u_minify(pr->depth0, level);
unsigned mwidth = u_minify(pr->width0, level);
unsigned mheight = u_minify(pr->height0, level);
glTexImage3D(gr->target, level, internalformat, mwidth, mheight,
depth_param, 0, glformat, gltype, NULL);
}
}
} else if (gr->target == GL_TEXTURE_1D && vrend_state.use_gles) {
report_gles_missing_func(NULL, "glTexImage1D");
} else if (gr->target == GL_TEXTURE_1D) {
if (vrend_state.have_texture_storage) {
glTexStorage1D(gr->target, args->last_level + 1, internalformat, args->width);
glTexStorage1D(gr->target, pr->last_level + 1, internalformat, pr->width0);
} else {
for (level = 0; level <= args->last_level; level++) {
unsigned mwidth = u_minify(args->width, level);
for (level = 0; level <= pr->last_level; level++) {
unsigned mwidth = u_minify(pr->width0, level);
glTexImage1D(gr->target, level, internalformat, mwidth, 0,
glformat,
gltype, NULL);
glformat, gltype, NULL);
}
}
} else {
if (vrend_state.have_texture_storage)
glTexStorage2D(gr->target, args->last_level + 1, internalformat, args->width,
gr->target == GL_TEXTURE_1D_ARRAY ? args->array_size : args->height);
glTexStorage2D(gr->target, pr->last_level + 1, internalformat, pr->width0,
gr->target == GL_TEXTURE_1D_ARRAY ? pr->array_size : pr->height0);
else {
for (level = 0; level <= args->last_level; level++) {
unsigned mwidth = u_minify(args->width, level);
unsigned mheight = u_minify(args->height, level);
glTexImage2D(gr->target, level, internalformat, mwidth, gr->target == GL_TEXTURE_1D_ARRAY ? args->array_size : mheight, 0, glformat,
gltype, NULL);
for (level = 0; level <= pr->last_level; level++) {
unsigned mwidth = u_minify(pr->width0, level);
unsigned mheight = u_minify(pr->height0, level);
glTexImage2D(gr->target, level, internalformat, mwidth,
gr->target == GL_TEXTURE_1D_ARRAY ? pr->array_size : mheight,
0, glformat, gltype, NULL);
}
}
}
gt->state.max_lod = -1;
gt->cur_swizzle_r = gt->cur_swizzle_g = gt->cur_swizzle_b = gt->cur_swizzle_a = -1;
return 0;
}
int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *args, struct iovec *iov, uint32_t num_iovs)
{
struct vrend_resource *gr;
int ret;
ret = check_resource_valid(args);
if (ret)
return EINVAL;
gr = (struct vrend_resource *)CALLOC_STRUCT(vrend_texture);
if (!gr)
return ENOMEM;
vrend_renderer_resource_copy_args(args, gr);
gr->iov = iov;
gr->num_iovs = num_iovs;
if (args->flags & VIRGL_RESOURCE_Y_0_TOP)
gr->y_0_top = true;
pipe_reference_init(&gr->base.reference, 1);
if (args->bind == VREND_RES_BIND_CUSTOM) {
/* custom should only be for buffers */
gr->ptr = malloc(args->width);
if (!gr->ptr) {
FREE(gr);
return ENOMEM;
}
} else if (args->bind == VREND_RES_BIND_INDEX_BUFFER) {
gr->target = GL_ELEMENT_ARRAY_BUFFER_ARB;
vrend_create_buffer(gr, args->width);
} else if (args->bind == VREND_RES_BIND_STREAM_OUTPUT) {
gr->target = GL_TRANSFORM_FEEDBACK_BUFFER;
vrend_create_buffer(gr, args->width);
} else if (args->bind == VREND_RES_BIND_VERTEX_BUFFER) {
gr->target = GL_ARRAY_BUFFER_ARB;
vrend_create_buffer(gr, args->width);
} else if (args->bind == VREND_RES_BIND_CONSTANT_BUFFER) {
gr->target = GL_UNIFORM_BUFFER;
vrend_create_buffer(gr, args->width);
} else if (args->target == PIPE_BUFFER && args->bind == 0) {
gr->target = GL_ARRAY_BUFFER_ARB;
vrend_create_buffer(gr, args->width);
} else if (args->target == PIPE_BUFFER && (args->bind & VREND_RES_BIND_SAMPLER_VIEW)) {
/*
* On Desktop we use GL_ARB_texture_buffer_object on GLES we use
* GL_EXT_texture_buffer (it is in the ANDRIOD extension pack).
*/
#if GL_TEXTURE_BUFFER != GL_TEXTURE_BUFFER_EXT
#error "GL_TEXTURE_BUFFER enums differ, they shouldn't."
#endif
/* need to check GL version here */
if (vrend_state.have_arb_or_gles_ext_texture_buffer) {
gr->target = GL_TEXTURE_BUFFER;
} else {
gr->target = GL_PIXEL_PACK_BUFFER_ARB;
}
vrend_create_buffer(gr, args->width);
} else {
int r = vrend_renderer_resource_allocate_texture(gr);
if (r)
return r;
}
ret = vrend_resource_insert(gr, args->handle);

Loading…
Cancel
Save