X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_state_sampler.c;h=c9aba1a8594a3025b084550a0cad4ad46c7f7907;hb=ce785f5ffd7dbed14a3909164e55a975a023ee97;hp=6b7e327e0fbfe2e79a1a861bfe67e015f688d547;hpb=87978518e996d02e055174d7152fff150fe3cd13;p=mesa.git diff --git a/src/gallium/drivers/llvmpipe/lp_state_sampler.c b/src/gallium/drivers/llvmpipe/lp_state_sampler.c index 6b7e327e0fb..c9aba1a8594 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_sampler.c +++ b/src/gallium/drivers/llvmpipe/lp_state_sampler.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2007 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * 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 TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * 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. @@ -66,7 +66,7 @@ llvmpipe_create_sampler_state(struct pipe_context *pipe, static void llvmpipe_bind_sampler_states(struct pipe_context *pipe, - unsigned shader, + enum pipe_shader_type shader, unsigned start, unsigned num, void **samplers) @@ -75,14 +75,7 @@ llvmpipe_bind_sampler_states(struct pipe_context *pipe, unsigned i; assert(shader < PIPE_SHADER_TYPES); - assert(start + num <= Elements(llvmpipe->samplers[shader])); - - /* Check for no-op */ - if (start + num <= llvmpipe->num_samplers[shader] && - !memcmp(llvmpipe->samplers[shader] + start, samplers, - num * sizeof(void *))) { - return; - } + assert(start + num <= ARRAY_SIZE(llvmpipe->samplers[shader])); draw_flush(llvmpipe->draw); @@ -105,37 +98,15 @@ llvmpipe_bind_sampler_states(struct pipe_context *pipe, llvmpipe->samplers[shader], llvmpipe->num_samplers[shader]); } - - llvmpipe->dirty |= LP_NEW_SAMPLER; -} - - -static void -llvmpipe_bind_fragment_sampler_states(struct pipe_context *pipe, - unsigned num, void **samplers) -{ - llvmpipe_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, num, samplers); -} - - -static void -llvmpipe_bind_vertex_sampler_states(struct pipe_context *pipe, - unsigned num, void **samplers) -{ - llvmpipe_bind_sampler_states(pipe, PIPE_SHADER_VERTEX, 0, num, samplers); + else { + llvmpipe->dirty |= LP_NEW_SAMPLER; + } } -static void -llvmpipe_bind_geometry_sampler_states(struct pipe_context *pipe, - unsigned num, void **samplers) -{ - llvmpipe_bind_sampler_states(pipe, PIPE_SHADER_GEOMETRY, 0, num, samplers); -} - static void llvmpipe_set_sampler_views(struct pipe_context *pipe, - unsigned shader, + enum pipe_shader_type shader, unsigned start, unsigned num, struct pipe_sampler_view **views) @@ -146,19 +117,27 @@ llvmpipe_set_sampler_views(struct pipe_context *pipe, assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS); assert(shader < PIPE_SHADER_TYPES); - assert(start + num <= Elements(llvmpipe->sampler_views[shader])); - - /* Check for no-op */ - if (start + num <= llvmpipe->num_sampler_views[shader] && - !memcmp(llvmpipe->sampler_views[shader] + start, views, - num * sizeof(struct pipe_sampler_view *))) { - return; - } + assert(start + num <= ARRAY_SIZE(llvmpipe->sampler_views[shader])); draw_flush(llvmpipe->draw); /* set the new sampler views */ for (i = 0; i < num; i++) { + /* Note: we're using pipe_sampler_view_release() here to work around + * a possible crash when the old view belongs to another context that + * was already destroyed. + */ + pipe_sampler_view_release(pipe, + &llvmpipe->sampler_views[shader][start + i]); + /* + * Warn if someone tries to set a view created in a different context + * (which is why we need the hack above in the first place). + * An assert would be better but st/mesa relies on it... + */ + if (views[i] && views[i]->context != pipe) { + debug_printf("Illegal setting of sampler_view %d created in another " + "context\n", i); + } pipe_sampler_view_reference(&llvmpipe->sampler_views[shader][start + i], views[i]); } @@ -177,37 +156,12 @@ llvmpipe_set_sampler_views(struct pipe_context *pipe, llvmpipe->sampler_views[shader], llvmpipe->num_sampler_views[shader]); } - - llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW; -} - - -static void -llvmpipe_set_fragment_sampler_views(struct pipe_context *pipe, - unsigned num, - struct pipe_sampler_view **views) -{ - llvmpipe_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num, views); -} - - -static void -llvmpipe_set_vertex_sampler_views(struct pipe_context *pipe, - unsigned num, - struct pipe_sampler_view **views) -{ - llvmpipe_set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0, num, views); + else { + llvmpipe->dirty |= LP_NEW_SAMPLER_VIEW; + } } -static void -llvmpipe_set_geometry_sampler_views(struct pipe_context *pipe, - unsigned num, - struct pipe_sampler_view **views) -{ - llvmpipe_set_sampler_views(pipe, PIPE_SHADER_GEOMETRY, 0, num, views); -} - static struct pipe_sampler_view * llvmpipe_create_sampler_view(struct pipe_context *pipe, struct pipe_resource *texture, @@ -215,11 +169,13 @@ llvmpipe_create_sampler_view(struct pipe_context *pipe, { struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); /* - * XXX we REALLY want to see the correct bind flag here but the OpenGL - * state tracker can't guarantee that at least for texture buffer objects. + * XXX: bind flags from OpenGL state tracker are notoriously unreliable. + * This looks unfixable, so fix the bind flags instead when it happens. */ - if (!(texture->bind & PIPE_BIND_SAMPLER_VIEW)) + if (!(texture->bind & PIPE_BIND_SAMPLER_VIEW)) { debug_printf("Illegal sampler view creation without bind flag\n"); + texture->bind |= PIPE_BIND_SAMPLER_VIEW; + } if (view) { *view = *templ; @@ -227,6 +183,36 @@ llvmpipe_create_sampler_view(struct pipe_context *pipe, view->texture = NULL; pipe_resource_reference(&view->texture, texture); view->context = pipe; + +#ifdef DEBUG + /* + * This is possibly too lenient, but the primary reason is just + * to catch state trackers which forget to initialize this, so + * it only catches clearly impossible view targets. + */ + if (view->target != texture->target) { + if (view->target == PIPE_TEXTURE_1D) + assert(texture->target == PIPE_TEXTURE_1D_ARRAY); + else if (view->target == PIPE_TEXTURE_1D_ARRAY) + assert(texture->target == PIPE_TEXTURE_1D); + else if (view->target == PIPE_TEXTURE_2D) + assert(texture->target == PIPE_TEXTURE_2D_ARRAY || + texture->target == PIPE_TEXTURE_CUBE || + texture->target == PIPE_TEXTURE_CUBE_ARRAY); + else if (view->target == PIPE_TEXTURE_2D_ARRAY) + assert(texture->target == PIPE_TEXTURE_2D || + texture->target == PIPE_TEXTURE_CUBE || + texture->target == PIPE_TEXTURE_CUBE_ARRAY); + else if (view->target == PIPE_TEXTURE_CUBE) + assert(texture->target == PIPE_TEXTURE_CUBE_ARRAY || + texture->target == PIPE_TEXTURE_2D_ARRAY); + else if (view->target == PIPE_TEXTURE_CUBE_ARRAY) + assert(texture->target == PIPE_TEXTURE_CUBE || + texture->target == PIPE_TEXTURE_2D_ARRAY); + else + assert(0); + } +#endif } return view; @@ -255,8 +241,7 @@ prepare_shader_sampling( struct llvmpipe_context *lp, unsigned num, struct pipe_sampler_view **views, - unsigned shader_type, - struct pipe_resource *mapped_tex[PIPE_MAX_SHADER_SAMPLER_VIEWS]) + enum pipe_shader_type shader_type) { unsigned i; @@ -269,7 +254,7 @@ prepare_shader_sampling( if (!num) return; - for (i = 0; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; i++) { + for (i = 0; i < num; i++) { struct pipe_sampler_view *view = i < num ? views[i] : NULL; if (view) { @@ -280,69 +265,52 @@ prepare_shader_sampling( unsigned first_level = 0; unsigned last_level = 0; - /* We're referencing the texture's internal data, so save a - * reference to it. - */ - pipe_resource_reference(&mapped_tex[i], tex); - if (!lp_tex->dt) { /* regular texture - setup array of mipmap level offsets */ struct pipe_resource *res = view->texture; int j; - void *mip_ptr; if (llvmpipe_resource_is_texture(res)) { first_level = view->u.tex.first_level; last_level = view->u.tex.last_level; assert(first_level <= last_level); assert(last_level <= res->last_level); - - /* must trigger allocation first before we can get base ptr */ - /* XXX this may fail due to OOM ? */ - mip_ptr = llvmpipe_get_texture_image_all(lp_tex, view->u.tex.first_level, - LP_TEX_USAGE_READ, - LP_TEX_LAYOUT_LINEAR); - addr = lp_tex->linear_img.data; + addr = lp_tex->tex_data; for (j = first_level; j <= last_level; j++) { - mip_ptr = llvmpipe_get_texture_image_all(lp_tex, j, - LP_TEX_USAGE_READ, - LP_TEX_LAYOUT_LINEAR); - mip_offsets[j] = (uint8_t *)mip_ptr - (uint8_t *)addr; - /* - * could get mip offset directly but need call above to - * invoke tiled->linear conversion. - */ - assert(lp_tex->linear_mip_offsets[j] == mip_offsets[j]); + mip_offsets[j] = lp_tex->mip_offsets[j]; row_stride[j] = lp_tex->row_stride[j]; img_stride[j] = lp_tex->img_stride[j]; } - if (res->target == PIPE_TEXTURE_1D_ARRAY || - res->target == PIPE_TEXTURE_2D_ARRAY) { + if (tex->target == PIPE_TEXTURE_1D_ARRAY || + tex->target == PIPE_TEXTURE_2D_ARRAY || + tex->target == PIPE_TEXTURE_CUBE || + tex->target == PIPE_TEXTURE_CUBE_ARRAY) { num_layers = view->u.tex.last_layer - view->u.tex.first_layer + 1; for (j = first_level; j <= last_level; j++) { mip_offsets[j] += view->u.tex.first_layer * lp_tex->img_stride[j]; } + if (view->target == PIPE_TEXTURE_CUBE || + view->target == PIPE_TEXTURE_CUBE_ARRAY) { + assert(num_layers % 6 == 0); + } assert(view->u.tex.first_layer <= view->u.tex.last_layer); assert(view->u.tex.last_layer < res->array_size); } } else { unsigned view_blocksize = util_format_get_blocksize(view->format); - mip_ptr = lp_tex->data; - addr = mip_ptr; + addr = lp_tex->data; /* probably don't really need to fill that out */ mip_offsets[0] = 0; row_stride[0] = 0; - row_stride[0] = 0; + img_stride[0] = 0; /* everything specified in number of elements here. */ - width0 = view->u.buf.last_element - view->u.buf.first_element + 1; - addr = (uint8_t *)addr + view->u.buf.first_element * - view_blocksize; - assert(view->u.buf.first_element <= view->u.buf.last_element); - assert(view->u.buf.last_element * view_blocksize < res->width0); + width0 = view->u.buf.size / view_blocksize; + addr = (uint8_t *)addr + view->u.buf.offset; + assert(view->u.buf.offset + view->u.buf.size <= res->width0); } } else { @@ -369,63 +337,40 @@ prepare_shader_sampling( } } } - + /** - * Called during state validation when LP_NEW_SAMPLER_VIEW is set. + * Called whenever we're about to draw (no dirty flag, FIXME?). */ void llvmpipe_prepare_vertex_sampling(struct llvmpipe_context *lp, unsigned num, struct pipe_sampler_view **views) { - prepare_shader_sampling(lp, num, views, PIPE_SHADER_VERTEX, - lp->mapped_vs_tex); -} - -void -llvmpipe_cleanup_vertex_sampling(struct llvmpipe_context *ctx) -{ - unsigned i; - for (i = 0; i < Elements(ctx->mapped_vs_tex); i++) { - pipe_resource_reference(&ctx->mapped_vs_tex[i], NULL); - } + prepare_shader_sampling(lp, num, views, PIPE_SHADER_VERTEX); } /** - * Called during state validation when LP_NEW_SAMPLER_VIEW is set. + * Called whenever we're about to draw (no dirty flag, FIXME?). */ void llvmpipe_prepare_geometry_sampling(struct llvmpipe_context *lp, unsigned num, struct pipe_sampler_view **views) { - prepare_shader_sampling(lp, num, views, PIPE_SHADER_GEOMETRY, - lp->mapped_gs_tex); + prepare_shader_sampling(lp, num, views, PIPE_SHADER_GEOMETRY); } -void -llvmpipe_cleanup_geometry_sampling(struct llvmpipe_context *ctx) -{ - unsigned i; - for (i = 0; i < Elements(ctx->mapped_gs_tex); i++) { - pipe_resource_reference(&ctx->mapped_gs_tex[i], NULL); - } -} void llvmpipe_init_sampler_funcs(struct llvmpipe_context *llvmpipe) { llvmpipe->pipe.create_sampler_state = llvmpipe_create_sampler_state; - llvmpipe->pipe.bind_fragment_sampler_states = llvmpipe_bind_fragment_sampler_states; - llvmpipe->pipe.bind_vertex_sampler_states = llvmpipe_bind_vertex_sampler_states; - llvmpipe->pipe.bind_geometry_sampler_states = llvmpipe_bind_geometry_sampler_states; - llvmpipe->pipe.set_fragment_sampler_views = llvmpipe_set_fragment_sampler_views; - llvmpipe->pipe.set_vertex_sampler_views = llvmpipe_set_vertex_sampler_views; - llvmpipe->pipe.set_geometry_sampler_views = llvmpipe_set_geometry_sampler_views; + llvmpipe->pipe.bind_sampler_states = llvmpipe_bind_sampler_states; llvmpipe->pipe.create_sampler_view = llvmpipe_create_sampler_view; + llvmpipe->pipe.set_sampler_views = llvmpipe_set_sampler_views; llvmpipe->pipe.sampler_view_destroy = llvmpipe_sampler_view_destroy; llvmpipe->pipe.delete_sampler_state = llvmpipe_delete_sampler_state; }