diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c index 9ca4548..3cd1386 100644 --- a/src/vrend_renderer.c +++ b/src/vrend_renderer.c @@ -4772,10 +4772,156 @@ static void vrend_create_buffer(struct vrend_resource *gr, uint32_t width) gr->is_buffer = true; } +static inline void +vrend_renderer_resource_copy_args(struct vrend_renderer_resource_create_args *args, + struct vrend_resource *gr) +{ + assert(gr); + assert(args); + + gr->handle = args->handle; + gr->base.width0 = args->width; + gr->base.height0 = args->height; + gr->base.depth0 = args->depth; + gr->base.format = args->format; + gr->base.target = args->target; + gr->base.last_level = args->last_level; + gr->base.nr_samples = args->nr_samples; + gr->base.array_size = args->array_size; +} + +static int vrend_renderer_resource_allocate_texture(struct vrend_resource *gr) +{ + uint level; + GLenum internalformat, glformat, gltype; + 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 (pr->width0 != 1 || pr->height0 != 1) { + report_gles_warn(NULL, GLES_WARN_TEXTURE_RECT, 0); + } + gr->target = GL_TEXTURE_2D; + } + + /* fallback for 1D textures */ + if (vrend_state.use_gles && gr->target == GL_TEXTURE_1D) { + gr->target = GL_TEXTURE_2D; + } + + /* fallback for 1D array textures */ + if (vrend_state.use_gles && gr->target == GL_TEXTURE_1D_ARRAY) { + gr->target = GL_TEXTURE_2D_ARRAY; + } + + glGenTextures(1, &gr->id); + glBindTexture(gr->target, gr->id); + + 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", pr->format); + FREE(gt); + return EINVAL; + } + + if (pr->nr_samples > 1) { + if (vrend_state.use_gles) { + if (gr->target == GL_TEXTURE_2D_MULTISAMPLE) { + glTexStorage2DMultisample(gr->target, pr->nr_samples, + internalformat, pr->width0, pr->height0, + GL_TRUE); + } else { + 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, pr->nr_samples, + internalformat, pr->width0, pr->height0, + GL_TRUE); + } else { + 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, 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 <= 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); + } + } + } + } else if (gr->target == GL_TEXTURE_3D || + 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) ? + pr->array_size : pr->depth0; + glTexStorage3D(gr->target, pr->last_level + 1, internalformat, pr->width0, pr->height0, depth_param); + } else { + 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, pr->last_level + 1, internalformat, pr->width0); + } else { + 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); + } + } + } else { + if (vrend_state.have_texture_storage) + 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 <= 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; - uint32_t level; int ret; ret = check_resource_valid(args); @@ -4786,17 +4932,9 @@ int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *a if (!gr) return ENOMEM; - gr->handle = args->handle; + vrend_renderer_resource_copy_args(args, gr); gr->iov = iov; gr->num_iovs = num_iovs; - gr->base.width0 = args->width; - gr->base.height0 = args->height; - gr->base.depth0 = args->depth; - gr->base.format = args->format; - gr->base.target = args->target; - 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; @@ -4842,125 +4980,9 @@ int vrend_renderer_resource_create(struct vrend_renderer_resource_create_args *a } vrend_create_buffer(gr, args->width); } else { - struct vrend_texture *gt = (struct vrend_texture *)gr; - GLenum internalformat, glformat, gltype; - gr->target = tgsitargettogltarget(args->target, args->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) { - report_gles_warn(NULL, GLES_WARN_TEXTURE_RECT, 0); - } - gr->target = GL_TEXTURE_2D; - } - - /* fallback for 1D textures */ - if (vrend_state.use_gles && gr->target == GL_TEXTURE_1D) { - gr->target = GL_TEXTURE_2D; - } - - /* fallback for 1D array textures */ - if (vrend_state.use_gles && gr->target == GL_TEXTURE_1D_ARRAY) { - gr->target = GL_TEXTURE_2D_ARRAY; - } - - 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; - if (internalformat == 0) { - fprintf(stderr,"unknown format is %d\n", args->format); - FREE(gr); - return EINVAL; - } - - if (args->nr_samples > 1) { - if (vrend_state.use_gles || vrend_state.have_texture_storage) { - if (gr->target == GL_TEXTURE_2D_MULTISAMPLE) { - glTexStorage2DMultisample(gr->target, args->nr_samples, - internalformat, args->width, args->height, - GL_TRUE); - } else { - glTexStorage3DMultisample(gr->target, args->nr_samples, - internalformat, args->width, args->height, args->array_size, - GL_TRUE); - } - } else { - if (gr->target == GL_TEXTURE_2D_MULTISAMPLE) { - glTexImage2DMultisample(gr->target, args->nr_samples, - internalformat, args->width, args->height, - GL_TRUE); - } else { - glTexImage3DMultisample(gr->target, args->nr_samples, - internalformat, args->width, args->height, args->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); - 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); - - glTexImage2D(ctarget, level, internalformat, mwidth, mheight, 0, glformat, - gltype, NULL); - } - } - } - } else if (gr->target == GL_TEXTURE_3D || - 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); - } 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); - } - } - } 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); - } else { - for (level = 0; level <= args->last_level; level++) { - unsigned mwidth = u_minify(args->width, level); - glTexImage1D(gr->target, level, internalformat, mwidth, 0, - 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); - 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); - } - } - } - - gt->state.max_lod = -1; - gt->cur_swizzle_r = gt->cur_swizzle_g = gt->cur_swizzle_b = gt->cur_swizzle_a = -1; + int r = vrend_renderer_resource_allocate_texture(gr); + if (r) + return r; } ret = vrend_resource_insert(gr, args->handle);