X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_sampler_view.c;h=a31e573c01a3dec0371ddcbbf94d306c3ccbc6b5;hb=493fdcf44647ee471e934de3e63d193c6a3b6ff0;hp=88d5d1aae2f2308dfd6b70370b321e36be2412a9;hpb=da2a51129bfcb761d10a7a0b3c6579aa0adc5137;p=mesa.git diff --git a/src/mesa/state_tracker/st_sampler_view.c b/src/mesa/state_tracker/st_sampler_view.c index 88d5d1aae2f..a31e573c01a 100644 --- a/src/mesa/state_tracker/st_sampler_view.c +++ b/src/mesa/state_tracker/st_sampler_view.c @@ -24,7 +24,7 @@ */ #include "pipe/p_context.h" -#include "util/u_format.h" +#include "util/format/u_format.h" #include "util/u_inlines.h" #include "main/context.h" @@ -38,28 +38,44 @@ #include "st_sampler_view.h" #include "st_texture.h" #include "st_format.h" +#include "st_cb_bufferobjects.h" #include "st_cb_texture.h" /** - * Try to find a matching sampler view for the given context. - * If none is found an empty slot is initialized with a - * template and returned instead. + * Set the given view as the current context's view for the texture. + * + * Overwrites any pre-existing view of the context. + * + * Takes ownership of the view (i.e., stores the view without incrementing the + * reference count). + * + * \return the view, or NULL on error. In case of error, the reference to the + * view is released. */ -struct pipe_sampler_view ** -st_texture_get_sampler_view(struct st_context *st, - struct st_texture_object *stObj) +static struct pipe_sampler_view * +st_texture_set_sampler_view(struct st_context *st, + struct st_texture_object *stObj, + struct pipe_sampler_view *view, + bool glsl130_or_later, bool srgb_skip_decode) { - struct pipe_sampler_view **free = NULL; + struct st_sampler_views *views; + struct st_sampler_view *free = NULL; + struct st_sampler_view *sv; GLuint i; - for (i = 0; i < stObj->num_sampler_views; ++i) { - struct pipe_sampler_view **sv = &stObj->sampler_views[i]; + simple_mtx_lock(&stObj->validate_mutex); + views = stObj->sampler_views; + + for (i = 0; i < views->count; ++i) { + sv = &views->views[i]; + /* Is the array entry used ? */ - if (*sv) { + if (sv->view) { /* check if the context matches */ - if ((*sv)->context == st->pipe) { - return sv; + if (sv->view->context == st->pipe) { + pipe_sampler_view_reference(&sv->view, NULL); + goto found; } } else { /* Found a free slot, remember that */ @@ -68,65 +84,185 @@ st_texture_get_sampler_view(struct st_context *st, } /* Couldn't find a slot for our context, create a new one */ + if (free) { + sv = free; + } else { + if (views->count >= views->max) { + /* Allocate a larger container. */ + unsigned new_max = 2 * views->max; + unsigned new_size = sizeof(*views) + new_max * sizeof(views->views[0]); + + if (new_max < views->max || + new_max > (UINT_MAX - sizeof(*views)) / sizeof(views->views[0])) { + pipe_sampler_view_reference(&view, NULL); + goto out; + } + + struct st_sampler_views *new_views = malloc(new_size); + if (!new_views) { + pipe_sampler_view_reference(&view, NULL); + goto out; + } + + new_views->count = views->count; + new_views->max = new_max; + memcpy(&new_views->views[0], &views->views[0], + views->count * sizeof(views->views[0])); + + /* Initialize the pipe_sampler_view pointers to zero so that we don't + * have to worry about racing against readers when incrementing + * views->count. + */ + memset(&new_views->views[views->count], 0, + (new_max - views->count) * sizeof(views->views[0])); - if (!free) { - /* Haven't even found a free one, resize the array */ - unsigned new_size = (stObj->num_sampler_views + 1) * - sizeof(struct pipe_sampler_view *); - stObj->sampler_views = realloc(stObj->sampler_views, new_size); - free = &stObj->sampler_views[stObj->num_sampler_views++]; - *free = NULL; + /* Use memory release semantics to ensure that concurrent readers will + * get the correct contents of the new container. + * + * Also, the write should be atomic, but that's guaranteed anyway on + * all supported platforms. + */ + p_atomic_set(&stObj->sampler_views, new_views); + + /* We keep the old container around until the texture object is + * deleted, because another thread may still be reading from it. We + * double the size of the container each time, so we end up with + * at most twice the total memory allocation. + */ + views->next = stObj->sampler_views_old; + stObj->sampler_views_old = views; + + views = new_views; + } + + sv = &views->views[views->count]; + + /* Since modification is guarded by the lock, only the write part of the + * increment has to be atomic, and that's already guaranteed on all + * supported platforms without using an atomic intrinsic. + */ + views->count++; } - assert(*free == NULL); +found: + assert(sv->view == NULL); + + sv->glsl130_or_later = glsl130_or_later; + sv->srgb_skip_decode = srgb_skip_decode; + sv->view = view; + sv->st = st; - return free; +out: + simple_mtx_unlock(&stObj->validate_mutex); + return view; +} + + +/** + * Return the most-recently validated sampler view for the texture \p stObj + * in the given context, if any. + * + * Performs no additional validation. + */ +const struct st_sampler_view * +st_texture_get_current_sampler_view(const struct st_context *st, + const struct st_texture_object *stObj) +{ + const struct st_sampler_views *views = p_atomic_read(&stObj->sampler_views); + + for (unsigned i = 0; i < views->count; ++i) { + const struct st_sampler_view *sv = &views->views[i]; + if (sv->view && sv->view->context == st->pipe) + return sv; + } + + return NULL; } /** * For the given texture object, release any sampler views which belong - * to the calling context. + * to the calling context. This is used to free any sampler views + * which belong to the context before the context is destroyed. */ void -st_texture_release_sampler_view(struct st_context *st, - struct st_texture_object *stObj) +st_texture_release_context_sampler_view(struct st_context *st, + struct st_texture_object *stObj) { GLuint i; - for (i = 0; i < stObj->num_sampler_views; ++i) { - struct pipe_sampler_view **sv = &stObj->sampler_views[i]; + simple_mtx_lock(&stObj->validate_mutex); + struct st_sampler_views *views = stObj->sampler_views; + for (i = 0; i < views->count; ++i) { + struct pipe_sampler_view **sv = &views->views[i].view; if (*sv && (*sv)->context == st->pipe) { pipe_sampler_view_reference(sv, NULL); break; } } + simple_mtx_unlock(&stObj->validate_mutex); } /** * Release all sampler views attached to the given texture object, regardless - * of the context. + * of the context. This is called fairly frequently. For example, whenever + * the texture's base level, max level or swizzle change. */ void st_texture_release_all_sampler_views(struct st_context *st, struct st_texture_object *stObj) { - GLuint i; - - /* XXX This should use sampler_views[i]->pipe, not st->pipe */ - for (i = 0; i < stObj->num_sampler_views; ++i) - pipe_sampler_view_release(st->pipe, &stObj->sampler_views[i]); + /* TODO: This happens while a texture is deleted, because the Driver API + * is asymmetric: the driver allocates the texture object memory, but + * mesa/main frees it. + */ + if (!stObj->sampler_views) + return; + + simple_mtx_lock(&stObj->validate_mutex); + struct st_sampler_views *views = stObj->sampler_views; + for (unsigned i = 0; i < views->count; ++i) { + struct st_sampler_view *stsv = &views->views[i]; + if (stsv->view) { + if (stsv->st && stsv->st != st) { + /* Transfer this reference to the zombie list. It will + * likely be freed when the zombie list is freed. + */ + st_save_zombie_sampler_view(stsv->st, stsv->view); + stsv->view = NULL; + } else { + pipe_sampler_view_reference(&stsv->view, NULL); + } + } + } + views->count = 0; + simple_mtx_unlock(&stObj->validate_mutex); } +/* + * Delete the texture's sampler views and st_sampler_views containers. + * This is to be called just before a texture is deleted. + */ void -st_texture_free_sampler_views(struct st_texture_object *stObj) +st_delete_texture_sampler_views(struct st_context *st, + struct st_texture_object *stObj) { + st_texture_release_all_sampler_views(st, stObj); + + /* Free the container of the current per-context sampler views */ + assert(stObj->sampler_views->count == 0); free(stObj->sampler_views); stObj->sampler_views = NULL; - stObj->num_sampler_views = 0; + + /* Free old sampler view containers */ + while (stObj->sampler_views_old) { + struct st_sampler_views *views = stObj->sampler_views_old; + stObj->sampler_views_old = views->next; + free(views); + } } @@ -188,49 +324,27 @@ swizzle_swizzle(unsigned swizzle1, unsigned swizzle2) */ static unsigned compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode, - enum pipe_format actualFormat, - unsigned glsl_version) + bool glsl130_or_later) { switch (baseFormat) { case GL_RGBA: return SWIZZLE_XYZW; case GL_RGB: - if (util_format_has_alpha(actualFormat)) - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE); - else - return SWIZZLE_XYZW; + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE); case GL_RG: - if (util_format_get_nr_components(actualFormat) > 2) - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE); - else - return SWIZZLE_XYZW; + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE); case GL_RED: - if (util_format_get_nr_components(actualFormat) > 1) - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, - SWIZZLE_ZERO, SWIZZLE_ONE); - else - return SWIZZLE_XYZW; + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_ONE); case GL_ALPHA: - if (util_format_get_nr_components(actualFormat) > 1) - return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, - SWIZZLE_ZERO, SWIZZLE_W); - else - return SWIZZLE_XYZW; + return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_W); case GL_LUMINANCE: - if (util_format_get_nr_components(actualFormat) > 1) - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); - else - return SWIZZLE_XYZW; + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); case GL_LUMINANCE_ALPHA: - if (util_format_get_nr_components(actualFormat) > 2) - return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W); - else - return SWIZZLE_XYZW; + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W); case GL_INTENSITY: - if (util_format_get_nr_components(actualFormat) > 1) - return SWIZZLE_XXXX; - else - return SWIZZLE_XYZW; + return SWIZZLE_XXXX; case GL_STENCIL_INDEX: case GL_DEPTH_STENCIL: case GL_DEPTH_COMPONENT: @@ -256,7 +370,7 @@ compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode, * BTW, it's required that sampler views are updated when * shaders change (check_sampler_swizzle takes care of that). */ - if (glsl_version && glsl_version >= 130) + if (glsl130_or_later) return SWIZZLE_XXXX; else return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, @@ -278,33 +392,29 @@ compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode, static unsigned get_texture_format_swizzle(const struct st_context *st, const struct st_texture_object *stObj, - unsigned glsl_version) + bool glsl130_or_later) { - GLenum baseFormat = _mesa_texture_base_format(&stObj->base); + GLenum baseFormat = _mesa_base_tex_image(&stObj->base)->_BaseFormat; unsigned tex_swizzle; - - if (baseFormat != GL_NONE) { - GLenum depth_mode = stObj->base.DepthMode; - /* In ES 3.0, DEPTH_TEXTURE_MODE is expected to be GL_RED for textures - * with depth component data specified with a sized internal format. - */ - if (_mesa_is_gles3(st->ctx) && - util_format_is_depth_or_stencil(stObj->pt->format)) { - const struct gl_texture_image *firstImage = - _mesa_base_tex_image(&stObj->base); - if (firstImage->InternalFormat != GL_DEPTH_COMPONENT && - firstImage->InternalFormat != GL_DEPTH_STENCIL && - firstImage->InternalFormat != GL_STENCIL_INDEX) - depth_mode = GL_RED; - } - tex_swizzle = compute_texture_format_swizzle(baseFormat, - depth_mode, - stObj->pt->format, - glsl_version); - } - else { - tex_swizzle = SWIZZLE_XYZW; + GLenum depth_mode = stObj->base.DepthMode; + + /* In ES 3.0, DEPTH_TEXTURE_MODE is expected to be GL_RED for textures + * with depth component data specified with a sized internal format. + */ + if (_mesa_is_gles3(st->ctx) && + (baseFormat == GL_DEPTH_COMPONENT || + baseFormat == GL_DEPTH_STENCIL || + baseFormat == GL_STENCIL_INDEX)) { + const struct gl_texture_image *firstImage = + _mesa_base_tex_image(&stObj->base); + if (firstImage->InternalFormat != GL_DEPTH_COMPONENT && + firstImage->InternalFormat != GL_DEPTH_STENCIL && + firstImage->InternalFormat != GL_STENCIL_INDEX) + depth_mode = GL_RED; } + tex_swizzle = compute_texture_format_swizzle(baseFormat, + depth_mode, + glsl130_or_later); /* Combine the texture format swizzle with user's swizzle */ return swizzle_swizzle(stObj->base._Swizzle, tex_swizzle); @@ -317,12 +427,13 @@ get_texture_format_swizzle(const struct st_context *st, * * \param stObj the st texture object, */ -MAYBE_UNUSED static boolean +ASSERTED static boolean check_sampler_swizzle(const struct st_context *st, const struct st_texture_object *stObj, - const struct pipe_sampler_view *sv, unsigned glsl_version) + const struct pipe_sampler_view *sv, + bool glsl130_or_later) { - unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl_version); + unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl130_or_later); return ((sv->swizzle_r != GET_SWZ(swizzle, 0)) || (sv->swizzle_g != GET_SWZ(swizzle, 1)) || @@ -358,87 +469,84 @@ last_layer(const struct st_texture_object *stObj) static enum pipe_format get_sampler_view_format(struct st_context *st, const struct st_texture_object *stObj, - const struct gl_sampler_object *samp) + bool srgb_skip_decode) { enum pipe_format format; - if (stObj->base.Target == GL_TEXTURE_BUFFER) { - format = - st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat); - } - else { - format = - stObj->surface_based ? stObj->surface_format : stObj->pt->format; + GLenum baseFormat = _mesa_base_tex_image(&stObj->base)->_BaseFormat; + format = stObj->surface_based ? stObj->surface_format : stObj->pt->format; - if (util_format_is_depth_and_stencil(format)) { - if (stObj->base.StencilSampling) { - format = util_format_stencil_only(format); - } - else { - GLenum baseFormat = _mesa_texture_base_format(&stObj->base); - if (baseFormat == GL_STENCIL_INDEX) { - format = util_format_stencil_only(format); - } - } - } - else { - /* If sRGB decoding is off, use the linear format */ - if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) { - format = util_format_linear(format); - } + if (baseFormat == GL_DEPTH_COMPONENT || + baseFormat == GL_DEPTH_STENCIL || + baseFormat == GL_STENCIL_INDEX) { + if (stObj->base.StencilSampling || baseFormat == GL_STENCIL_INDEX) + format = util_format_stencil_only(format); - /* Use R8_UNORM for video formats */ - switch (format) { - case PIPE_FORMAT_NV12: - case PIPE_FORMAT_IYUV: - format = PIPE_FORMAT_R8_UNORM; - break; - default: - break; - } - } + return format; } + /* If sRGB decoding is off, use the linear format */ + if (srgb_skip_decode) + format = util_format_linear(format); + + /* if resource format matches then YUV wasn't lowered */ + if (format == stObj->pt->format) + return format; + + /* Use R8_UNORM for video formats */ + switch (format) { + case PIPE_FORMAT_NV12: + case PIPE_FORMAT_IYUV: + format = PIPE_FORMAT_R8_UNORM; + break; + case PIPE_FORMAT_P010: + case PIPE_FORMAT_P016: + format = PIPE_FORMAT_R16_UNORM; + break; + case PIPE_FORMAT_YUYV: + case PIPE_FORMAT_UYVY: + format = PIPE_FORMAT_R8G8_UNORM; + break; + case PIPE_FORMAT_AYUV: + format = PIPE_FORMAT_RGBA8888_UNORM; + break; + case PIPE_FORMAT_XYUV: + format = PIPE_FORMAT_RGBX8888_UNORM; + break; + default: + break; + } return format; } static struct pipe_sampler_view * st_create_texture_sampler_view_from_stobj(struct st_context *st, - struct st_texture_object *stObj, - enum pipe_format format, - unsigned glsl_version) + struct st_texture_object *stObj, + enum pipe_format format, + bool glsl130_or_later) { + /* There is no need to clear this structure (consider CPU overhead). */ struct pipe_sampler_view templ; - unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl_version); + unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl130_or_later); - u_sampler_view_default_template(&templ, stObj->pt, format); + templ.format = format; - if (stObj->pt->target == PIPE_BUFFER) { - unsigned base, size; - - base = stObj->base.BufferOffset; - if (base >= stObj->pt->width0) - return NULL; - size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize); - if (!size) - return NULL; - - templ.u.buf.offset = base; - templ.u.buf.size = size; + if (stObj->level_override >= 0) { + templ.u.tex.first_level = templ.u.tex.last_level = stObj->level_override; } else { templ.u.tex.first_level = stObj->base.MinLevel + stObj->base.BaseLevel; templ.u.tex.last_level = last_level(stObj); - assert(templ.u.tex.first_level <= templ.u.tex.last_level); - if (stObj->layer_override) { - templ.u.tex.first_layer = templ.u.tex.last_layer = stObj->layer_override; - } else { - templ.u.tex.first_layer = stObj->base.MinLayer; - templ.u.tex.last_layer = last_layer(stObj); - } - assert(templ.u.tex.first_layer <= templ.u.tex.last_layer); - templ.target = gl_target_to_pipe(stObj->base.Target); } + if (stObj->layer_override >= 0) { + templ.u.tex.first_layer = templ.u.tex.last_layer = stObj->layer_override; + } else { + templ.u.tex.first_layer = stObj->base.MinLayer; + templ.u.tex.last_layer = last_layer(stObj); + } + assert(templ.u.tex.first_layer <= templ.u.tex.last_layer); + assert(templ.u.tex.first_level <= templ.u.tex.last_level); + templ.target = gl_target_to_pipe(stObj->base.Target); templ.swizzle_r = GET_SWZ(swizzle, 0); templ.swizzle_g = GET_SWZ(swizzle, 1); @@ -453,50 +561,117 @@ struct pipe_sampler_view * st_get_texture_sampler_view_from_stobj(struct st_context *st, struct st_texture_object *stObj, const struct gl_sampler_object *samp, - unsigned glsl_version) + bool glsl130_or_later, + bool ignore_srgb_decode) { - struct pipe_sampler_view **sv; + const struct st_sampler_view *sv; + bool srgb_skip_decode = false; - if (!stObj || !stObj->pt) { - return NULL; - } + if (!ignore_srgb_decode && samp->sRGBDecode == GL_SKIP_DECODE_EXT) + srgb_skip_decode = true; - sv = st_texture_get_sampler_view(st, stObj); + sv = st_texture_get_current_sampler_view(st, stObj); - if (*sv) { + if (sv && + sv->glsl130_or_later == glsl130_or_later && + sv->srgb_skip_decode == srgb_skip_decode) { /* Debug check: make sure that the sampler view's parameters are * what they're supposed to be. */ - MAYBE_UNUSED struct pipe_sampler_view *view = *sv; - assert(!check_sampler_swizzle(st, stObj, view, glsl_version)); - assert(get_sampler_view_format(st, stObj, samp) == view->format); + struct pipe_sampler_view *view = sv->view; + assert(stObj->pt == view->texture); + assert(!check_sampler_swizzle(st, stObj, view, glsl130_or_later)); + assert(get_sampler_view_format(st, stObj, srgb_skip_decode) == view->format); assert(gl_target_to_pipe(stObj->base.Target) == view->target); - if (stObj->base.Target == GL_TEXTURE_BUFFER) { - unsigned base = stObj->base.BufferOffset; - MAYBE_UNUSED unsigned size = MIN2(stObj->pt->width0 - base, - (unsigned) stObj->base.BufferSize); + assert(stObj->level_override >= 0 || + stObj->base.MinLevel + stObj->base.BaseLevel == view->u.tex.first_level); + assert(stObj->level_override >= 0 || last_level(stObj) == view->u.tex.last_level); + assert(stObj->layer_override >= 0 || stObj->base.MinLayer == view->u.tex.first_layer); + assert(stObj->layer_override >= 0 || last_layer(stObj) == view->u.tex.last_layer); + assert(stObj->layer_override < 0 || + (stObj->layer_override == view->u.tex.first_layer && + stObj->layer_override == view->u.tex.last_layer)); + return view; + } + + /* create new sampler view */ + enum pipe_format format = get_sampler_view_format(st, stObj, + srgb_skip_decode); + struct pipe_sampler_view *view = + st_create_texture_sampler_view_from_stobj(st, stObj, format, + glsl130_or_later); + + view = st_texture_set_sampler_view(st, stObj, view, + glsl130_or_later, srgb_skip_decode); + + return view; +} + + +struct pipe_sampler_view * +st_get_buffer_sampler_view_from_stobj(struct st_context *st, + struct st_texture_object *stObj) +{ + const struct st_sampler_view *sv; + struct st_buffer_object *stBuf = + st_buffer_object(stObj->base.BufferObject); + + if (!stBuf || !stBuf->buffer) + return NULL; + + sv = st_texture_get_current_sampler_view(st, stObj); + + struct pipe_resource *buf = stBuf->buffer; + + if (sv) { + struct pipe_sampler_view *view = sv->view; + + if (view->texture == buf) { + /* Debug check: make sure that the sampler view's parameters are + * what they're supposed to be. + */ + assert(st_mesa_format_to_pipe_format(st, + stObj->base._BufferObjectFormat) + == view->format); + assert(view->target == PIPE_BUFFER); + ASSERTED unsigned base = stObj->base.BufferOffset; + ASSERTED unsigned size = MIN2(buf->width0 - base, + (unsigned) stObj->base.BufferSize); assert(view->u.buf.offset == base); assert(view->u.buf.size == size); - } - else { - assert(stObj->base.MinLevel + stObj->base.BaseLevel == - view->u.tex.first_level); - assert(last_level(stObj) == view->u.tex.last_level); - assert(stObj->layer_override || stObj->base.MinLayer == view->u.tex.first_layer); - assert(stObj->layer_override || last_layer(stObj) == view->u.tex.last_layer); - assert(!stObj->layer_override || - (stObj->layer_override == view->u.tex.first_layer && - stObj->layer_override == view->u.tex.last_layer)); + return view; } } - else { - /* create new sampler view */ - enum pipe_format format = get_sampler_view_format(st, stObj, samp); - *sv = st_create_texture_sampler_view_from_stobj(st, stObj, - format, glsl_version); + unsigned base = stObj->base.BufferOffset; - } + if (base >= buf->width0) + return NULL; + + unsigned size = buf->width0 - base; + size = MIN2(size, (unsigned)stObj->base.BufferSize); + if (!size) + return NULL; + + /* Create a new sampler view. There is no need to clear the entire + * structure (consider CPU overhead). + */ + struct pipe_sampler_view templ; + + templ.format = + st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat); + templ.target = PIPE_BUFFER; + templ.swizzle_r = PIPE_SWIZZLE_X; + templ.swizzle_g = PIPE_SWIZZLE_Y; + templ.swizzle_b = PIPE_SWIZZLE_Z; + templ.swizzle_a = PIPE_SWIZZLE_W; + templ.u.buf.offset = base; + templ.u.buf.size = size; + + struct pipe_sampler_view *view = + st->pipe->create_sampler_view(st->pipe, buf, &templ); + + view = st_texture_set_sampler_view(st, stObj, view, false, false); - return *sv; + return view; }